Skip to content

Making of — nanoclaw-extras

Living journal. Newest entries at the top of each chapter; new chapters appended below as the repo evolves.

Chapter 1 — the org-migration repo-ification pass (2026-07-08)

Starting point

nanoclaw-extras was found as a loose, un-versioned directory (git init had never been run) containing exactly two files: ollama-mcp.mjs (a zero-dependency stdio MCP server bridging NanoClaw agent containers to a host Ollama instance) and wire-ollama.sh (a bash script that registers that bridge as an MCP server on every NanoClaw agent group). Both were already functionally complete and clearly hand-written for NanoClaw specifically — no scaffolding, tests, docs, or CI existed yet.

Fleet-material check

Before repo-ifying, checked whether either file was actually shared brief/system-prompt material belonging to the wider codex-harness-mirror fleet (Codex, Gemini/NanoClaw, Odysseus, Grok), which is parked for a separate consolidation effort and should not be duplicated per-tool. Neither file is: both reference NanoClaw's own CLI shape (src/cli/client.ts, groups/<folder>/, pnpm run setup:auto) and NanoClaw-specific conventions, not any cross-fleet shared prompt or brief. Verdict: this is legitimately standalone "extras" material, safe to ship as its own repo.

What changed during this pass

  • Moved both files under extras/ (matching where wire-ollama.sh itself expects to be installed inside a real NanoClaw checkout: extras/ollama-mcp.mjs relative to repo root).
  • ollama-mcp.mjs: added exports for TOOLS/callTool/handle/reply/replyError, an injectable fetchImpl/ollamaBase/defaultModel options bag on callTool, an injectable writeOut on reply/replyError/handle, and an isMain guard (via pathToFileURL) so the stdin listener only starts when the file is run directly, not when imported for tests. Behavior when run directly as node ollama-mcp.mjs is unchanged.
  • wire-ollama.sh: wrapped the body in a main() function guarded by a [[ "${BASH_SOURCE[0]}" == "${0}" ]] check (so tests can source it to reach extract_ids without running the whole script), and added an NCL_OVERRIDE env var so tests can point the CLI invocation at a stub instead of the real npx tsx src/cli/client.ts. Default behavior when the var is unset is unchanged.
  • Added a 17-test node:test unit suite (tests/ollama-mcp.test.mjs) — 85.5% line / 84.6% branch coverage, all HTTP happy/error paths and every JSON-RPC method branch covered.
  • Added a 16-assertion hermetic bash E2E suite (tests/wire-ollama.test.sh + tests/stub-client.mjs), a hand-rolled harness since no bats-core is installed in this environment.
  • Added tests/run-tests.sh as the single CI/local entry point (JS unit+coverage gate, then bash E2E gate), matching the pilot's tests/Invoke-CI.ps1 pattern.
  • Added the full house docs set, .github/workflows/ci.yml (test / churn / security jobs on home-ci-pending self-hosted labels, SHA-pinned checkout, Semgrep via Docker), .env.example, .gitignore, package.json.
  • git init, ran the secret-pattern grep gate (empty) and codex exec security review before the first commit. Committed locally only — no GitHub repo created, no push, per the current org-migration freeze.

Gate results (this pass)

  • Secret-pattern grep: empty, over the working tree and full git history.
  • Codex security review (codex exec ... danger-full-access, since the Windows sandbox helper codex-windows-sandbox-setup.exe is missing on this box and blocks the default sandboxed exec path — noted here as an environment gap, not a repo issue): no hardcoded secrets, no injection. Three cheap findings, all addressed same-session — see docs/technical/SECURITY.md for the full breakdown (Semgrep image now digest-pinned; self-hosted-runner + pull_request risk accepted and documented, matching the house pilot's own accepted posture; npx tsx first-run fetch behavior documented rather than changed).
  • Local test run (bash tests/run-tests.sh): 17 JS unit tests pass, 85.5% line / 84.6% branch coverage (floor 70%); 16 bash E2E assertions pass.