| name | subzeroclaw-use |
| description | Run and operate SubZeroClaw — the ~550-line C agentic daemon (skill.md + LLM + shell + loop). Load this to build it, configure it (~/.subzeroclaw/config), write an agent skill, run a task, wire it to an unhardcoded router for routing/cache/compaction, or run it as a systemd service with credential isolation. WARNING: it executes arbitrary shell with no sandbox. To develop the runtime itself, use subzeroclaw-contribute. |
Using SubZeroClaw
Read the warning first. SubZeroClaw runs whatever the model emits through
popen() — no confirmation, no sandbox, rm -rf / included. There is nothing
between the model's output and your system. Run it only where you accept that,
ideally as an unprivileged service user (see As a service).
The whole runtime is: read a skill (markdown) → call an LLM → run shell tools →
loop until done. One tool: shell. The "adapter" for git/curl/email/ffmpeg is
that they're one popen() away — install the CLI, the model uses it.
Two senses of "skill" — don't conflate them. A SubZeroClaw skill is a
plain .md file in ~/.subzeroclaw/skills/ that becomes the agent's system
prompt (what the agent knows). This file is a Claude Code skill (how to
operate the tool). When the docs below say "write a skill", they mean the
former.
Build & run
git clone https://github.com/genlayerlabs/subzeroclaw && cd subzeroclaw
make
mkdir -p ~/.subzeroclaw/skills
./subzeroclaw "check disk usage and clean tmp if over 80%"
./subzeroclaw
make install
An agent skill is just prose the LLM reads — no format, no registry, no trigger
matching. Drop a .md in ~/.subzeroclaw/skills/ and it joins the system
prompt. The repo's skills/*.md are format examples tied to one setup; write
your own.
Configuration (~/.subzeroclaw/config)
These are the only keys the runtime parses (config_parse_line); config.example
is the canonical template.
| Key | Meaning |
|---|
api_key | The unhardcoded router consumer key (llmr_…) — SubZeroClaw is designed to run on the router. A bare OpenRouter/provider key also works but is a degraded loop. Required. |
request_extra | JSON merged into every request body. Carries the model ({"model":"..."}) — there is no dedicated model key. Against a router it also carries the routing policy_ir. Override wins on key collision. |
compact_extra | JSON enabling async compaction: keep_recent + a cheap summariser policy_ir. Unset → no compaction. |
endpoint | default OpenRouter; point at an unhardcoded router for routing/cache/compaction. |
skills_dir, log_dir | defaults under ~/.subzeroclaw/. |
max_turns | tool-call loops per input (default 200). |
Env vars SUBZEROCLAW_API_KEY, SUBZEROCLAW_ENDPOINT, SUBZEROCLAW_REQUEST_EXTRA,
SUBZEROCLAW_COMPACT_EXTRA override the file.
The unhardcoded substrate (routing + compaction)
Routing with prompt-cache affinity and context compaction are not part of
"skill + LLM + shell + loop" — they live in the substrate. Point endpoint at an
unhardcoded router and express them
as JSON:
- Routing:
request_extra = {"model":"policy:auto","policy_ir":[ … ]}. The
runtime sends a per-run session id so the router keeps the conversation on its
cache-hot peer. (Author the policy_ir with the unhardcoded-use skill.)
- Compaction: on an
x_router.compact signal, the runtime fires an
append-only seal at the router's /v1/compact in the background and keeps
taking turns, splicing the sealed block in ahead of the turns that arrived
meanwhile — no pause, the cache prefix is never rewritten. compact_extra
carries keep_recent + the summariser policy.
Pointed at a bare provider the HTTP call still fires, but it's a degraded loop
(no routing, cache, or compaction) — not a supported standalone mode.
As a service (and credential isolation)
SubZeroClaw doesn't supervise itself — bring your init system. A systemd unit with
Restart=on-failure and an EnvironmentFile (root-owned, chmod 600) holding
SUBZEROCLAW_API_KEY gets you restart + credential isolation. The runtime
scrubs the four provider secrets (SUBZEROCLAW_API_KEY, _ENDPOINT,
_REQUEST_EXTRA, _COMPACT_EXTRA) from its own environment right after
config_load — wiping the value in place, then unsetenv — so the shell it hands
the model never inherits the key (cat /proc/self/environ comes up empty).
Non-secret vars like SUBZEROCLAW_SKILLS are deliberately kept (the genswarms
wrapper sets it). The supervisor owns the secret; the shell stays unguarded by
design — the scrub only keeps the runtime's own secrets out of it.
Gotchas
- A top-level
model = line in the config is ignored — the runtime never
parses it. The model rides in request_extra. (This is the most common
misconfiguration.)
- Use a tool-calling model. If the model can't call tools it will loop without
progress. Set it in
request_extra.
curl is required at runtime (API calls shell out to it); gcc only to build.
- Compaction is opt-in: unset
compact_extra → context grows until the
provider refuses it.
Where to read more
README.md — the full config reference, session logging, troubleshooting table.
config.example — the canonical config template.
- The
unhardcoded-use / sigma-policy-author skills — author the routing and
summariser policy_ir this runtime sends.