jpskill.com
🛠️ 開発・MCP コミュニティ

linjector-luau-script-ide

Open-source Luau/Lua script IDE and executor built as a Windows Forms C# application with Monaco editor integration

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o linjector-luau-script-ide.zip https://jpskill.com/download/22998.zip && unzip -o linjector-luau-script-ide.zip && rm linjector-luau-script-ide.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/22998.zip -OutFile "$d\linjector-luau-script-ide.zip"; Expand-Archive "$d\linjector-luau-script-ide.zip" -DestinationPath $d -Force; ri "$d\linjector-luau-script-ide.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して linjector-luau-script-ide.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → linjector-luau-script-ide フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1
📖 Claude が読む原文 SKILL.md(中身を展開)

この本文は AI(Claude)が読むための原文(英語または中国語)です。日本語訳は順次追加中。

LInjector Luau Script IDE

Skill by ara.so — Daily 2026 Skills collection.

LInjector is an open-source Luau/Lua script IDE and executor built as a Windows Forms application in C# (.NET Framework 4.8, 32-bit). It features the Monaco editor (the same editor powering VS Code) with Luau syntax highlighting, an optimized multi-tab system, and DLL injection capabilities targeting the Roblox UWP client.

Important Note (2026): The UWP Version is patched due to Hyperion/Byfron anti-cheat. You can still build, modify, and extend LInjector by providing your own working DLL or injection method.


Project Structure

LInjector/
├── LInjector.sln              # Visual Studio solution
├── LInjector/
│   ├── LInjector.csproj       # Project file (.NET 4.8, x86)
│   ├── Forms/                 # Windows Forms UI
│   │   ├── MainForm.cs        # Main application window
│   │   └── *.cs               # Other form files
│   ├── Classes/               # Core logic classes
│   │   ├── Injector.cs        # DLL injection logic
│   │   ├── TabSystem.cs       # Optimized tab management
│   │   └── *.cs
│   ├── Monaco/                # Monaco editor web assets
│   │   ├── index.html         # Editor host page
│   │   └── *.js               # Monaco JS files
│   └── Resources/             # Embedded resources

Build Requirements

  • Visual Studio 2022
  • .NET Framework 4.8 SDK
  • Target Platform: x86 (32-bit)
  • Configuration: Release

How to Build

# 1. Clone the repository
git clone https://github.com/WeritoP/LInjector-FORKED-
cd LInjector-FORKED-

# 2. Open in Visual Studio 2022
start LInjector.sln

# 3. Set build configuration in VS:
#    Configuration: Release
#    Platform: x86

# 4. Build via keyboard shortcut
# CTRL + SHIFT + B

# OR via CLI with MSBuild
msbuild LInjector.sln /p:Configuration=Release /p:Platform=x86

Important: Always compile before editing Forms. If you open a Form before compiling, Visual Studio's designer will fail. If this happens, restart Visual Studio.


Monaco Editor Integration

LInjector embeds Monaco in a WebBrowser or WebView2 control. The editor is hosted in a local HTML file.

Accessing the Monaco Editor from C

// In your Form class — get script content from Monaco
private string GetEditorContent()
{
    // Execute JavaScript to retrieve editor value
    object result = webBrowser.Document.InvokeScript(
        "eval",
        new object[] { "monaco.editor.getModels()[0].getValue()" }
    );
    return result?.ToString() ?? string.Empty;
}

// Set content in Monaco editor
private void SetEditorContent(string script)
{
    string escaped = script
        .Replace("\\", "\\\\")
        .Replace("'", "\\'")
        .Replace("\n", "\\n")
        .Replace("\r", "\\r");

    webBrowser.Document.InvokeScript(
        "eval",
        new object[] { $"monaco.editor.getModels()[0].setValue('{escaped}')" }
    );
}

Monaco Editor Host HTML (Monaco/index.html pattern)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
        html, body, #container {
            width: 100%; height: 100%;
            margin: 0; padding: 0;
            overflow: hidden;
            background: #1e1e1e;
        }
    </style>
</head>
<body>
    <div id="container"></div>
    <script src="monaco/min/vs/loader.js"></script>
    <script>
        require.config({ paths: { 'vs': 'monaco/min/vs' } });
        require(['vs/editor/editor.main'], function () {
            window.editor = monaco.editor.create(
                document.getElementById('container'), {
                    value: '-- LInjector Script\n',
                    language: 'lua',
                    theme: 'vs-dark',
                    fontSize: 14,
                    automaticLayout: true,
                    minimap: { enabled: false },
                    scrollBeyondLastLine: false
                }
            );
        });

        // Helper functions callable from C#
        function getScript() {
            return window.editor.getValue();
        }
        function setScript(val) {
            window.editor.setValue(val);
        }
        function clearScript() {
            window.editor.setValue('');
        }
    </script>
</body>
</html>

Tab System

LInjector's tab system is optimized to cap RAM usage at ~1 GB even with 40+ tabs open.

// TabSystem.cs — Example pattern for managing script tabs
public class ScriptTab
{
    public string Name { get; set; }
    public string Content { get; set; }
    public TabPage TabPage { get; set; }

