Commit Graph

1732 Commits

Author SHA1 Message Date
github-actions[bot] d85efea229 chore: bump version to 2.1.1 2026-06-08 12:10:39 +00:00
github-actions[bot] c5b22cb308 docs: update token count to 183k tokens · 92% of context window 2026-06-08 12:10:36 +00:00
gavrielc 1592369201 Merge pull request #2713 from nanocoai/feat/egress-lockdown
feat(security): egress lockdown (opt-in, off by default)
2026-06-08 15:10:22 +03:00
Omri Maya 6420c0e254 feat(security): egress lockdown (opt-in) — agent egress only via OneCLI
Place agent containers on a Docker `--internal` network (no internet route)
with the OneCLI gateway attached, aliased host.docker.internal. The injected
proxy URL resolves only to the gateway, so a non-proxy-aware client or raw
socket has nowhere to go — closing the HTTPS_PROXY-bypass hole. The agent is
non-root with no NET_ADMIN, so it cannot undo this. Self-healing: the gateway
is re-attached at every spawn and on each host-sweep tick.

Fail-fast: when lockdown is enabled but the network/gateway can't be
established, refuse to spawn and surface a clear EgressLockdownError rather
than silently falling back to open egress. The host-sweep re-heal is the lone
exception — a heal failure there is logged, not fatal, since running agents
stay on the internal net (no leak) until the gateway returns.

Off by default — opt in with NANOCLAW_EGRESS_LOCKDOWN=true (so OSS users get
the prior behavior unchanged on pull). Also NANOCLAW_EGRESS_NETWORK and
ONECLI_GATEWAY_CONTAINER.

The lockdown logic lives in its own src/egress-lockdown.ts; container-runtime.ts
keeps only the generic runtime surface. Documented in docs/SECURITY.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 11:23:17 +03:00
gavrielc aef8d38b36 Merge pull request #2710 from markbala/docs/ollama-prefix-cache
docs(ollama): allow prompt caching by filtering the cache-busting hash
2026-06-07 23:21:45 +03:00
gavrielc 6d6f813deb Merge branch 'main' into docs/ollama-prefix-cache 2026-06-07 22:01:26 +03:00
markbala f9c86d0af2 docs(ollama): allow prompt caching by filtering the cache-busting hash
The Claude Agent SDK adds a per-request cch=<hash> to the front of every
prompt; it changes each turn, and Ollama's prompt cache only reuses a
prompt whose start is unchanged, so it re-reads the whole prompt every
time (slow). A tiny proxy filters the hash out (pins cch to a constant) so
caching kicks in. In our setup (31B on Apple Silicon) follow-up replies
went ~80s -> ~4s; numbers vary by model/hardware. Ollama ignores the hash,
so output is unchanged.

Scope: only the Claude-Code-CLI -> Ollama path; Codex/OpenCode emit no cch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 23:20:11 +08:00
github-actions[bot] 9edb33dd3a docs: update token count to 182k tokens · 91% of context window 2026-06-07 14:06:19 +00:00
gavrielc 8ba5261ae8 Merge pull request #2707 from nanocoai/feat/upgrade-tripwire
feat(upgrade): startup tripwire + upgrade marker
2026-06-07 17:06:03 +03:00
gavrielc 8c84dec8e9 Merge remote-tracking branch 'origin/main' into feat/upgrade-tripwire
# Conflicts:
#	.claude/skills/migrate-nanoclaw/SKILL.md
2026-06-07 17:05:24 +03:00
gavrielc 092487d7ad chore: release 2.1.0; guard auto-bump against deliberate version changes
Set package.json to 2.1.0 to match the CHANGELOG entry for the upgrade
tripwire (a [BREAKING] change warrants a minor bump). The startup
tripwire reads package.json as the source of truth, so this is the
version the gate will enforce.

