Skip to content

Latest commit

 

History

History
146 lines (110 loc) · 3.88 KB

File metadata and controls

146 lines (110 loc) · 3.88 KB

Tools

Microcode ships seven tools. Each is implemented in ~50–100 lines under src/tools/.

Tool Side effect Permission gated Description
read read no Read a UTF-8 text file with line numbers
ls read no List a single directory level
glob read no Find files by glob pattern
grep read no Search file contents with a regex
write mutating yes Create or overwrite a file
edit mutating yes Replace exact strings in a file
bash mutating yes Run a shell command

Read tools are never gated. Mutating tools always go through the permission policy.


read

{
  "name": "read",
  "input": {
    "path": "src/main.rs",
    "offset": 1,
    "limit": 200
  }
}
  • path — relative to cwd or absolute.
  • offset — 1-indexed line to start at. Default 1.
  • limit — max lines to return. Default 2000.

Output is <line-number>\t<line> so the model can reference exact locations. Files larger than 1.5 MB return an error suggesting offset/limit.

ls

{ "name": "ls", "input": { "path": "src" } }

Single-level directory listing. Honors .gitignore. Returns up to 500 entries, prefixed d (directory) or f (file).

glob

{
  "name": "glob",
  "input": { "pattern": "src/**/*.rs" }
}
  • pattern — gitignore-style glob.
  • path — search root, relative to cwd. Defaults to cwd.

Returns up to 200 matches, sorted by mtime (newest first).

grep

{
  "name": "grep",
  "input": {
    "pattern": "TODO|FIXME",
    "include": "*.rs",
    "case_insensitive": false
  }
}
  • pattern — Rust regex syntax.
  • path — search root.
  • include — glob filter, e.g. *.rs or src/**/*.toml.
  • case_insensitive — defaults to false.

Returns up to 200 matches as path:line:content. Skips files that look binary (NUL byte in first 8 KB) and files outside the gitignore set.

write

{
  "name": "write",
  "input": {
    "path": "src/lib.rs",
    "content": "pub fn hello() {}\n"
  }
}

Overwrites unconditionally. Creates parent directories as needed. Triggers the cargo verifier if the path ends in .rs.

edit

{
  "name": "edit",
  "input": {
    "path": "src/main.rs",
    "old_string": "fn main() {}",
    "new_string": "fn main() { println!(\"hi\"); }",
    "replace_all": false
  }
}
  • old_string must match exactly (whitespace included). It must be unique in the file unless replace_all is true.
  • The match must exist; missing matches return a tool error.
  • Triggers the cargo verifier if the path ends in .rs.

This is the right tool for surgical edits. If the model wants to rewrite a whole file, it should use write.

bash

{
  "name": "bash",
  "input": {
    "command": "cargo test --quiet",
    "timeout_ms": 60000
  }
}
  • command — shell pipeline. Run via sh -c.
  • timeout_ms — max ms. Defaults to 120000, capped at 600000.

Returns combined stdout+stderr (separated by --- stderr ---), truncated to 200 KB, with the exit code on the last line. Non-zero exit codes mark is_error = true.

Bash is the only tool that can do arbitrary side effects, so it's also the tool whose permission rules deserve the most thought. The default microcode init config allows bash:cargo * and bash:rg * and denies bash:sudo * and bash:rm -rf /*. Tune to taste.


Adding a tool

See DEVELOPMENT.md. Six steps:

  1. New file src/tools/foo.rs implementing Tool.
  2. Register it in ToolRegistry::defaults().
  3. If it modifies Rust files, extend CargoVerifier::should_run_for.
  4. Add a unit test in tests/tools_test.rs.
  5. Document in docs/tools.md.
  6. If it adds a config knob, document in USAGE.md.

Resist the urge to add a tool unless you've personally wanted it on three separate occasions. The seven existing tools cover the long tail.