    public ScriptTab(string name, string content = "")
    {
        Name = name;
        Content = content;
    }
}

public class TabManager
{
    private readonly List<ScriptTab> _tabs = new List<ScriptTab>();
    private readonly TabControl _tabControl;
    private int _activeIndex = 0;

    public TabManager(TabControl tabControl)
    {
        _tabControl = tabControl;
    }

    // Add a new script tab
    public void AddTab(string name = null)
    {
        int tabNumber = _tabs.Count + 1;
        string tabName = name ?? $"Script {tabNumber}";

        var tab = new ScriptTab(tabName);
        var tabPage = new TabPage(tabName);

        tab.TabPage = tabPage;
        _tabs.Add(tab);
        _tabControl.TabPages.Add(tabPage);
        _tabControl.SelectedTab = tabPage;
    }

    // Remove tab by index
    public void RemoveTab(int index)
    {
        if (index < 0 || index >= _tabs.Count) return;
        _tabControl.TabPages.Remove(_tabs[index].TabPage);
        _tabs.RemoveAt(index);
    }

    // Save current tab content before switching
    public void SaveCurrentTabContent(string content)
    {
        if (_activeIndex >= 0 && _activeIndex < _tabs.Count)
            _tabs[_activeIndex].Content = content;
    }

    // Get content for a tab
    public string GetTabContent(int index)
    {
        if (index < 0 || index >= _tabs.Count) return string.Empty;
        return _tabs[index].Content;
    }
}

DLL Injection (Custom Integration)

Since the original injection target is patched, here is the pattern used to plug in your own DLL:

// Classes/Injector.cs — Pattern for DLL injection
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;

public class Injector
{
    [DllImport("kernel32.dll")]
    private static extern IntPtr OpenProcess(int access, bool inherit, int processId);

    [DllImport("kernel32.dll")]
    private static extern IntPtr VirtualAllocEx(
        IntPtr hProcess, IntPtr lpAddress,
        uint dwSize, uint flAllocationType, uint flProtect);

    [DllImport("kernel32.dll")]
    private static extern bool WriteProcessMemory(
        IntPtr hProcess, IntPtr lpBaseAddress,
        byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);

    [DllImport("kernel32.dll")]
    private static extern IntPtr CreateRemoteThread(
        IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize,
        IntPtr lpStartAddress, IntPtr lpParameter,
        uint dwCreationFlags, IntPtr lpThreadId);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    private const int PROCESS_ALL_ACCESS = 0x1F0FFF;
    private const uint MEM_COMMIT = 0x1000;
    private const uint MEM_RESERVE = 0x2000;
    private const uint PAGE_READWRITE = 0x04;

    /// <summary>
    /// Inject a DLL into a target process by name.
    /// Returns true on success.
    /// </summary>
    public static bool InjectDll(string processName, string dllPath)
    {
        if (!File.Exists(dllPath))
            throw new FileNotFoundException($"DLL not found: {dllPath}");

        Process[] procs = Process.GetProcessesByName(processName);
        if (procs.Length == 0)
            throw new Exception($"Process '{processName}' not found.");

        Process target = procs[0];
        IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, target.Id);
        if (hProcess == IntPtr.Zero)
            throw new Exception("Failed to open process.");

        byte[] dllBytes = System.Text.Encoding.ASCII.GetBytes(dllPath + "\0");
        IntPtr allocMem = VirtualAllocEx(
            hProcess, IntPtr.Zero, (uint)dllBytes.Length,
            MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

        if (allocMem == IntPtr.Zero)
            throw new Exception("Memory allocation failed.");

        WriteProcessMemory(hProcess, allocMem, dllBytes,
            (uint)dllBytes.Length, out _);

        IntPtr loadLibAddr = GetProcAddress(
            GetModuleHandle("kernel32.dll"), "LoadLibraryA");

        IntPtr thread = CreateRemoteThread(
            hProcess, IntPtr.Zero, 0,
            loadLibAddr, allocMem, 0, IntPtr.Zero);

        return thread != IntPtr.Zero;
    }
}

Using the Injector from UI