bump-version.yml previously ran `pnpm version patch` on every push to
main, which would patch a deliberate 2.1.0 up to 2.1.1. It now skips the
auto-bump when the pushed commits already changed package.json
themselves. fetch-depth: 0 so the before/after diff has both tips.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v2.1.0
2026-06-07 17:03:02 +03:00
gavrielc 87850aa7f8 docs(changelog): release the upgrade-tripwire entry as 2.1.0
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 16:59:30 +03:00
gavrielc 526170fd47 feat(upgrade): add human-addressed guidance to tripwire banner
The startup tripwire message was written for a coding agent and gave a
human no direction — only the bare `set` override (which skips the
migrations the gate guards). Add one human-addressed stanza pointing to
/update-nanoclaw as the correct fix. The tested CODING AGENT block is
left byte-for-byte unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 16:57:13 +03:00
gavrielc 2d9375531b Merge pull request #2698 from nanocoai/feat/skill-exemplars
Skills conformance: exemplars + fleet retrofit (upgrade-maintainable skills)
2026-06-06 20:16:24 +03:00
gavrielc cee19ad300 feat(skills): rewrite use-native-credential-proxy, add-ollama-tool, migrate-from-openclaw for v2
Three skills that were broken on v2 (branch-merge installs of stale branches,
SKILL.md-only with no shipped code, dead v1 schema targets) rewritten to the
additive standard:
- use-native-credential-proxy: a skill-owned .env credential proxy + one-line
  seam reach-in (behavior + wiring tests, REMOVE.md). Explicit OneCLI opt-out;
  the credential-home inversion is flagged in docs/skill-smells.md.
- add-ollama-tool: an atomic-chat-shaped MCP-tool skill — bun stdio server,
  container registration + wiring tests, idempotent REMOVE.md.
- migrate-from-openclaw: retargeted at v2 (data/v2.db, ncl, OneCLI SecretRef,
  v2 recurrence) with a transform unit test and a REMOVE.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:09:12 +03:00
gavrielc 14dba9b73f feat(skills): MCP-tool / capability / operational conformance cleanup
Anatomy + correctness pass driven by the audit: REMOVE.md added to every
file-creating skill (gmail/gcal/rtk/mnemon/vercel/macos-statusbar/karpathy);
dead/fabricated reach-ins removed (mnemon's nonexistent OpenCode path and
migration-doc reach-in; migrate-from-v1's nonexistent scanForV1Patterns);
structural Dockerfile dep-tests where a CLI binary was unguarded; debug and
customize rewritten off stale v1 architecture onto v2 (data/v2.db, ncl,
two-DB sessions); update-skills + migrate-nanoclaw's branch-merge reapply
converted to additive re-runs; diff-against-past framing and non-step callouts
stripped throughout. Direct-DB / credential / telemetry smells flagged, not
actioned (see docs/skill-smells.md).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:08:59 +03:00
gavrielc 83c245722e feat(skills): provider conformance for opencode and codex
The provider-multipoint archetype: each skill now fetches and runs a
barrel-driven registration test in BOTH trees (host listProviderContainerConfigNames,
container listProviderNames) — pushed to origin/providers — instead of relying on
the shipped *.factory.test.ts, which imports the provider module directly,
self-registers, and stays green when a barrel line is deleted. Adds a structural
Dockerfile dep-test for codex's @openai/codex CLI binary, and a cross-runtime
REMOVE.md that reverses both barrels, the copied files, the dependency, and the
Dockerfile edits. Drops the grep-based "Verify" section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:08:42 +03:00
gavrielc 2908ffccf7 feat(skills): channel-family conformance retrofit
All 15 channel skills brought to the slack/deltachat standard: SKILL.md fetches
and runs the behavior registration test (pushed to origin/channels) in a
"Build and validate" step; REMOVE.md rewritten to delete every copied file and
remove the channel's actual env vars + package (each was individually wrong —
e.g. discord falsely claimed "no package to uninstall"); the VERIFY.md
anti-pattern deleted across the fleet; REMOVE.md created for emacs and whatsapp.
linear drops its stale bridge-patch step and relies on the bridge default +
the wiring's engage mode.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:08:31 +03:00
gavrielc 28e814d70c chore(skills): drop 4 skills broken on v2 + fix dangling refs
claw, x-integration, add-parallel, and convert-to-apple-container target
removed v1 architecture (v1 DB schema, file-IPC) or install via a forbidden
branch-merge of a stale branch — they can't be made conformant and are retired.
Cleans up the references to them in README.md, docs/SPEC.md, CONTRIBUTING.md,
and CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:08:09 +03:00
gavrielc ff22a2bcfb skill(add-dashboard): document that build guards the @nanoco dependency
The behavior test mocks @nanoco/nanoclaw-dashboard (its startDashboard binds a
real port), so the test alone passes with the dependency missing. The build
step is what catches a missing dep (TS2307 on the `await import(...)`), so the
validate step must run `pnpm run build` before the tests. Make that explicit so
it survives edits — a dependency install is an integration point that needs a
red-on-missing check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:09:45 +03:00
gavrielc 4578b58a0b skill(add-deltachat,add-slack): behavior registration test, implicit dep check
The registration tests now import the real barrel and assert the registry
contains the channel (not a structural source parse). Update the validate-step
prose accordingly: the test also goes red if the adapter package isn't
installed (the unmocked barrel import throws), so it implicitly verifies the
dependency-install step — and a structural check would falsely pass when the
barrel can't evaluate or the dep is missing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:05:36 +03:00
gavrielc b23c25fa19 skill(add-slack): make conformant — integration test, drop VERIFY.md
Retrofits the Slack skill to the two core principles and establishes the
template for the Chat SDK channel family (discord, telegram, teams, gchat,
webex, linear, github, …), which all share this single-barrel-import shape:

