CSharp Console

August 23, 2026 · View on GitHub

CSharp Console

Interactive C# REPL for Unity — powered by Roslyn

License Unity Claude Code Codex UPM

Execute C# code on the fly in Unity Editor & Runtime — no compilation wait, no boilerplate,
full access to your project's live state. Editor zero-config, Runtime just works with HybridCLR.

Features · Installation · Quick Start · REPL Usage · Extending Commands

English | 中文


✦ Features

Core Capabilities

FeatureDescription
>_Interactive REPLRoslyn-based script submissions with persistent session state — variables, using directives, and types survive across executions
#Top-level SyntaxWrite statements directly. No class, no Main, no boilerplate
@Command FrameworkExtensible [CommandAction] commands with automatic JSON-to-parameter binding (positional & named args), /batch endpoint for multi-command workflows
TabSemantic CompletionReal-time member, namespace, and type completions directly from Roslyn
🔓Private Member AccessBypass private / protected / internal access modifiers at compile time for deep inspection
Debug While PausedSubmit code while the Editor is paused in Play Mode — inspect transient state captured at the exact frame, without losing the snapshot
📡Remote ExecutionCompile in the Editor, execute on a connected Player build (IL2CPP via HybridCLR)

How It Looks

Live theme preview — browse candidates with ↑ / ↓

/theme

Fuzzy semantic completion — type only the significant characters

GameObject.fnd  →  GameObject.Find

Private member access — inspect accessibility before accepting

cam.mid  →  cam.m_InstanceID

Stateful submissions — reuse live Unity values in later expressions

var m = cam.transform.localToWorldMatrix
m.mp34  →  m.MultiplyPoint3x4

Command expressions — inspect Editor state directly

@editor.status()

⚙ Installation

Add via Packages/manifest.json:

{
  "dependencies": {
    "com.zh1zh1.csharpconsole": "https://github.com/niqibiao/unity-csharpconsole.git"
  }
}

Or reference as a local package:

{
  "dependencies": {
    "com.zh1zh1.csharpconsole": "file:../com.zh1zh1.csharpconsole"
  }
}

Note: Both assembly definitions have autoReferenced: false. If your code needs to reference this package, add Zh1Zh1.CSharpConsole.Runtime (or .Editor) to your asmdef's references explicitly.

▶ Quick Start

Editor — Zero Configuration

Import the package and it just works. The Editor-side HTTP service starts automatically via [InitializeOnLoadMethod] — no initialization code, no settings to tweak, no manual setup. Open the REPL from the Unity menu:

Menu ItemTarget
Console > C#ConsoleLocal Editor
Console > RemoteC#ConsoleRemote Editor / Player

Runtime — One Line, No Extra Setup

Enable the remote console on a Player build with a single call:

#if DEVELOPMENT_BUILD
Zh1Zh1.CSharpConsole.RuntimeInitializer.ConsoleInitialize();
#endif

Runtime execution only depends on HybridCLR's Assembly.Load capability for IL2CPP (no additional configuration needed).

The runtime assembly is gated by DEVELOPMENT_BUILD || UNITY_EDITOR.

Port
Editor14500 (default)
Runtime15500 (default)

If a port is occupied, the service automatically advances to the next available one.

Warning

The service binds all network interfaces and has no authentication, by design: it targets trusted LANs where reaching a teammate's Editor or a device build is a feature. Anyone who can reach the port can execute C# in your Editor — do not expose it to untrusted networks.

⌨ REPL Usage

Starting the REPL

The recommended way is through the Unity menu. You can also launch directly:

# Auto-discover running Unity Editors
python "Editor/ExternalTool~/console-client/csharp_repl.py"

# Connect to a specific Editor
python "Editor/ExternalTool~/console-client/csharp_repl.py" --editor --ip 127.0.0.1 --port 14500

# Connect to a Runtime Player (with Editor as compile server)
python "Editor/ExternalTool~/console-client/csharp_repl.py" \
  --mode runtime --ip 127.0.0.1 --port 15500 \
  --compile-ip 127.0.0.1 --compile-port 14500

Python 3.7+ is required. Python dependencies (requests, prompt_toolkit, Pygments) are installed automatically on first launch.

Remote Runtime — Optional Settings

When connecting to a Runtime Player via Console > RemoteC#Console, two optional settings are available to improve compilation accuracy:

SettingDescription
Runtime Dll PathDirectory containing the player's compiled assemblies. The compiler uses these DLLs instead of Editor assemblies to resolve types, ensuring the compiled code matches what the player actually has. Recommended path: Library/Bee/PlayerScriptAssemblies (populated after a player build).
Runtime Defines FileA .txt file listing preprocessor defines that match the player's build configuration, ensuring #if directives evaluate the same way as in the player. Supports one define per line or semicolon-separated (e.g. UNITY_ANDROID;IL2CPP;DEVELOPMENT_BUILD).

Both settings are persisted in EditorPrefs and only apply when Remote Is Editor is unchecked. Leave them empty to use defaults (Editor assemblies and defines).

Key Bindings

KeyAction
EnterSubmit input
Ctrl+EnterInsert newline without submitting
TabAccept completion candidate
Ctrl+RReverse history search
Ctrl+CCopy selection; otherwise clear input (confirm quit if empty)

