以下为本文档的中文说明
CLI Anything sbox 是 HKUDS 开发的一项面向 s&box 游戏引擎(Facepunch Studios 出品,基于 Source 2 引擎)的原生命令行工具技能。该技能提供了超过 79 条命令,分布在 14 个功能组中,能够直接操作项目中的 .scene(场景文件)、.prefab(预制体文件)、.vmat(材质文件)、.sound(声音文件)、Input.config(输入配置)、Collision.config(碰撞配置)等 JSON 格式文件,也能生成符合 C# 语言习惯的游戏组件代码,并在项目上运行实时的资源图查询。该技能的工作方式非常独特——大部分命令直接在项目的 JSON 文件上操作,无需启动 s&box 编辑器本身即可完成配置修改,这大大提升了模组开发的工作效率。该技能适用于 s&box 游戏模组开发的全流程,包括项目管理、场景和预制体编辑、材质与声音配置、本地化设置、C# 代码生成、资源依赖关系查询、项目验证以及一键启动编辑器。其核心特点包括:丰富的命令覆盖游戏开发的各个方面、基于 Python 实现易于安装部署、以及不依赖编辑器即可完成大量配置工作的离线操作能力。
s&box CLI
Agent-native CLI for the s&box game engine (Facepunch Studios, Source 2). 79+ commands across 14 groups. Manipulate.scene,.prefab,.vmat,.sound,Input.config,Collision.configJSON files directly, generate idiomatic C# components, and run a real-time asset graph over the project.
Installation
pipinstallgit+https://github.com/HKUDS/CLI-Anything.git#subdirectory=sbox/agent-harnessRequirements
- Python 3.10+
- s&box installed via Steam - auto-detected, or set
SBOX_PATHto a custom installation directory. - Most commands work entirely on the project’s JSON files - s&box does not need to be running.
Global Options
--json Machine-readable JSON output (always pass for agent use) --project PATH Project directory (auto-detects from cwd .sbproj if omitted)Command Groups
project - Manage s&box projects
cli-anything-sbox project new--nameMyGame --output-dir ./MyGame cli-anything-sbox--jsonproject info cli-anything-sbox project config --max-players32--tick-rate64cli-anything-sbox--json--project./MyGame project add-package facepunch.libsdf cli-anything-sbox--json--project./MyGame project remove-package facepunch.libsdf# Lint: broken asset refs, duplicate GUIDs, malformed Input.configcli-anything-sbox--json--project./MyGame project validate cli-anything-sbox--project./MyGame project validate --no-inputs --no-guidsscene - Manipulate.scenefiles
cli-anything-sbox scene new--namegameplay-o./Assets/scenes/gameplay.scene cli-anything-sbox--jsonscene info ./scene.scene cli-anything-sbox--jsonscene list ./scene.scene cli-anything-sbox scene add-object ./scene.scene Enemy--position"100,0,0"--components"model,box_collider,rigidbody"--tags"enemy"cli-anything-sbox scene remove-object ./scene.scene--nameEnemy cli-anything-sbox scene add-component ./scene.scene<object-guid>Sandbox.PointLight cli-anything-sbox scene remove-component ./scene.scene<object-guid>--component-type Sandbox.Rigidbody cli-anything-sbox--jsonscene modify-object ./scene.scene--guid<guid>--nameNewName--position"200,0,0"cli-anything-sbox--jsonscene clone-object ./scene.scene--nameEnemy --new-name EnemyCopy--position"300,0,0"cli-anything-sbox--jsonscene get-object ./scene.scene--nameSun cli-anything-sbox scene set-property ./scene.scene --fixed-update-freq64--timescale0.5cli-anything-sbox scene set-navmesh ./scene.scene--enabled--agent-height72--agent-radius16cli-anything-sbox--jsonscene list-presets cli-anything-sbox--jsonscene modify-component ./scene.scene<object-guid><component-guid>--properties'{"Damage":50}'# Find objects matching one or more filters (AND-combined)cli-anything-sbox--jsonscene query ./scene.scene --has-component rigidbody --has-tag tower cli-anything-sbox--jsonscene query ./scene.scene --name-regex"^Tower\\d$"--in-bounds"0,-500,-50,1000,500,50"# Extract every asset reference (.vmdl, .vmat, .vsnd, .vtex, .vpcf, .prefab) from a scenecli-anything-sbox--jsonscene refs ./scene.scene# Apply the same modification to every object that matches a querycli-anything-sbox--jsonscene bulk-modify ./scene.scene --has-tag tower--position"0,0,100"--enable# Structural diff between two scenes (added/removed/modified GameObjects + SceneProperties)cli-anything-sbox--jsonscenediff./old.scene ./new.scene# Insert a prefab as a GameObject in a scenecli-anything-sbox--jsonscene instantiate-prefab ./level.scene ./Assets/prefabs/bullet.prefab--position"10,0,0"prefab - Manage.prefabfiles
cli-anything-sbox prefab new--nameBullet-o./Assets/prefabs/bullet.prefab--components"model,sphere_collider,rigidbody"cli-anything-sbox--jsonprefab info ./Assets/prefabs/bullet.prefab cli-anything-sbox prefab from-scene ./scene.scene<object-guid>-o./Assets/prefabs/extracted.prefab cli-anything-sbox--jsonprefab add-component ./prefab.prefab rigidbody cli-anything-sbox prefab remove-component ./prefab.prefab --component-type Sandbox.Rigidb ody cli-anything-sbox--jsonprefab list# Asset references inside a prefabcli-anything-sbox--jsonprefab refs ./prefab.prefab# Modify component properties on a prefab (by component type or component GUID)cli-anything-sbox--jsonprefab modify-component ./prefab.prefab --component-type Sandbox.Rigidbody--properties'{"Gravity":false,"MassOverride":50}'# Structural diff between two prefabs (root + named children)cli-anything-sbox--jsonprefabdiff./old.prefab ./new.prefabcodegen - Generate C# code
# Plain Componentcli-anything-sbox codegen component--namePlayerController--methodsOnUpdate,OnFixedUpdate-o./Code/PlayerController.cs# Component with [Property] fieldscli-anything-sbox--jsoncodegen component--nameTower--properties'[{"name":"Damage","type":"float","default":"25f"},{"name":"Range","type":"float","default":"500f"}]'# Networked component (partial class) with RPC method stubscli-anything-sbox codegen component--nameNetPlayer--networked--methodsOnUpdate,OnFixedUpdate --rpc-methods"Fire:Broadcast,TakeDamage:Host"-o./Code/NetPlayer.cs# GameResourcecli-anything-sbox codegen gameresource--nameTowerData --display-name"Tower Data"--extensiontower-o./Code/TowerData.cs# Editor menu (Editor/ assembly)cli-anything-sbox codegen editor-menu--nameMyTools --menu-path"Editor/My Tools/Open"-o./Editor/MyTools.cs# Plain Razor UI component (.razor + .razor.scss)cli-anything-sbox codegen razor--nameHudPanel--properties'[{"name":"Score","type":"int","default":"0"}]'-o./UI/HudPanel.razor# Static or base-derived classcli-anything-sbox codegen class--nameMath2--static-o./Code/Math2.cs# PanelComponent + sibling ScreenPanel scaffold (handles the s&box quirk where# PanelComponent input only works when both are on the same GameObject).# Emits .razor + .razor.scss + a paste-ready GameObject snippet, or appends# directly to a scene with --scene.cli-anything-sbox--jsoncodegen panel-component--nameHudBar-o./UI/HudBar.razor cli-anything-sbox codegen panel-component--nameCrosshair-o./UI/Crosshair.razor--scene./Assets/scenes/game.sceneinput - ManageInput.config
cli-anything-sbox--jsoninput list cli-anything-sbox inputadd--namePlaceTower--groupGameplay--keyboardmouse1--gamepadRightTrigger cli-anything-sbox input remove--namePlaceTower cli-anything-sbox inputset--nameAttack1--keyboardmouse1collision - ManageCollision.config
cli-anything-sbox--jsoncollision list cli-anything-sbox collision add-layer--nameprojectile--defaultCollide cli-anything-sbox collision add-rule --layer-a projectile --layer-b solid--resultCollide cli-anything-sbox collision remove-rule --layer-a projectile --layer-b solid cli-anything-sbox collision remove-layer--nameprojectilematerial - Manage.vmatmaterials
cli-anything-sbox--jsonmaterial new--namefloor--shadercomplex --color-texture"textures/floor.tga"--metalness0.3-o./Assets/materials/floor.vmat cli-anything-sbox--jsonmaterial info ./Assets/materials/floor.vmat cli-anything-sbox--jsonmaterial list cli-anything-sbox--jsonmaterialset./Assets/materials/floor.vmat--metalness0.8sound - Manage.soundevents
cli-anything-sbox--jsonsound new--namegunshot--sounds"sounds/gun1.vsnd,sounds/gun2.vsnd"--volume0.8-o./Assets/sounds/gunshot.sound cli-anything-sbox--jsonsound info ./Assets/sounds/gunshot.sound cli-anything-sbox--jsonsound list cli-anything-sbox--jsonsoundset./Assets/sounds/gunshot.sound--volume0.5localization - Manage translations
cli-anything-sbox localization new--langen-o./Localization/en.json cli-anything-sbox localizationset./Localization/en.json--key"game.title"--value"My Game"cli-anything-sbox--jsonlocalization list ./Localization/en.json cli-anything-sbox localization get ./Localization/en.json--key"game.title"cli-anything-sbox localization remove ./Localization/en.json--key"game.title"cli-anything-sbox localization bulk-se t ./Localization/en.json--keys'{"ui.start":"Start","ui.quit":"Quit"}'server - Dedicated server
cli-anything-sbox server info cli-anything-sbox server start--gamemy_game--mapfacepunch.flatgrassasset - Asset management & reverse lookups
cli-anything-sbox--jsonasset list--typescene cli-anything-sbox--jsonasset info ./Assets/scenes/minimal.scene cli-anything-sbox asset compile ./Assets/materials/floor.vmat# Which scenes/prefabs reference this asset?cli-anything-sbox--json--project./MyGame asset find-refs models/myteam/widget.vmdl# Find unreferenced assets (per type, or across all referenceable types)cli-anything-sbox--json--project./MyGame asset find-unused cli-anything-sbox--json--project./MyGame asset find-unused--typemodel--typematerial# Rename an asset and update every scene/prefab reference (extension preserved if omitted)cli-anything-sbox--json--project./MyGame assetrenamemodels/team/widget.vmdl gizmo cli-anything-sbox--project./MyGame assetrenamemodels/team/widget.vmdl gizmo --dry-run# Move an asset across directories and update every referencecli-anything-sbox--json--project./MyGame asset move models/team/widget.vmdl models/shared/widget.vmdlsession - State management
cli-anything-sbox session status cli-anything-sbox session undo cli-anything-sbox session redotest - Automated map/scene generation harness
cli-anything-sboxtestsetup cli-anything-sbox--jsontestrunlaunch - Open project in s&box editor
cli-anything-sbox launchComponent Presets
29 short names usable with--componentsonscene add-object,prefab new, etc. Each maps to aSandbox.*component type.
| Preset | Component Type |
|---|---|
model | Sandbox.ModelRenderer |
box_collider | Sandbox.BoxCollider |
sphere_collider | Sandbox.SphereCollider |
capsule_collider | Sandbox.CapsuleCollider |
plane_collider | Sandbox.PlaneCollider |
model_collider | Sandbox.ModelCollider |
rigidbody | Sandbox.Rigidbody |
character_controller | Sandbox.CharacterController |
player_controller | Sandbox.PlayerController |
camera | Sandbox.CameraComponent |
light_directional | Sandbox.DirectionalLight |
light_point | Sandbox.PointLight |
spot_light | Sandbox.SpotLight |
ambient_light | Sandbox.AmbientLight |
sprite_renderer | Sandbox.SpriteRenderer |
skinned_model_renderer | Sandbox.SkinnedModelRenderer |
text_renderer | Sandbox.TextRenderer |
line_renderer | Sandbox.LineRenderer |
decal_renderer | Sandbox.DecalRenderer |
trail_renderer | Sandbox.TrailRenderer |
particle_effect | Sandbox.ParticleEffect |
sound_point | Sandbox.SoundPointComponent |
nav_mesh_agent | Sandbox.NavMeshAgent |
screen_panel | Sandbox.ScreenPanel |
world_panel | Sandbox.WorldPanel |
fixed_joint | Sandbox.FixedJoint |
hinge_joint | Sandbox.HingeJoint |
spring_joint | Sandbox.SpringJoint |
ball_socket_joint | Sandbox.BallSocketJoint |
scene list-presetsreturns the live preset registry as JSON.
Agent Usage Pattern
Pass--jsonfor every agent-driven invocation. Pipe throughjqto thread GUIDs and paths between commands:
# Bootstrap a projectsbproj=$(cli-anything-sbox--jsonproject new--nameMyGame --output-dir /tmp/MyGame|jq-r'.sbproj')cd/tmp/MyGame# Add a tower with a specific component layout, capture its GUIDguid=$(cli-anything-sbox--jsonscene add-object ./Assets/scenes/main.scene Tower\\--components"model,box_collider,rigidbody"--tags"tower"\\|jq-r'.guid')# Generate the corresponding C# component, networkedcli-anything-sbox--jsoncodegen component--nameTower--networked\\--rpc-methods"Fire:Host"--properties'[{"name":"Damage","type":"float","default":"25f"}]'\\-o./Code/Tower.cs# Bulk-tweak every tower in the scenecli-anything-sbox--jsonscene bulk-modify ./Assets/scenes/main.scene\\--has-tag tower--enable--position-y-add50# Validate before committingcli-anything-sbox--jsonproject validateREPL Mode
cli-anything-sboxwith no arguments enters an interactive REPL with a styled prompt:
$ cli-anything-sbox cli-anything-sbox> project info cli-anything-sbox> scene list ./Assets/scenes/main.scene cli-anything-sbox> codegen component --name Foo -o ./Code/Foo.cs cli-anything-sbox> quitEnvironment Variables
| Variable | Description | Default |
|---|---|---|
SBOX_PATH | s&box installation directory | Auto-detected from Steam library folders |
CLI_ANYTHING_SKILL_REPO | Override the reporepl_skinreads SKILL.md from | HKUDS/CLI-Anything |