Loopback-only agentic coding harness. One Rust binary: crate and CLI cgagentharness.
This is not CyClaw. CyClaw is the offline-first RAG soul agent
(cgfixit/CyClaw). This repo is the
harness/ console plus the agentic/ real-repo pipeline, ported from that
Python stack: same security posture, no RAG, no corpus, no terminal, no
fsconnect / sqlconnect / netconnect.
Status: 0.1.0. MSRV Rust 1.88. MIT. Bind is loopback-only. Every
write gate ships closed.
- Console:
http://127.0.0.1:8790/(assets/static/harness.html, served verbatim) - Chat: local OpenAI-compatible model (Ollama on
127.0.0.1:11434by default) - Pipeline: clone → plan → patch → hard-sandbox verify → human decide → commit → push → draft PR
- Isolation: the HTTP process never calls the pipeline in-process. It only
spawns
cgagentharness agentic …as a child (src/shim). Exit codes0 / 2 / 3 / 4are the whole interface.
CyClaw's Python harness/ + agentic/ layer is the part worth extracting:
the console, the child-process I6 boundary, the clone jail, and the write
gates. Everything else (RAG, soul, Telegram, fsconnect) stays in CyClaw.
If you want an offline knowledge agent, use CyClaw. If you want a local
coding harness that cannot reach the pipeline except through src/shim,
use this.
Shipped defaults do nothing to a repository. You chat with a local model in the browser; only after you arm the gates can the same binary clone a repo, propose a patch, verify it in a hard sandbox, and open a draft PR — and only after a human reviews a digest-bound diff.
| Need | Why |
|---|---|
Rust 1.88+ (rust-toolchain.toml) |
Build |
Ollama on 127.0.0.1:11434 with a chat model |
Console chat and local planner |
gh ≥ 2.40.0, logged in |
Real-repo pipeline only |
openssl (or any CSPRNG) |
Generate CGAGENTHARNESS_API_KEY |
Default model tag in config is qwen3.8:27b-mlx. Change
models.local_llm.model if that is not what you run.
Mutable state lives under ~/.CGagentHarness (CGAGENTHARNESS_HOME
overrides), seeded from assets/config.default.yaml.
git clone https://github.com/cgfixit/CG-agent-harness.git
cd CG-agent-harness
cargo build --release
export CGAGENTHARNESS_API_KEY="$(openssl rand -hex 20)"
./target/release/cgagentharness serve
# http://127.0.0.1:8790/Ollama must be running. Paste the same key into the console's key field
(held in that tab only), send a line, then try /status, /skills,
/tools. None of those touch a GitHub repository.
Step-by-step macOS walkthrough: setup-guide.md.
The shipped config keeps every write gate closed. After gh auth login,
edit ~/.CGagentHarness/config.yaml and set all four:
agentic:
enabled: true
repo: "owner/name"
deepagent_github:
enabled: true
allow_git_write_tools: trueRestart serve. In the console a typical loop is /agent run … (stage),
/agent confirm <why> (clone → plan → sandbox verify; no commit yet),
/agent status, then /agent approve → /agent push →
/agent publish <why>. Publish needs a fresh reason and confirm: true
on that call; confirm is never defaulted on.
CGAGENTHARNESS_AGENTIC_WRITE_DISABLE=1 is the disable-only kill switch.
Depth of the gates, clone jail, and digest-bound approval:
INVARIANTS.md. Operator rules: AGENTS.md.
Full arming walkthrough: setup-guide.md §9.
| Default | Behavior |
|---|---|
Unset CGAGENTHARNESS_API_KEY |
Every guarded route 401 (fail-closed) |
Non-loopback bind (--host 0.0.0.0, …) |
Refused at startup |
| Host header not a loopback name | Refused (DNS-rebinding defense) |
agentic.enabled, deepagent_github.enabled, allow_git_write_tools |
All ship false |
security.api_key_optional |
Ships false |
CGAGENTHARNESS_AGENTIC_WRITE_DISABLE (1 / true / yes / on) |
Disable-only write kill switch (cannot arm writes) |
GROK_API_KEY, ANTHROPIC_API_KEY, DEEPAGENT_API_KEY in CI |
Blanked; tests must not assert a developer key is present |
Quoted YAML "true" is off for every gate (flag_is_true). A reason
is never optional on a write.
scripts/verify-local.sh # fmt, clippy -D warnings, deny, tests, release build, live smoke
SKIP_LIVE=1 scripts/verify-local.sh # static + tests + build onlyCI blanks planner keys the same way. The live smoke
(scripts/smoke-ollama.sh) needs Ollama; skip it with SKIP_LIVE=1.
Quality bar and traps: AGENTS.md.
| Doc | What it is |
|---|---|
| INVARIANTS.md | What the code enforces and where (I6, gates, clone jail) |
| AGENTS.md | Operator / agent rules; do not "deduplicate" across the shim |
| setup-guide.md | Fresh-machine walkthrough (macOS) |
| assets/config.default.yaml | Every tunable; no hardcoded tunables elsewhere |
| LICENSE | MIT |