- Fetch and run a new src/channels/slack-registration.test.ts (lives on the
  channels branch next to the adapter, copied in via git show). Structural
  barrel parse asserting the `import './slack.js';` line — the one reach-in
  that fires the adapter's top-level registerChannelAdapter. Hermetic (does
  not import @chat-adapter/slack); red-on-delete. SKILL.md gains a
  build+validate step that also notes the build leg guards the adapter's
  createChatSdkBridge core-API consumption.
- REMOVE.md now deletes the import line and rm's the adapter and its test
  (was a soft comment-out), and re-syncs .env to the container.
- Drop VERIFY.md — tests are the verification; its manual check is covered by
  Next Steps / webhook setup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:56:09 +03:00
gavrielc c6afef1fe6 skill(add-deltachat): make conformant — integration test, drop VERIFY.md
Retrofits the existing deltachat channel skill to the two core principles
(minimal integration surface + a test for every functional integration point):

- Fetch and run a new src/channels/deltachat-registration.test.ts (lives on
  the channels branch next to the adapter, copied in via git show like the
  adapter itself). It guards the skill's one reach-in — the
  `import './deltachat.js';` line in the channel barrel that fires the
  adapter's top-level registerChannelAdapter. Structural barrel parse rather
  than importing it, so the native @deltachat/stdio-rpc-server isn't pulled
  into the host test process; the build leg covers that the import resolves.
  Red-on-delete of the barrel line. SKILL.md gains a build+validate step.
- REMOVE.md now deletes the import line and rm's the adapter and its test
  (was a soft comment-out), per the anatomy rule that remove reverses every
  change including copied test files.
- Drop VERIFY.md — tests are the verification; its manual log/connectivity/
  e2e checks were operational and already covered in Troubleshooting.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:21:23 +03:00
gavrielc 3ddfbfabd2 feat(add-atomic-chat-tool): make conformant — integration tests + standalone remove
- Add red-on-delete integration tests for both reach-ins:
  - index.ts mcpServers registration (AST, container/Bun tree)
  - buildContainerArgs env-forward call (AST, host/Node tree)
- Extract env forwarding into src/atomic-chat-env.ts so the container-runner
  reach-in is a single call (minimal integration point)
- Drop the redundant providers/claude.ts allowlist edit — the allow-pattern is
  derived from registered MCP server names
- Move removal into a standalone REMOVE.md; SKILL.md reads as a self-contained,
  present-tense artifact
- Document the shared stderr logger reach-in as a known hotspot (registry candidate)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 16:25:06 +03:00
gavrielc 6592e8461c feat(add-dashboard): conformant skill (minimal integration point + tests)
First exemplar of the skills upgradeability model, built example-first.
Giving the skill real tests surfaced — and the build caught — two silent
drifts that would break any adopter today.

