Dogfooded 2026-04-18 on main HEAD 2bf2a11 from /tmp/cdZZ.
Asymmetric normalization:
normalize_tool_name(value) = trim + lowercase + replace -→_
Canonical 'read_file' (snake_case):
accepts: read_file, READ_FILE, Read-File, read-file,
Read (alias), read (alias)
rejects: ReadFile, readfile, READFILE
→ Because normalize('ReadFile')='readfile', and name_map
has key 'read_file' not 'readfile'.
Canonical 'WebFetch' (PascalCase):
accepts: WebFetch, webfetch, WEBFETCH
rejects: web_fetch, web-fetch, Web-Fetch
→ Because normalize('WebFetch')='webfetch' (no underscore).
User input 'web_fetch' normalizes to 'web_fetch' (keeps
underscore). Keys don't match.
The normalize function ADDS underscores (hyphen→underscore) but
DOESN'T REMOVE them. So PascalCase canonicals have underscore-
free normalized keys; user input with explicit underscores keeps
them, creating key mismatch.
Result: 'bash,Bash,BASH,Read,read_file,Read-File,WebFetch' all
accepted, but 'web_fetch,web-fetch' rejected.
Additional silent-flag issues:
- Splits on commas OR whitespace (undocumented — help says
TOOL[,TOOL...])
- 'bash,Bash,BASH' silently accepts all 3 case variants, no
dedup warning
- Allowed tools NOT in status/doctor JSON — claw passing
--allowedTools has no way to verify what runtime accepted
Trace:
tools/src/lib.rs:192-244 normalize_allowed_tools:
canonical_names from mvp_tool_specs + plugin_tools + runtime
name_map: (normalize_tool_name(canonical), canonical)
for token in value.split(|c| c==',' || c.is_whitespace()):
lookup normalize_tool_name(token) in name_map
tools/src/lib.rs:370-372 normalize_tool_name:
fn normalize_tool_name(value: &str) -> String {
value.trim().replace('-', '_').to_ascii_lowercase()
}
Replaces - with _. Lowercases. Does NOT remove _.
Asymmetry source: normalize('WebFetch')='webfetch',
normalize('web_fetch')='web_fetch'. Different keys.
--allowedTools NOT plumbed into Status JSON output
(no 'allowed_tools' field).
Fix shape (~50 lines):
- Symmetric normalization: strip underscores from both canonical
and input, OR don't normalize hyphens in input either.
Pick one convention.
- claw tools list / --allowedTools help subcommand that prints
canonical names + accepted variants.
- Surface allowed_tools in status/doctor JSON when flag set.
- Document comma+whitespace split semantics in --help.
- Warn on duplicate tokens (bash,Bash,BASH = 3 tokens, 1 unique).
- Regression per normalization pair + status surface + duplicate.
Joins Silent-flag/documented-but-unenforced (#96-#101, #104,
#108, #111, #115, #116, #117, #118, #119, #121, #122) as 16th.
Joins Permission-audit/tool-allow-list (#94, #97, #101, #106,
#115, #120) as 7th.
Joins Truth-audit — status/doctor JSON hides what allowed-tools
set actually is.
Joins Parallel-entry-point asymmetry (#91, #101, #104, #105,
#108, #114, #117, #122) as 9th — --allowedTools vs
.claw.json permissions.allow likely disagree on normalization.
Natural bundles:
#97 + #123 — --allowedTools trust-gap pair:
empty silently blocks (#97) +
asymmetric normalization + invisible runtime state (#123)
Permission-audit 7-way (grown):
#94 + #97 + #101 + #106 + #115 + #120 + #123
Flagship permission-audit sweep 8-way (grown):
#50 + #87 + #91 + #94 + #97 + #101 + #115 + #123
Filed in response to Clawhip pinpoint nudge 1494993419536306176
in #clawcode-building-in-public.
Claw Code
ultraworkers/claw-code · Usage · Rust workspace · Parity · Roadmap · UltraWorkers Discord
Claw Code is the public Rust implementation of the claw CLI agent harness.
The canonical implementation lives in rust/, and the current source of truth for this repository is ultraworkers/claw-code.
Important
Start with
USAGE.mdfor build, auth, CLI, session, and parity-harness workflows. Makeclaw doctoryour first health check after building, userust/README.mdfor crate-level details, readPARITY.mdfor the current Rust-port checkpoint, and seedocs/container.mdfor the container-first workflow.ACP / Zed status:
claw-codedoes not ship an ACP/Zed daemon entrypoint yet. Runclaw acp(orclaw --acp) for the current status instead of guessing from source layout;claw acp serveis currently a discoverability alias only, and real ACP support remains tracked separately inROADMAP.md.
Current repository shape
rust/— canonical Rust workspace and theclawCLI binaryUSAGE.md— task-oriented usage guide for the current product surfacePARITY.md— Rust-port parity status and migration notesROADMAP.md— active roadmap and cleanup backlogPHILOSOPHY.md— project intent and system-design framingsrc/+tests/— companion Python/reference workspace and audit helpers; not the primary runtime surface
Quick start
Note
[!WARNING]
cargo install claw-codeinstalls the wrong thing. Theclaw-codecrate on crates.io is a deprecated stub that placesclaw-code-deprecated.exe— notclaw. Running it only prints"claw-code has been renamed to agent-code". Do not usecargo install claw-code. Either build from source (this repo) or install the upstream binary:cargo install agent-code # upstream binary — installs 'agent.exe' (Windows) / 'agent' (Unix), NOT 'agent-code'This repo (
ultraworkers/claw-code) is build-from-source only — follow the steps below.
# 1. Clone and build
git clone https://github.com/ultraworkers/claw-code
cd claw-code/rust
cargo build --workspace
# 2. Set your API key (Anthropic API key — not a Claude subscription)
export ANTHROPIC_API_KEY="sk-ant-..."
# 3. Verify everything is wired correctly
./target/debug/claw doctor
# 4. Run a prompt
./target/debug/claw prompt "say hello"
Note
Windows (PowerShell): the binary is
claw.exe, notclaw. Use.\target\debug\claw.exeor runcargo run -- prompt "say hello"to skip the path lookup.
Windows setup
PowerShell is a supported Windows path. Use whichever shell works for you. The common onboarding issues on Windows are:
- Install Rust first — download from https://rustup.rs/ and run the installer. Close and reopen your terminal when it finishes.
- Verify Rust is on PATH:
If this fails, reopen your terminal or run the PATH setup from the Rust installer output, then retry.cargo --version - Clone and build (works in PowerShell, Git Bash, or WSL):
git clone https://github.com/ultraworkers/claw-code cd claw-code/rust cargo build --workspace - Run (PowerShell — note
.exeand backslash):$env:ANTHROPIC_API_KEY = "sk-ant-..." .\target\debug\claw.exe prompt "say hello"
Git Bash / WSL are optional alternatives, not requirements. If you prefer bash-style paths (/c/Users/you/... instead of C:\Users\you\...), Git Bash (ships with Git for Windows) works well. In Git Bash, the MINGW64 prompt is expected and normal — not a broken install.
Note
Auth: claw requires an API key (
ANTHROPIC_API_KEY,OPENAI_API_KEY, etc.) — Claude subscription login is not a supported auth path.
Run the workspace test suite:
cd rust
cargo test --workspace
Documentation map
USAGE.md— quick commands, auth, sessions, config, parity harnessrust/README.md— crate map, CLI surface, features, workspace layoutPARITY.md— parity status for the Rust portrust/MOCK_PARITY_HARNESS.md— deterministic mock-service harness detailsROADMAP.md— active roadmap and open cleanup workPHILOSOPHY.md— why the project exists and how it is operated
Ecosystem
Claw Code is built in the open alongside the broader UltraWorkers toolchain:
Ownership / affiliation disclaimer
- This repository does not claim ownership of the original Claude Code source material.
- This repository is not affiliated with, endorsed by, or maintained by Anthropic.
