Module code — working with the codebase

🟢 The module gives the agent access to the project's code: reading, creating, and making targeted edits to files, browsing/searching, and running commands (build, tests, git). It comes with a ready-made agent coder. The module is dual-transport: the same code works as a linked crate and as a native DLL.

What it provides

What Identifier Description
Tools kind: read_file … run_command 6 operations on the project's code
Agent coder a ready-made code agent with tools connected
Setting code/code_root project root (projected into AGENT_OS_CODE_ROOT)

The module is part of the default set (server.yaml → modules.enabled).

Tools

kind Purpose
read_file read a file/range of lines
write_file create a new file (creation only)
edit_file targeted replacement of a fragment (old_string → new_string)
list_files list files by glob
grep search by content (regex)
run_command run a command in the project root

list_files/grep do not descend into .git and vendor/cache directories (node_modules, target, .venv, .next, …) and limit traversal (FS_MAX_SCAN), so searching a large tree doesn't hang the run.

The tools don't touch the filesystem or processes directly — they go through host ports agent_os.Fs and agent_os.Process, so the kernel sandbox applies equally in both transports, and the module declares the corresponding capabilities.

Project root

Priority:

  1. root: in the tool's YAML (absolute or with ${VAR});
  2. template_vars[code_root] from the invocation context — this is how the directory is passed to a subagent via params on subagent_tool (the key is configured by the root_var field);
  3. AGENT_OS_CODE_ROOT (the code/code_root setting on the Settings page);
  4. the server's working directory.

All paths are relative to the root; absolute paths and .. are rejected; escaping the root (including via symlinks) is forbidden. Additionally, the agent's sandbox is applied (read_roots/write_roots).

Edits — targeted only

edit_file replaces a unique fragment; the file is not overwritten in its entirety. write_file — creation only (an existing file is not overwritten).

run_command and security

The command is chosen by the LLM. The policy is in the tool's YAML:

deny:  [rm, sudo, shutdown]   # запрещённые программы/строки
# allow: [cargo, git, npm]    # если задан — разрешены только перечисленные
approval:                     # gate одобрения человека (ядро)
  required: true
  severity: high
  timeout_secs: 600
  on_timeout: deny
  action: "Выполнить команду: {{ input.command }}{% if input.args %} {{ input.args | join(' ') }}{% endif %}?"

Plus a hard timeout; in the linked build — kernel sandbox limits (CPU/mem/procs/ fsize, process tree kill). In the DLL build, kernel limits are not applied — protection comes down to approval + policy + timeout.

Agent coder

It ships as a config bundle (agents/coder/) and is loaded alongside config/agents/ when the module is enabled. It declares tool_files for all six tools. The agent config/agents/coder (if present) wins over the bundled one.

coder is declared admin_only: true: only an admin can interact with it (admin token or admin login cookie); regular and anonymous users get 403. This protects powerful tools (file editing, command execution). When authentication is disabled, the gate is open — set server.yaml → auth.

How the module contributes

The module emits one stable object ToolEngine per each kind into the registry tool.engines and declares capabilities:

agent_os_sdk::declare_module!(
    CodeModule, "code", contribute, DOCS,
    capabilities = ["agent_os.Fs", "agent_os.Process"]
);