What conformance means here:
- Minimal integration point: all startup logic lives in startDashboard() in
  the skill's own file; the edit to src/index.ts is a single colocated block
  (dynamic import + await call) in main() — no top-of-file import.
- Behavior test (dashboard-pusher.test.ts): real in-memory DB + real pusher
  + fake dashboard HTTP endpoint; asserts the /api/ingest snapshot on both
  the enabled and disabled paths.
- Wiring test (dashboard-wiring.test.ts): TS-AST assertion that index.ts
  dynamically imports the pusher and awaits startDashboard() colocated in
  main(), after DB init and before the boot-complete log — catches deletion
  AND misplacement, which a grep can't.
- Build catches drift: fixed imports of five DB modules that moved into
  src/modules/, and a stale g.container_config (now getContainerConfig()).

apply copies all three files and runs the tests; remove deletes them and the
single index.ts block. apply/remove stay markdown prose; the tests are the
verification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 16:25:06 +03:00
gavrielc e734e5cddd feat(upgrade): startup tripwire + upgrade marker
Refuse to start unless this install reached the current version through a
sanctioned path (setup / update / migrate). A raw `git pull` that skips
migrations now fails loudly with a self-healing message instead of
silently breaking.

- src/upgrade-state.ts: marker at data/upgrade-state.json, getCodeVersion,
  isUpgradeCurrent, enforceUpgradeTripwire (fails closed on missing /
  corrupt / mismatched marker)
- src/index.ts: gate wired in at startup step 0.5, before DB init
- scripts/upgrade-state.ts: get/set CLI (also the override / recovery cmd)
- setup/service.ts, /update-nanoclaw, /migrate-nanoclaw: stamp on success;
  update/migrate also self-update their own skill first
- CHANGELOG [BREAKING] entry bridges existing installs via the skills'
  breaking-change check
