GShell
January 11, 2026 · View on GitHub
English | 简体中文
A REPL tool for Unity:
- Supports Mono (both in the Editor and in the Player)
- Supports IL2CPP (requires integration with HybridCLR)
- Supports direct access to non-public classes, methods, properties, fields, etc., without using reflection
- Supports Unity 2019 and later
For implementation details, see this blog post (In Chinese)
Table of Contents
Feature Examples
> 1 + 2 // Evaluate expression
3
> var x = 2 + 3; // Define a variable
> x // Output previously defined variable
5
> int Add(int a, int b) // Define a function, supports multi-line input
* {
* return a + b;
* }
> Add(3, 1) // Call the previously defined function
4
> Entry.Run_AOTGeneric(); // Call a method in HotUpdate.dll, but the dll isn’t referenced yet
(1,1): error CS0103: The name 'Entry' does not exist in the current context
> #r "HotUpdate.dll" // Reference HotUpdate.dll (you can pre-configure common dlls to avoid doing this every time)
> Entry.Run_AOTGeneric(); // Run_AOTGeneric is a private method and can be called directly
> new Entry.MyVec3() // MyVec3 is a private class and can be accessed directly
[Entry+MyVec3] {
x: 0,
y: 0,
z: 0
}
> using UnityEngine.SceneManagement; // Import a namespace
> SceneManager.GetActiveScene().name // Access a type from the imported namespace
"main"
> var transform = GameObject.Find("LoadDll").transform;
> transform.localPosition = Vector3.zero; // Modify a property
> var list = new List<int>() { 1, 2, 3 }; // Create a List
> list // Output variable value
List<int>(3) {
1,
2,
3
}
> var s = "";
> foreach (var item in list) // Loop, supports multi-line input
* s += item + ",";
> s
"1,2,3,"
> #load "test.cs" // Load and execute the test.cs file in the current directory (demo\Client)
> #reset // Reset the state
> s // Previously declared variables no longer exist
(1,1): error CS0103: The name 's' does not exist in the current context
How to Run the Demo
Run in the Editor
- Open the
demo\Clientproject with Unity. - Start the HTTP Server:
Demo -> Start HTTP Server. - Open the scene:
Scenes\main.unity. - Enter Play Mode.
- Open Shell Launcher:
MODX -> Shell Launcherand selectEditorShellSettings. - Click Launch.
Run in an IL2CPP Build
- Open the
demo\Clientproject with Unity. - Start the HTTP Server:
Demo -> Start HTTP Server. - Install HybridCLR:
HybridCLR -> Installer. - Build the Player:
Build -> Win64. - Run the Player:
demo\Client\Release-Win64\HybridCLRTrial.exe. - Open Shell Launcher:
MODX -> Shell Launcherand selectPlayerShellSettings. - Click Compile Scripts.
- Click Launch.
Use the Web Version of GShell
Using the Editor as an example
- Open the
demo\Clientproject with Unity. - Start the HTTP Server:
Demo -> Start HTTP Server. - Open the scene:
Scenes\main.unity. - Enter Play Mode.
- Modify the config file
demo\GShell.Web\shellsettings.json:- TargetFramework: Set to
netstandard2.0ornetstandard2.1depending on your Unity version. - SearchPaths: Adjust the path according to your local Unity installation.
- TargetFramework: Set to
- Run GShell.Web (choose one of the following):
- Open
demo\GShell.Web\GShell.Web.slnin Visual Studio and press F5 (browser opens automatically). - Run
dotnet run GShell.Web.csprojin thedemo\GShell.Webdirectory, then open http://localhost:5052/ in your browser.
- Open
- Enter
100in the PlayerId field (100 is the default for the demo client). - Click Start.
Integration
Use GShell
The tool communicates externally via HTTP(S). Your server can receive data from GShell, forward it to the target client for execution, and then send the result back to GShell.
Steps:
-
Add the package: com.modx.gshell, e.g., https://github.com/AlanLiu90/GShell.git?path=/src/GShell.UnityClient/Packages/com.modx.gshell#v1.3.1
-
Install GShell:
dotnet tool install --global GShell -
Support communication with GShell:
- The server receives data from GShell (GShell sends JSON via POST to the configured
Execute URL):
class ShellPostData { public string SessionId { get; set; } public int SubmissionId { get; set; } public string EncodedAssembly { get; set; } public string ScriptClassName { get; set; } public Dictionary<string, string> ExtraEncodedAssemblies { get; set; } public Dictionary<string, string> ExtraData { get; set; } }- The server uses data in
ExtraData(fromExtra Data Itemsin the configuration) to determine the target client and forwards theShellPostData. - The client executes the code and sends the result back:
public class ShellResponse { public string Result { get; set; } public bool Success { get; set; } } // Initialization ShellExecutor mExecutor = new ShellExecutor(maximumOutputLength: 2048); // Execute code var shellData = JsonConvert.DeserializeObject<ShellPostData>(text); mExecutor.EnsureObjectFormatterCreated(shellData.ExtraEncodedAssemblies); var (result, success) = await mExecutor.Execute(shellData.SessionId, shellData.SubmissionId, shellData.EncodedAssembly, shellData.ScriptClassName); var shellResponse = new ShellResponse() { Result = (string)result, Success = success }; // Send shellResponse back to the server- The server replies to GShell with
shellResponse. - See the demo implementation in
demo\Client\Assets\HotUpdate\TestShell.csanddemo\HttpServer\HttpServer.cs.
- The server receives data from GShell (GShell sends JSON via POST to the configured
-
Copy
EditorShellSettings.assetandPlayerShellSettings.assetfromdemo\Client\Assets\Editorinto your project and modify:- Command →
gshell - Execute URL → your actual endpoint
- Extra Data Items → adjust according to your project
- Command →
Install GShell as a Local Tool
Installing GShell as a local tool allows you to add the tool’s version information to version control, making it easier to manage.
Steps (using Windows as an example):
- In the Unity project directory (the one containing
Assets), run:
dotnet new tool-manifest
dotnet tool install GShell
- In the same directory, create a file named start_gshell.bat and add the following content:
dotnet tool restore
dotnet tool run gshell %*
- Add .config\dotnet-tools.json to version control.
- In the configuration file, change Command to
start_gshell.bat.
Use GShell.Core
For projects that want to use GShell’s functionality within their own tools, GShell.Core can be integrated.
You can refer to the GShell.Web project, which essentially runs GShell in the browser. The main files:
- demo\GShell.Web\Shell\Shell.cs: Implements a subclass of
ShellBasefrom GShell.Core - demo\GShell.Web\Components\Pages\Terminal.razor: Implements the web terminal’s input and output
Configuration
-
Assembly Compilation Settings
- Used to generate a platform-specific DLL for GShell to reference during compilation.
- When used in the Editor, set the Build Target to No Target.
-
Dynamic Code Compilation Settings
- Assembly Search Paths: List of directories to search for referenced DLLs. Earlier entries have higher priority.
- When used in the Editor, add
Library\ScriptAssemblies. - The tool automatically prepends the output directory for compiled assemblies.
- It automatically appends the directory containing
UnityEngine.CoreModule.dll.
- When used in the Editor, add
- References: DLLs to reference during compilation. Common DLLs:
UnityEngine.CoreModule.dll(mscorlib.dll, System.Core.dll, and other framework DLLs are included automatically)
- Usings: Namespaces automatically imported during compilation. Common namespaces:
SystemSystem.Collections.GenericSystem.LinqUnityEngine
- Source File Search Paths:List of directories to search for source files, used by
#loaddirective. - Script Class Name: When compiling dynamic code, the type name is generated automatically based on it and usually doesn’t need to be modified.
- Assembly Search Paths: List of directories to search for referenced DLLs. Earlier entries have higher priority.
-
Runtime
- Use Mono in the Editor
- Use Mono or IL2CPP in the Player depending on the scripting backend.
-
Command: The command to run GShell.
-
Execute URL: The URL to send compiled code to for execution.
-
Extra Assemblies: Additional assemblies sent by GShell.
GShell.ObjectFormatter.dll: Enables using Roslyn’sCSharpObjectFormatterfor object formatting.
-
Extra Datas: Additional data sent to the
Execute URL, e.g., player ID for routing requests. -
Authentication Settings
- Type:
None: No authenticationBasic: Basic auth (requires username/password)JWT: JSON Web Token (requires token)
- See
demo\HttpServerfor authentication and token generation examples. - When using authentication, HTTPS is recommended.
- Type:
Limitations
Each input in GShell (e.g., an expression, statement, or function definition) is compiled into a separate DLL. HybridCLR supports loading a maximum of 338 DLLs (documentation). This limitation applies only to IL2CPP.