// In MainForm.cs — Inject button click handler
private async void btnInject_Click(object sender, EventArgs e)
{
    string dllPath = Path.Combine(
        Application.StartupPath, "Modules", "your_dll.dll");

    try
    {
        bool success = await Task.Run(() =>
            Injector.InjectDll("RobloxPlayerBeta", dllPath));

        lblStatus.Text = success
            ? "✔ Injected successfully"
            : "✘ Injection failed";
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Error: {ex.Message}", "LInjector",
            MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

Script Execution Pattern

// Execute the current script via the injected DLL's named pipe or HTTP endpoint
private async void btnExecute_Click(object sender, EventArgs e)
{
    string script = GetEditorContent();
    if (string.IsNullOrWhiteSpace(script)) return;

    try
    {
        await ExecuteScriptAsync(script);
        lblStatus.Text = "Script executed.";
    }
    catch (Exception ex)
    {
        lblStatus.Text = $"Error: {ex.Message}";
    }
}

private async Task ExecuteScriptAsync(string script)
{
    // Example: communicate with injected DLL via named pipe
    using var pipe = new System.IO.Pipes.NamedPipeClientStream(
        ".", "LInjectorPipe",
        System.IO.Pipes.PipeDirection.Out);

    await pipe.ConnectAsync(timeoutMilliseconds: 3000);

    byte[] data = System.Text.Encoding.UTF8.GetBytes(script);
    await pipe.WriteAsync(data, 0, data.Length);
}

Script File Management

// Save script to file
private void SaveScript(string content, string filePath = null)
{
    if (filePath == null)
    {
        using var sfd = new SaveFileDialog
        {
            Filter = "Lua Files (*.lua)|*.lua|Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
            DefaultExt = "lua",
            FileName = "script"
        };
        if (sfd.ShowDialog() != DialogResult.OK) return;
        filePath = sfd.FileName;
    }
    File.WriteAllText(filePath, content, System.Text.Encoding.UTF8);
}

// Load script from file
private string LoadScript()
{
    using var ofd = new OpenFileDialog
    {
        Filter = "Lua Files (*.lua)|*.lua|Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
    };
    if (ofd.ShowDialog() != DialogResult.OK) return null;
    return File.ReadAllText(ofd.FileName, System.Text.Encoding.UTF8);
}

Configuration Pattern

LInjector uses app settings for persistent configuration:

// Reading/writing settings (App.config / user settings)
// In Settings.settings, add keys: Theme, FontSize, AutoInject

// Read
string theme = Properties.Settings.Default.Theme ?? "vs-dark";
int fontSize = Properties.Settings.Default.FontSize > 0
    ? Properties.Settings.Default.FontSize : 14;

// Write and save
Properties.Settings.Default.Theme = "vs-dark";
Properties.Settings.Default.FontSize = 16;
Properties.Settings.Default.Save();

// Apply theme to Monaco from C#
private void ApplyEditorTheme(string theme)
{
    webBrowser.Document.InvokeScript(
        "eval",
        new object[] { $"monaco.editor.setTheme('{theme}')" }
    );
}

Common Customization Patterns

Change Target Process

// Replace "RobloxPlayerBeta" with your target process name
private const string TARGET_PROCESS = "RobloxPlayerBeta";
// or for UWP:
// private const string TARGET_PROCESS = "Windows10Universal";

Add Custom Luau Autocomplete to Monaco

// In Monaco/index.html — register Luau-specific completions
monaco.languages.registerCompletionItemProvider('lua', {
    provideCompletionItems: function(model, position) {
        return {
            suggestions: [
                {
                    label: 'game',
                    kind: monaco.languages.CompletionItemKind.Variable,
                    insertText: 'game',
                    documentation: 'The root DataModel instance'
                },
                {
                    label: 'workspace',
                    kind: monaco.languages.CompletionItemKind.Variable,
                    insertText: 'workspace',
                    documentation: 'Alias for game.Workspace'
                },
                {
                    label: 'loadstring',
                    kind: monaco.languages.CompletionItemKind.Function,
                    insertText: 'loadstring(${1:source})()',
                    insertTextRules:
                        monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
                    documentation: 'Load and execute a string as Lua code'
                }
            ]
        };
    }
});

Troubleshooting

Problem Cause Fix
Forms designer blank/broken Compiled before opening form Compile first (CTRL+SHIFT+B), then restart VS
msbuild not found MSBuild not in PATH Use VS Developer Command Prompt
Injection returns false Process not found or access denied Run as Administrator; verify process name
Monaco editor blank WebBrowser control needs IE11 emulation Add registry key for IE emulation (see below)
DLL not found error DLL missing from Modules/ folder Place your DLL in the output Modules/ directory

Fix Monaco Blank in WebBrowser Control

Add this to your app startup (requires running as admin once, or via installer):

// Force IE11 rendering mode for WebBrowser control
private static void SetWebBrowserEmulation()
{
    string appName = Path.GetFileName(Application.ExecutablePath);
    using var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
        @"SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION",
        writable: true);
    key?.SetValue(appName, 11001, Microsoft.Win32.RegistryValueKind.DWord);
}
// Call SetWebBrowserEmulation() in Program.cs before Application.Run()

Verify Target Process is Running

public static bool IsProcessRunning(string name)
    => Process.GetProcessesByName(name).Length > 0;

// Usage
if (!IsProcessRunning("RobloxPlayerBeta"))
{
    MessageBox.Show("Please launch Roblox before injecting.",
        "LInjector", MessageBoxButtons.OK, MessageBoxIcon.Warning);
    return;
}

Key Facts

  • Language: C# / .NET Framework 4.8
  • Platform: Windows, x86 (32-bit) only
  • Editor: Monaco (VS Code engine) with Lua/Luau syntax
  • Injection speed: ~300ms (when working)
  • Tab RAM cap: ~1 GB for 40+ tabs
  • License: MIT
  • Status (2026): UWP target patched by Hyperion; source remains functional for custom DLL targets