- docs/upgrade-recovery.md: clearing the tripwire

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 13:02:12 +03:00
github-actions[bot] d14472142d chore: bump version to 2.0.76 2026-06-05 08:04:24 +00:00
gavrielc 0c1897ad12 fix: blank the secret_url path instead of /*
A bare * in the pre-filled secret_url path doesn't survive (the gateway
URL-encodes everything, so an unencoded * collapses to just /, which only
exact-matches the path /). Leave the path blank instead so the created
secret matches all of huggingface.co, not a single endpoint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 11:04:06 +03:00
github-actions[bot] d16b24d5b4 docs: update token count to 181k tokens · 91% of context window 2026-06-05 07:56:50 +00:00
github-actions[bot] d0de64b999 chore: bump version to 2.0.75 2026-06-05 07:56:45 +00:00
gavrielc f3fde69536 fix: trim the upload-trace not-signed-in message
Drop "(host pattern pre-filled)" and "— no restart needed" from the HF
setup instructions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 10:56:30 +03:00
github-actions[bot] 20140c84be chore: bump version to 2.0.74 2026-06-05 07:55:13 +00:00
gavrielc 33c36842fa Merge pull request #2691 from nanocoai/upload-trace-gateway-setup-url
feat: show OneCLI's own setup URL when HF token is missing
2026-06-05 10:54:58 +03:00
gavrielc 0435736314 feat: show OneCLI's own setup URL when HF token is missing
The not-signed-in message hardcoded both a local and a hosted OneCLI
dashboard URL because the container can't tell which gateway it's behind.
But the gateway already tells us: a credential-less proxied request comes
back with the right URL in its error body —

  - credential_not_found → secret_url (pre-filled "new secret" form)
  - access_restricted     → manage_url (grant this agent access)
  - app_not_connected     → connect_url

Capture whoami's body + status (drop -f so the JSON survives the 401),
extract that URL, and present it. It's always the correct gateway, local
or hosted, with zero extra wiring. The secret_url's pre-filled `path`
defaults to the failing request path (/api/whoami-v2), so broaden it to
/* — otherwise the created secret wouldn't cover the upload endpoints.
Falls back to generic text when there's no gateway JSON to read.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 10:48:02 +03:00
github-actions[bot] 384f9c29e3 chore: bump version to 2.0.73 2026-06-05 07:37:40 +00:00
github-actions[bot] aa8597acf8 docs: update token count to 181k tokens · 90% of context window 2026-06-05 07:37:35 +00:00
gavrielc 3ae4ba18c3 Merge pull request #2690 from nanocoai/fix-upload-trace-secret-mode-docs
fix: simplify HF token setup + correct secret-mode docs
2026-06-05 10:37:20 +03:00
gavrielc de88be8a7a fix: simplify HF token setup + correct secret-mode docs
The default OneCLI secret mode for auto-created agents is `all`, not
`selective` — a fresh agent created via ensureAgent({name, identifier})
comes back with secretMode "all", so matching vault secrets inject
automatically. Drop the now-unnecessary per-agent assignment step.

- upload-trace.ts: remove step 3 (set-secret-mode) from the not-authed
  message; creating the token and adding it to the vault is enough
- CLAUDE.md: trim the secret-mode gotcha to reflect `all` as the default
- init-onecli skill: replace stale `onecli start` (gone in 1.4.x) and the
  `ps aux | grep onecli` check with the real Docker Compose start path

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 10:35:42 +03:00
github-actions[bot] b9141218ad docs: update token count to 181k tokens · 91% of context window 2026-05-31 20:17:59 +00:00
github-actions[bot] 341b5950e1 chore: bump version to 2.0.72 2026-05-31 20:17:55 +00:00
gavrielc 8cb4ed27ef Merge pull request #2648 from nanocoai/share-session-command 2026-05-31 23:17:43 +03:00
gavrielc 729cd8d2a6 feat: add /upload-trace command to upload session trace to Hugging Face
Adds a runner-handled /upload-trace slash command (admin-gated, like /clear)
that uploads the current session's Claude Code transcript to the user's own
private {hf_user}/nanoclaw-traces dataset, browsable in the HF Agent Trace
Viewer. The transcript is already in the format the viewer auto-detects, so
the command just locates the newest one and pushes it via the Hub commit API.

Auth is handled by the OneCLI gateway: curl goes out through the injected
HTTPS_PROXY, which adds the user's HF token — no credential ever touches
agent code. A missing/unassigned token yields a clear setup message.

- container/agent-runner/src/upload-trace.ts: isUploadTraceCommand() + uploadTrace()
- poll-loop.ts: recognize and handle /upload-trace in the runner
- command-gate.ts: admin-gate /upload-trace on the host
- upload-trace.test.ts: unit + integration coverage for the command

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:42:36 +03:00
github-actions[bot] 3601a8a1fe chore: bump version to 2.0.71 2026-05-28 19:41:34 +00:00
gavrielc 991969085e Merge pull request #2637 from nanocoai/bump-claude-code-2.1.154
chore: bump claude-code to 2.1.154 and claude-agent-sdk to 0.3.154
2026-05-28 22:41:19 +03:00
gavrielc 81d99e1dc9 chore: bump claude-code to 2.1.154 and claude-agent-sdk to 0.3.154
claude-code CLI 2.1.128 -> 2.1.154 (Dockerfile build-arg). agent-runner SDK 0.2.128 -> 0.3.154: the 0.3 major moved @anthropic-ai/sdk and @modelcontextprotocol/sdk from regular deps to peer deps, so add @anthropic-ai/sdk ^0.100.0 as a direct dep and raise @modelcontextprotocol/sdk to ^1.29.0. Regenerate bun.lock. Typecheck + agent-runner tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 22:35:34 +03:00
github-actions[bot] 24922593e3 docs: update token count to 179k tokens · 89% of context window 2026-05-25 08:41:50 +00:00
github-actions[bot] b142055a1f chore: bump version to 2.0.70 2026-05-25 08:41:46 +00:00
glifocat 0c5104df68 Merge pull request #2526 from glifocat/fix/2525-groups-delete-cascade
fix(cli): cascade dependent rows on groups delete (#2525)
2026-05-25 10:41:31 +02:00
github-actions[bot] cabc7c0f82 docs: update token count to 178k tokens · 89% of context window 2026-05-23 17:06:48 +00:00
github-actions[bot] 3e533413e5 chore: bump version to 2.0.69 2026-05-23 17:06:44 +00:00