Completion activates automatically as you type. The toolbar shows semantic completion status: on / off .

Built-in Commands

CommandDescription
/completion <0|1>Toggle semantic completion
/theme [name]List or switch code-highlighting themes
/usingShow default using file path
/defineShow preprocessor defines file path
/reloadReload using / define files
/resetReset the REPL session
/clearClear the terminal
/dofile <path>Execute a local .cs file

Command Expressions

The REPL supports @-prefixed command expressions that invoke the server-side command framework directly — bypassing Roslyn compilation:

@project.scene.open(scenePath: "Assets/Scenes/SampleScene.unity", mode: "single")
@editor.status()
@session.inspect(sessionId: "session-1")

Tab completion works for both command names and argument names.

📋 Built-in Actions

62 built-in commands across 15 namespaces, covering editor control, scene manipulation, asset management, and more.

NamespaceActionDescription
gameobjectfindFind GameObjects by name, tag, or component type
createCreate a new GameObject (empty or primitive)
destroyDestroy a GameObject
getGet detailed GameObject, transform, component, and static-state info
modifyChange name, tag, layer, active state, or static flag
set_parentReparent a GameObject
duplicateDuplicate a GameObject
componentaddAdd a component to a GameObject
removeRemove a component from a GameObject
getGet serialized field data of a component
modifyModify serialized fields of a component
transformsetSet position, rotation, and/or scale (local or world)
scenehierarchyGet the full scene hierarchy tree, optionally with component info
prefabcreateCreate a prefab asset from a scene GameObject
instantiateInstantiate a prefab into the active scene
unpackUnpack a prefab instance
asset_hierarchyGet the hierarchy tree of a prefab asset
asset_getGet detailed info about a GameObject in a prefab asset
asset_get_componentGet serialized properties of a component in a prefab asset
asset_modify_componentModify serialized fields of a component in a prefab asset
asset_add_componentAdd a component to a GameObject in a prefab asset
asset_remove_componentRemove a component from a GameObject in a prefab asset
asset_modify_gameobjectModify a GameObject's properties in a prefab asset
asset_add_gameobjectAdd a child GameObject to a prefab asset
asset_remove_gameobjectRemove a child GameObject from a prefab asset
materialcreateCreate a new material asset with a specified shader
getGet material properties from an asset or a Renderer
assignAssign a material to a Renderer component
scriptableobjectcreateCreate a ScriptableObject asset of a given type
getGet serialized field data of a ScriptableObject asset
modifyModify serialized fields of a ScriptableObject asset
screenshotscene_viewCapture the Scene View to an image file
game_viewCapture the Game View to an image file
profilerstartStart Profiler recording (optional deep profiling)
stopStop Profiler recording
statusGet current Profiler state
saveSave recorded profiler data to a .raw file
editorstatusGet editor, play-mode, and transition state
playmode.enterEnter play mode
playmode.exitExit play mode
console.clearClear the editor console
console.markWrite a searchable marker into the editor log and return the log file path
test.runStart a Unity Test Framework run (EditMode or PlayMode)
test.statusGet the state and results of the latest test run
projectscene.listList all scenes in the project
scene.openOpen a scene by path
scene.saveSave the current scene
selection.getGet the current editor selection
selection.setSet the editor selection
asset.listList assets by type filter
asset.importImport an asset by path
asset.reimportReimport an asset by path
assetmoveMove or rename an asset
copyCopy an asset to a new path
deleteDelete one or more assets
create_folderCreate a folder in the Asset Database
sessionlistList active REPL sessions
inspectInspect a session's state
resetReset a session's compiler and executor
commandlistList all registered commands (built-in + custom)
registry.snapshotGet the command registry snapshot
runtimeinfoReport the responding process's device facts and well-known file paths

39 actions need the editor and say so when a player receives them. The other 23 also answer in a player: runtime/info, scene/hierarchy, gameobject/*, transform/set, component/*, screenshot/game_view, profiler/start|stop|status, session/* and command/*. A player has no undo stack, so mutations made there cannot be reversed, and component/get|modify only covers components the project declares — built-in components keep their state in native properties rather than serialized fields.

prefab/asset_* edit the asset on disk without opening a scene. They address children by the identity selector returned from asset_hierarchy (gid:<guid>:<localFileId>), not by name path.

editor/test.* require com.unity.test-framework in the consuming project; without it they stay registered but return an explanatory error.

🔌 Extending Commands

The command framework lets any project add custom commands without modifying the package source — declare a [CommandAction] method and the framework handles discovery, parameter binding, and routing automatically.

See the full guide: Extending Commands

📦 Requirements

DependencyVersion
Unity2022.3+
Python3.7+ (on system PATH)
Windows TerminalOptional (falls back to Python directly)
  • unity-cli-plugin — Non-interactive CLI for the same HTTP service, designed for scripting and automation workflows.
  • python-prompt-toolkit — Terminal UI library powering the REPL's interactive interface.
  • HybridCLR — IL2CPP hot-reload solution enabling Assembly.Load in Runtime mode.

📄 Third-Party Notices

This package bundles Roslyn compiler assemblies and dnlib under Editor/Plugins/. See ThirdPartyNotices.md for full attribution and license details.

📜 License

Apache License 2.0