267 Commits

Author SHA1 Message Date
glifocat
bda72a4bf4 chore: rename remaining qwibitai/nanoclaw references to nanocoai/nanoclaw
Sweep of outbound strings, doc URLs, comments, and clone instructions
that were missed in the original org rename. One both-match case in
setup/lib/channels-remote.sh (URL detection) accepts either name so
existing forks with a `qwibitai` remote continue to resolve cleanly;
everywhere else is a straight rename.

Historical mentions left intact:
- CHANGELOG.md (v2.0.0 entry, frozen history)
- .claude/skills/add-gmail-tool/SKILL.md (pre-v2 qwibitai skill — historical)
- repo-tokens/badge.svg (auto-regenerated by update-tokens.yml)
2026-05-11 08:40:09 +02:00
gavrielc
2754f7559a Merge pull request #2320 from ira-at-work/feat/skill-docs-updates
docs(skills): update SKILL.md for debug, init-onecli, add-gmail-tool, add-opencode, add-signal, add-vercel
2026-05-08 00:11:40 +03:00
gavrielc
1594a0c682 Apply suggestion from @gavrielc 2026-05-08 00:10:24 +03:00
gavrielc
a90104b8e3 Merge pull request #2318 from ira-at-work/feat/add-mnemon
feat(skills): add /add-mnemon skill — persistent semantic memory
2026-05-07 23:49:35 +03:00
gavrielc
f7c610ac4a Apply suggestion from @gavrielc 2026-05-07 18:49:57 +03:00
glifocat
348e200c11 fix(add-karpathy-llm-wiki): update for v2 — schedule_task MCP + no build step 2026-05-07 13:09:40 +02:00
Ira Abramov
877d2a370a docs(skills): update SKILL.md for debug, init-onecli, add-gmail-tool, add-opencode, add-signal, add-vercel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 13:06:33 +03:00
Ira Abramov
8eff3e558c feat(skills): add /add-mnemon skill — persistent semantic memory for agent groups
Adds a skill that installs the mnemon CLI into agent containers, giving each
agent group a persistent, queryable knowledge graph across sessions.

Mnemon stores facts (insights) with categories, importance scores, and entity
tags, and connects them with typed edges (causal, semantic, temporal, entity).
The agent can remember, recall, search, link, and forget facts — surviving
container restarts and context compaction.

Installation: drops the mnemon binary from the channels branch, creates the
per-agent-group data directory, and configures the agent's CLAUDE.md to load
the skill on every spawn.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 12:43:08 +03:00
NanoClaw bot user
0d7458c6f3 fix(skills): replace sqlite3 CLI with in-tree better-sqlite3 wrapper
Setup deliberately avoids the sqlite3 CLI (`setup/verify.ts:5` calls
this out: "Uses better-sqlite3 directly (no sqlite3 CLI)") and never
installs or probes for the binary. Despite that, 13 skills shelled out
to `sqlite3 ...` directly, breaking on hosts where the CLI isn't
preinstalled — the same root cause as #2191 but spread across the
skill surface.

Add `scripts/q.ts`, a ~30-LOC wrapper over the `better-sqlite3` dep
that setup already installs and verifies. Default output matches
`sqlite3 -list` (pipe-separated, no header) so existing skill text
reads identically — only the binary changes. SELECT/WITH queries go
through `db.prepare().all()`; everything else (INSERT/UPDATE/DELETE,
including compound statements) goes through `db.exec()`.

Migrate every in-tree caller:

- 17 hardcoded invocations across 8 SKILL.md files (init-first-agent,
  add-deltachat, add-signal, add-emacs, add-whatsapp, add-ollama-provider,
  debug, add-parallel) plus add-deltachat/VERIFY.md.
- `manage-channels/SKILL.md` shows canonical SQL but never prescribed
  a tool, so the assistant defaulted to `sqlite3` and silently failed.
  Add a one-line wrapper hint above the SQL block.
- `migrate-v2.sh` schema/count probes (was the original #2191 case).
  Replace `.tables` with `SELECT name FROM sqlite_master`.
- Document the wrapper convention in root `CLAUDE.md` under "Central DB".

Add `scripts/q.test.ts` with 6 vitest cases covering both modes,
NULL rendering, empty-result, compound mutations, and arg validation.
Wire `scripts/**/*.test.ts` into `vitest.config.ts`.

Out of scope (flagged for follow-up):
- `debug` and `add-parallel` still reference the v1-only path
  `store/messages.db`. Routing through the wrapper now produces a
  cleaner "no such file" error, but the surrounding sections are
  v1-era throughout — a v1-content cleanup is its own PR.
- `cleanup-sessions.sh` is being addressed in #1889 (different style,
  hard-fail rather than wrap); left untouched here to avoid stepping
  on that author's work.

Closes #2191.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 19:38:33 +02:00
Ethan Munoz
eacb93c4e5 fix(manage-channels): include canonical SQL queries in SKILL.md
The skill's "Assess Current State" step said only "query agent_groups,
messaging_groups, ..." without specifying columns. The `register` CLI
takes `--assistant-name "<name>"` (mentioned three times in the same
SKILL.md), but the schema column is `name`, not `assistant_name` — and
the SKILL.md never linked the two.

When the agent had to compose a SELECT against `agent_groups` from the
SKILL.md vocabulary alone, it extrapolated `--assistant-name` into a
column name and produced:

  SELECT id, folder, assistant_name FROM agent_groups;
  -> Error: in prepare, no such column: assistant_name

Replace the prose pointer with canonical SQL queries that match the
real schema. The `name AS assistant_name` alias preserves the familiar
term in the agent's output.

Verified locally as a drop-in: `/manage-channels` runs clean from end
to end with this version, no further inference needed.

Closes #2289
2026-05-06 00:29:54 +02:00
glifocat
a8e0a7f011 fix(setup): pin Baileys to 7.0.0-rc.9 in install-whatsapp scripts
PR #2259 (Baileys v6→v7) was merged into the channels branch instead of
main. PR #2260 was merged into main 28s later assuming v7 was already
in place. The v6 pin survived in three sites while the WhatsApp adapter
copied from origin/channels at install time was already on the v7 LID
API, breaking every fresh migrate-v2.sh run at 2c-install-whatsapp with
TS errors on remoteJidAlt/participantAlt/lid-mapping.update.

Bumps the pin to 7.0.0-rc.9 (the version v1 has been running on for
months) in:

- setup/install-whatsapp.sh
- setup/add-whatsapp.sh
- .claude/skills/add-whatsapp/SKILL.md (install instruction)

package.json + pnpm-lock.yaml are not touched here — install-whatsapp.sh
mutates them at runtime via pnpm install with the corrected pin.

Closes #2283
2026-05-05 20:47:36 +02:00
glifocat
9633788a1b fix(skills): bump @chat-adapter/* cohort to 4.27.0
@chat-adapter/discord@4.27.0 includes vercel/chat#256, which fixes the
Discord adapter unconditionally setting payload.content alongside
payload.embeds when posting a card. In 4.26.0 every Discord card
appeared twice (text content above the embed, identical content inside
the embed) — every new install reproduced this on the welcome tour and
on every approval card.

The other 7 skills bump in lockstep because @chat-adapter/discord@4.27.0
depends on chat@4.27.0 while @chat-adapter/<other>@4.26.0 depend on
chat@4.26.0. Mixing the cohort produces a TypeScript dual-version
conflict between the bridge and adapter ChatInstance types.

Files updated (one line per file in each pnpm install command):
- add-discord (the user-visible bug fix)
- add-gchat, add-github, add-linear, add-slack, add-teams, add-telegram,
  add-whatsapp-cloud (cohort consistency)

Out of scope: add-imessage, add-matrix, add-webex, add-resend use
third-party packages with independent versioning.

Closes #2264
2026-05-05 00:28:25 +02:00
Gabi Simons
cf783385e7 fix: handle missing bun on host and dynamic systemd service name
Container typecheck and bun install gracefully skip when bun isn't
installed on the host. Linux service restart now detects the actual
systemd service name instead of hardcoding 'nanoclaw'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 15:45:54 +00:00
Gabi Simons
e432467066 fix: update /update-nanoclaw skill for v2 architecture
The skill was written for v1 and missed several v2 changes: container
rebuild after merge, dependency install for both pnpm and bun lockfiles,
container typecheck, channel/provider branch update awareness, and
platform-aware service restart instructions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 14:46:18 +00:00
gavrielc
82216b536d Add /add-deltachat skill
Skill files only — copied from PR #2192 (channels branch).
Source adapter (src/channels/deltachat.ts) lives on the channels
branch and is installed by the skill.

Co-Authored-By: Axel McLaren <scm@axml.uk>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 21:21:58 +03:00
Gavriel Cohen
7922a19af7 docs(migrate-from-v1): drop the blocker/deferred table
Trust the agent to figure out which failed steps actually stop
routing. The rule is the goal ("can the bot route one message?"),
not a hardcoded list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:40:07 +03:00
Gavriel Cohen
8c1b209aeb docs(migrate-from-v1): 2b-channel-auth and 3c-auth are blockers
2b-channel-auth: copies the Baileys keystore + channel-specific env
keys. Without it WhatsApp can't connect — saw this firsthand when
the original candidatePaths bug left env_keys=0,files=0.

3c-auth: registers Anthropic credentials in OneCLI. 3b installs the
gateway; 3c puts the secret in the vault. Without 3c every agent
request 401s regardless of 3b's status.

1c-groups stays deferred — agent runs on stock CLAUDE.md without it,
but routing works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:36:10 +03:00
Gavriel Cohen
2bc1279a12 docs(migrate-from-v1): trim Phase 0 to intent only
Previous version spelled out launchctl/systemctl commands, log lines
to grep for, diagnostic recipes — the agent reading this skill knows
all of that. Keep only the parts that aren't obvious from the rest of
the codebase: which steps are blocking vs deferred, the smoke-test
ordering, and the non-destructive framing for the user.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:31:23 +03:00
Gavriel Cohen
2617313f19 docs(migrate-from-v1): blockers-first + smoke test before deeper work
Phase 0 used to be "triage every failed step before doing anything
else", which front-loaded a bunch of fixes for things that don't
actually block the user from proving v2 works. Restructure:

- 0a — fix blockers only (1b/1d/2c/2d/3a/3b/3e). Defer non-blockers
  (1a, 1c, 1e, 2b, 3c) — most surface naturally in later phases.
- 0b — smoke test: switch v1 → v2, send a real message, verify the
  routing chain in logs/nanoclaw.log. AskUserQuestion gates whether
  to continue.
- Revert recipe (launchctl/systemctl) called out as always-available,
  not destructive — v1 process, data, and credentials are untouched.

Up-front list of what the script handled now also mentions the
WhatsApp LID resolution and Baileys keystore copy, so users see
exactly what continuity they're getting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:28:46 +03:00
Gavriel Cohen
8439a180be docs(migrate-v2): collapsible README section + skill preflight
README: replace the one-line v1 migration note with a collapsed
<details> block. Quick Start stays compact for the common case (fresh
install) while v1 users get the actual instructions. Calls out
explicitly that the script must be run from a real terminal — not from
inside a Claude session — so the channel-select / switchover prompts
and the Node/pnpm/Docker bootstrap all work.

migrate-from-v1 skill: add a Preflight section that aborts if
logs/setup-migration/handoff.json is missing. Without this, invoking
the skill before the script just leads Claude to start guessing /
running shell commands. The new message redirects them to the script
and tells them it'll hand back to Claude on completion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:22:50 +03:00
exe.dev user
f35be24aef chore: move shared helpers to migrate-v2/, delete migrate-v1/
Extracted the helpers we use (JID parsing, trigger mapping, channel
auth registry, generateId, v2PlatformId) into setup/migrate-v2/shared.ts.
Deleted setup/migrate-v1/ entirely — no code references it anymore.

Updated README, CLAUDE.md, docs/v1-to-v2-changes.md, and
docs/migration-dev.md to reference the new paths and migrate-v2.sh
entry point.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 20:23:34 +00:00
exe.dev user
1d73b2986a feat: add migrate-v2.sh — standalone v1 → v2 migration script
New entry point: `bash migrate-v2.sh` from the v2 checkout.
Replaces the old setup-embedded migration flow with a standalone
4-phase script + rewritten Claude skill for the interactive parts.

Phase 0: Bootstrap (Node/pnpm/deps via setup.sh) + find v1
Phase 1: Core state (env, DB, groups, sessions, tasks)
Phase 2: Channels (clack multiselect, auth copy, code install)
Phase 3: Infrastructure (OneCLI, auth, Docker, skills, container build)
Service switchover: stop v1 → start v2 → test → keep or revert
Phase 4: Handoff → exec claude "/migrate-from-v1"

The skill handles: owner seeding, access policy, CLAUDE.local.md
cleanup, container config validation, fork customization porting.

Key fixes found during testing:
- triggerToEngage: requires_trigger=0 must override non-empty pattern
- unknown_sender_policy defaults to 'public' (strict drops all msgs
  before owner is seeded)
- Service revert must stop v2 (parse unit name from step log, not
  early tsx one-liner that can fail)
- Session continuity: copy JSONL from -workspace-group/ to
  -workspace-agent/ and write continuation:claude into outbound.db
- container_config.additionalMounts written directly to container.json
  (same shape in v1 and v2)
- EXIT trap writes handoff.json; explicit write_handoff before exec

Includes migrate-v2-reset.sh for dev iteration and docs/migration-dev.md
for testing/debugging reference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 20:13:38 +00:00
gabi-simons
36e731c02d Merge branch 'main' into feat/migrate-from-v1
Resolve import conflict in setup/auto.ts — keep runMigrateV1 import,
deduplicate runWindowedStep and getLaunchdLabel/getSystemdUnit imports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-01 04:52:41 +00:00
Gabi Simons
c5d0243417 fix(setup): add Interactivity & Shortcuts step to Slack setup
Slack interactive buttons (channel approval cards) require Interactivity
to be enabled in the app settings. Without it, button clicks silently
fail to reach the host. Added the step to both the setup wizard
post-install checklist and the add-slack SKILL.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-28 12:19:44 +00:00
Gabi Simons
c36f0c6b36 fix(setup): wire Slack agent during setup like Discord/Telegram
Slack setup previously stopped after installing the adapter, leaving
users to manually discover /init-first-agent. When they DM'd the bot,
the channel-approval flow silently failed because no owner existed.

Now the Slack setup flow matches Discord/Telegram:
- Collects the operator's Slack member ID
- Opens a DM channel via conversations.open (requires im:write scope)
- Runs init-first-agent to establish ownership, wiring, and welcome DM
- Updates post-install note to focus on webhook URL (the only remaining step)

The welcome DM is delivered via chat.postMessage (outbound), which works
before Event Subscriptions are configured. The user sees the greeting
immediately; inbound replies require webhooks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-28 11:35:51 +00:00
Gabi Simons
5812422321 Merge branch 'main' into feat/migrate-from-v1 2026-04-26 12:26:04 +03:00
Ira Abramov
b6be3b9bf4 docs(skills): merge add-signal-v2 lessons into add-signal, drop v2
Absorbs battle-tested knowledge from the v2 skill into the upstream
add-signal: registration paths (new number + linked device), CAPTCHA
flow, VoIP SMS-first timing, Java prereq, config-lock warning, wiring
SQL for groups, not_member silent-drop fix, GroupV2 groupId extraction
note, and UUID-based platform ID format.

Corrects a factual error in the upstream: DM platform IDs are
signal:{UUID} (ACI), not phone numbers.

Removes the now-redundant add-signal-v2 skill.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 16:52:20 +03:00
Ira Abramov
7e99d0eaf7 Merge branch 'main' into pr/add-signal-v2
* main: (185 commits)
  chore: bump version to 2.0.13
  chore: bump version to 2.0.12
  docs: update token count to 132k tokens · 66% of context window
  fix(register): wire channels with correct engage fields, skip prefix for native IDs
  skill(add-gcal-tool): OneCLI-native Google Calendar MCP tool
  docs(providers): note that container.json provider is what the runner reads
  Revert src changes; skill applies them at install time
  chore: bump version to 2.0.11
  fix(workflows): label PRs from forks that follow the contributing template
  chore(format): apply prettier to chat-sdk-bridge.ts
  chore(setup): minimize verify diff
  test(setup): cover CLI-only verify status
  fix(setup): accept CLI-only verify success
  detect setup auth ping failures
  fix(agent-route): reject unsafe attachment filenames to prevent path traversal
  fix(agent-route): forward file attachments between agents
  refactor(session-state): key continuations per provider to survive provider switches
  skill(add-gmail-tool): OneCLI-native Gmail MCP tool
  fix(setup): register step uses engage_mode columns dropped by migration 010
  docs: update token count to 130k tokens · 65% of context window
  ...
2026-04-25 16:44:42 +03:00
gavrielc
6d35c85129 skill(add-gcal-tool): OneCLI-native Google Calendar MCP tool
Adds /add-gcal-tool — a sibling of /add-gmail-tool that installs
@cocal/google-calendar-mcp with the same OneCLI stub-file pattern. Skill
applies the Dockerfile + TOOL_ALLOWLIST changes at install time; trunk
stays clean so users who never run the skill don't carry the calendar
MCP in their image.

Dropped the Phase 5 dry-run section since it hardcoded a per-install
image tag slug and duplicated Phase 4's live agent test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 16:49:40 +03:00
gavrielc
c7f8e98471 Merge branch 'main' into skill/add-gmail-tool 2026-04-24 16:41:59 +03:00
exe.dev user
52f8661f0c docs(providers): note that container.json provider is what the runner reads
The upstream precedence fix (5845a5a) made agent_groups.agent_provider and
sessions.agent_provider authoritative for host-side provider contribution
(per-session mount, env passthrough), but those DB values don't propagate
into the group's container.json — and the in-container runner reads
`provider` from container.json, not from the DB. That caused a confusing
failure mode: flipping the DB column to 'codex', rebuilding, and
restarting still spawned a Claude runner because container.json had no
provider field. The old skill wording ("container receives AGENT_PROVIDER
from the resolved value") overstated the integration.

Update add-codex and add-opencode "Per group / per session" sections to
say: set `"provider": "<name>"` in the group's container.json — that's
the source the runner reads. Keep the DB columns documented for the
host-side contribution they actually drive, and spell out the
session → group → container.json → 'claude' fallback so the precedence
is still discoverable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 13:38:05 +00:00
grtwrn
9e33274e2a skill(add-gmail-tool): OneCLI-native Gmail MCP tool
Adds /add-gmail-tool — a Utility skill that installs Gmail as an MCP tool
in NanoClaw v2 using OneCLI for credential injection. No raw OAuth tokens
ever reach the container; the gateway swaps the "onecli-managed" stub
bearer for the real token at request time.

Scope (3 files):
- container/Dockerfile: pnpm global-install of
  @gongrzhe/server-gmail-autoauth-mcp@1.1.11, pinned behind GMAIL_MCP_VERSION.
  Also pins zod-to-json-schema@3.22.5 to avoid an ERR_PACKAGE_PATH_NOT_EXPORTED
  crash: the MCP server's loose zod range resolves zod@3.24.x while
  zod-to-json-schema@3.25.x imports the zod/v3 subpath that only exists in
  zod>=3.25.
- container/agent-runner/src/providers/claude.ts: adds 'mcp__gmail__*' to
  TOOL_ALLOWLIST so the agent can invoke the server's tools.
- .claude/skills/add-gmail-tool/SKILL.md: pre-flight checks (OneCLI Gmail app
  connected, stubs present, mount allowlist covers ~/.gmail-mcp, agent
  secret-mode), per-group wiring in container.json (mount + mcpServers),
  verification steps, troubleshooting, removal instructions. Credits to
  gongrzhe for the MCP server and the add-atomic-chat-tool / add-vercel
  skill patterns.

Addresses #1500 (proxy Gmail OAuth through credential proxy) on the Gmail
side. Overlaps in intent with #1810 but stays surgical — no bundled
unrelated changes.

Tested end-to-end on Linux/Docker: CLI and WhatsApp self-chat agents can
list labels, search/read/send mail via OneCLI-injected tokens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 20:43:02 -04:00
gavrielc
ce28e7f558 docs(add-codex): bump CODEX_VERSION to 0.124.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 01:27:20 +03:00
gavrielc
5f3bd9c880 fix(signal): address review feedback from #1953
Correctness fixes:
- parseSignalStyles now uses a recursive walker so nested styles (e.g.
  **bold with `code` inside**) produce correct offsets against the final
  plain text. Previous impl recorded styles against intermediate text and
  didn't reindex when later passes stripped prefix characters.
- *single-asterisk* maps to ITALIC (was BOLD, divergent from standard
  Markdown). _underscore_ also maps to ITALIC.
- EchoCache keys on (platformId, text) so an outbound "hi" to Alice no
  longer drops a real "hi" inbound from Bob.
- On TCP socket close, flip adapter connected=false and log a warning so
  operators see lost daemon connections instead of silently failing sends.
- signalTcpCheck clears its 5s timeout on success so successful checks
  don't leak a setTimeout handle.

Config hygiene:
- Rename SIGNAL_HTTP_HOST/PORT to SIGNAL_TCP_HOST/PORT (transport is TCP
  JSON-RPC, not HTTP) and add SIGNAL_CLI_PATH for non-PATH installs.
- Remove unused readFileSync import.
- Log a warning in deliver() when outbound files are dropped (native
  adapter doesn't forward attachments to signal-cli yet).

Tests:
- Nested style offset correctness
- *italic* and _italic_ ITALIC mapping
- Cross-recipient echo isolation
- Same-recipient echo still suppressed
- isConnected() flips on socket close
- Outbound-files warn-and-drop path

SKILL.md realigned to the add-telegram / add-whatsapp template: fetches
from the `channels` branch (not a `skill/*` branch), lists pre-flight
idempotency checks, adds Features / Troubleshooting sections. Added
VERIFY.md and REMOVE.md siblings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 22:54:27 +03:00
Doug Daniels
c6d2f45f93 feat: add Signal channel adapter
Native Signal adapter using signal-cli TCP JSON-RPC daemon. No Chat SDK
bridge or npm dependencies — uses only Node.js builtins.

Features:
- DM and group message support
- Voice message detection (placeholder text; transcription via
  /add-voice-transcription skill)
- Typing indicators (DMs only)
- Mention detection via text match
- Managed daemon lifecycle (auto-start/stop signal-cli)
- Echo suppression for outbound messages

Also fixes init-first-agent.ts to skip channel-prefixing for phone
numbers (+...) and Signal group IDs (group:...), which are native
platform IDs that adapters send without a channel prefix.

Install via /add-signal skill. Uses /init-first-agent for channel wiring.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 15:15:42 -04:00
gavrielc
e5a7a33084 docs(add-codex): fix Dockerfile install step — separate RUN block, not combined list
The prior instruction told users to append "@openai/codex@${CODEX_VERSION}" to
a single combined `pnpm install -g` block. That block no longer exists on
main — the Dockerfile splits each global CLI (vercel, agent-browser,
claude-code) into its own RUN layer for cache granularity. Update the skill
to add a standalone RUN block for Codex that matches the existing pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 21:38:16 +03:00
gavrielc
0ec56b732d docs(add-codex): add skill for installing Codex provider from providers branch
Mirrors the /add-opencode and /add-ollama-provider pattern. Copies the
add-codex SKILL.md from the providers branch onto trunk so the skill is
discoverable without a manual branch copy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 21:35:00 +03:00
Gabi Simons
a65ee2e55c Merge branch 'main' into feat/migrate-from-v1 2026-04-23 16:38:36 +03:00
gavrielc
dd5bc85b02 refactor(skill/atomic-chat-tool): ship MCP file in skill folder, revert src edits
The initial /add-atomic-chat-tool merge added src edits directly to main.
That conflicts with the utility-skill pattern used elsewhere (e.g. /claw):
the skill folder should ship the file and SKILL.md should instruct copy +
idempotent edits at install time, not a git merge that carries src diffs.

- Move container/agent-runner/src/atomic-chat-mcp-stdio.ts →
  .claude/skills/add-atomic-chat-tool/atomic-chat-mcp-stdio.ts
- Revert the atomic_chat mcpServers entry in agent-runner index.ts
- Revert mcp__atomic_chat__* from TOOL_ALLOWLIST in providers/claude.ts
- Revert ATOMIC_CHAT_* env forwarding and [ATOMIC] log elevation in
  src/container-runner.ts
- Empty .env.example back out
- Rewrite SKILL.md: copy the shipped file, then apply deterministic Edits
  (index.ts, providers/claude.ts, container-runner.ts, .env.example)
  with exact before/after snippets the installer agent can match.

Main is now back to its pre-PR state for the tool; /add-atomic-chat-tool
re-applies everything at install time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 16:29:10 +03:00
Misha Skvortsov
3a9b98f1a4 feat: add Atomic Chat MCP tool skill
Exposes local Atomic Chat models (OpenAI-compatible API at
127.0.0.1:1337/v1) as tools to the container agent. Adds
atomic_chat_list_models and atomic_chat_generate alongside
the existing Ollama skill.

Rebased on current main:
- MCP server registered in agent-runner index.ts using bun (no tsc
  step in-image), sibling path to index.ts, env: {} with ATOMIC_CHAT_*
  forwarded when set.
- allowedTools entry moved to providers/claude.ts TOOL_ALLOWLIST.
- SKILL.md: drop obsolete per-group copy step (single RO mount
  supersedes it); use pnpm build.

Made-with: Cursor
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 16:18:34 +03:00
gabi-simons
3ee7d2147e feat: add v1 → v2 migration to setup flow (experimental)
`bash nanoclaw.sh` detects a v1 install before channel pairing and does a
best-effort automated port of operationally important state. Hands off to
a new `/migrate-from-v1` skill for owner seeding and fork customizations.

Between the timezone and channel steps, `setup/auto.ts` calls
`runMigrateV1()` which orchestrates these registered sub-steps (each a
separate entry in the progression log with its own raw log + status
block — failures never abort the chain):

- **migrate-detect** — scans siblings of the v2 checkout + common $HOME
  locations; `$NANOCLAW_V1_PATH` overrides authoritatively. Relaxed
  `package.json` check lets forks + partial installs still match; DB
  presence is the strongest signal.
- **migrate-validate** — asserts v1 DB shape (tables + required
  columns); writes `schema-mismatch.json` on failure. Subsequent steps
  short-circuit their DB-dependent parts but still run.
- **migrate-db** — seeds `agent_groups` + `messaging_groups` +
  `messaging_group_agents` from v1's `registered_groups`. JID
  decomposition (`dc:123` → `channel_type='discord'`,
  `platform_id='discord:123'`); `trigger_pattern` + `requires_trigger`
  → `engage_mode` + `engage_pattern` (mirrors migration 010 backfill).
  Users + user_roles are NOT seeded — the skill does that with an owner
  interview. Idempotent: existing rows reused, not duplicated.
- **migrate-groups** — rsync group folders. v1 `CLAUDE.md` → v2
  `CLAUDE.local.md` (v2 composes `CLAUDE.md` at container spawn); v1
  `container_config` JSON → `.v1-container-config.json` sidecar for the
  skill to translate. Tight v1-pattern scan (`/workspace/ipc/tasks`,
  `store/messages.db`, `[PR_CONTEXT:`, etc.) flags files referencing
  v1-specific infrastructure — content is NOT modified, just flagged in
  the handoff.
- **migrate-env** — merges v1 `.env` into v2 `.env`, never overwriting
  existing v2 keys.
- **migrate-channel-auth** — per-channel registry tracks v1 env keys,
  v2 required keys (with source-of-key instructions — e.g. Discord
  needs `DISCORD_PUBLIC_KEY` which v1 never stored), and candidate
  on-disk auth state paths (Baileys keystore, matrix sync state,
  etc.). Missing required v2 keys surface as actionable followups and
  flip the step to `partial`.
- **migrate-channels** — runs `setup/install-<channel>.sh` for each
  detected channel in non-interactive mode. Install-script output is
  captured to `logs/setup-migration/install-<channel>.log` sidecars
  (silent under the parent spinner). Channels with no v2 adapter get
  a `not_supported` followup but don't degrade status.
- **migrate-tasks** — v1 `scheduled_tasks` → `messages_in` rows with
  `kind='task'` in each session's `inbound.db`. `schedule_type`
  mapping (cron / interval / once → v2 cron). Idempotent: skips v1
  task ids already present. Inactive rows dumped to
  `inactive-tasks.json` for reference.

Everything writes to `logs/setup-migration/handoff.json` — the source
of truth the skill consumes.

`.claude/skills/migrate-from-v1/SKILL.md`:

- **Phase A** (always): owner seeding + v1 access policy flip
  (`unknown_sender_policy` public/strict) via `AskUserQuestion`. Pulls
  sender candidates from v1's `messages` table as hints.
- **Phase B** (if followups exist): walks
  `handoff.followups` — translates `.v1-container-config.json`
  sidecars, handles `not_supported` channels, fills in missing
  required keys with instructions on where to get them.
- **Phase C** (fork-aware): `git log <upstream>..HEAD` in v1. Empty →
  "no customizations to port." Non-empty → scope choice (mechanical /
  full interview / reference-only). Portable categories
  (`container/skills/*`, `.claude/skills/*`, docs) scan+copy with
  `scanForV1Patterns`. Non-portable (`src/*`,
  `container/agent-runner/src/*`) stash to `docs/v1-fork-reference/`
  — explicit "don't translate v1 infra to v2" warning because v1's
  IPC file queue / single DB don't exist in v2.

Clearly marked in README, CLAUDE.md, SKILL.md header, and via a `p.warn`
that fires once per run when v1 is detected. Users with no v1 install
see a silent skip — no prompts, no noise.

Verified end-to-end against a live v1 install (300 discord + 1
discord-supervisor groups, fork with ~15 commits of PR-factory work):
- Detect → validate → db (301 rows seeded) → groups (301 CLAUDE.local.md
  + 178 other files + 1 container_config sidecar) → env (4 keys copied)
  → channel-auth (flagged missing `DISCORD_APPLICATION_ID` +
  `DISCORD_PUBLIC_KEY`) → channels (discord installed, discord-supervisor
  → not_supported) → tasks (0 rows, skipped)
- Idempotent re-run: 0 rows created, 903 rows reused; tasks skip if
  id already present
- Fresh-user case: silent skip, no prompts, straight to "You're ready!"
- Schema-mismatch case: recorded to `schema-mismatch.json`, chain
  continues

- Unit tests for the pure transforms (`parseJid`,
  `inferChannelType`, `triggerToEngage`, `scanForV1Patterns`,
  `looksLikeV1Install`)
- Validate `requiredV2Keys` for telegram/slack/matrix/teams/webex/
  resend/linear against the actual Chat SDK packages (Discord was
  verified from real error output)
- Widen candidate auth file paths for WhatsApp/Matrix/iMessage based
  on real non-Discord v1 installs once we have some

See docs/v1-to-v2-changes.md for the v1 → v2 architecture diff.
2026-04-23 13:06:14 +00:00
gavrielc
469dd9af7e refactor(skills): collapse setup skill to one instruction — run bash nanoclaw.sh
Deletes the Claude-orchestrated /setup and /new-setup flows. The scripted installer (bash nanoclaw.sh → setup:auto) now handles bootstrap, container, OneCLI, auth, service, first agent, and optional channel wiring end-to-end with inline Claude-assisted recovery on failure. Keeps /setup as a one-line redirect so the trigger still resolves. Drops the opt-out diagnostics files that belonged to the old flow and updates cross-refs in add-wechat, migrate-nanoclaw, and update-nanoclaw.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 23:20:38 +03:00
Gabi Simons
52a9ab5179 feat(add-wechat): personal WeChat channel via Tencent iLink Bot API
New channel skill for personal WeChat, using Tencent's official iLink
Bot API (the same protocol @tencent-weixin/openclaw-weixin uses).
Region-restricted to mainland 微信 accounts — international WeChat
clients can't complete the QR flow.

Skill contents:
- Install steps copy the adapter from the `channels` branch (same
  pattern as other /add-<channel> skills) and register it in
  src/channels/index.ts.
- Post-login wiring helper at scripts/wire-dm.ts — lists unwired
  WeChat messaging groups, prompts for an agent group, and inserts the
  messaging_group_agents row with sender policy `request_approval` by
  default (matches the router auto-create default so the admin gets an
  approval card on the next unknown-sender DM).
- Channel Info documents how /new-setup Claude captures the
  operator's user_id (from data/wechat/auth.json.operatorUserId) and
  the first DM's platform_id (from the adapter's "WeChat inbound" log).

Also adds WeChat as option 15 in /new-setup's channel list so setup
wires into the existing /add-<channel> flow automatically.

Addresses https://github.com/qwibitai/nanoclaw/issues/1901.

Co-Authored-By: ythx-101 <226337373+ythx-101@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-21 17:21:50 +00:00
Koshkoshinsk
1f7508f2aa refactor(skills): merge /new-setup-2 into unified /new-setup
Collapses the two-phase setup into a single linear skill: steps 1-6
(prereqs through end-to-end CLI ping) run straight through, steps 7-13
(naming, timezone, channel wiring, mounts, QoL, done) are skippable.
Drops the "chat now vs. continue" branch point — after the ping the
flow emits "Test Agent success, proceeding with setup" and continues
directly into the naming questions.

Also updates stale `/new-setup-2` header comments in setup/install-*.sh.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 15:20:19 +03:00
gavrielc
40ddc94d0a Revert "fix(init-first-agent): seed welcome via inbound.db; drop --no-cli-bonus"
This reverts commit 9fe529984a.
2026-04-21 15:20:06 +03:00
gavrielc
77e6d3bc66 Revert "refactor(skills): merge /new-setup-2 into unified /new-setup"
This reverts commit 483969a194.
2026-04-21 15:20:06 +03:00
Koshkoshinsk
483969a194 refactor(skills): merge /new-setup-2 into unified /new-setup
Collapses the two-phase setup into a single linear skill: steps 1-6
(prereqs through end-to-end CLI ping) run straight through, steps 7-13
(naming, timezone, channel wiring, mounts, QoL, done) are skippable.
Drops the "chat now vs. continue" branch point — after the ping the
flow emits "Test Agent success, proceeding with setup" and continues
directly into the naming questions.

Also updates stale `/new-setup-2` header comments in setup/install-*.sh.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 10:37:06 +00:00
Koshkoshinsk
9fe529984a fix(init-first-agent): seed welcome via inbound.db; drop --no-cli-bonus
The welcome DM used to be handed to the running service over the CLI
admin socket, which stamped `cli:local` as the sender. On a strict
messaging group (any fresh DM wired by init-first-agent), that tripped
the unknown-sender approval gate — the operator's own bootstrap script
ended up requesting its own approval. Fix by writing the welcome
directly into the session's inbound.db with a `System` sender; the
running service's host-sweep wakes the container on its next pass.

Also drop `--no-cli-bonus`. Now that init-cli-agent always wires
cli/local to the scratch CLI agent, every caller of init-first-agent
had to pass --no-cli-bonus to avoid double-wiring; the flag has become
mandatory, so it's just removed. The cli-bonus branch goes with it.

Skill docs updated in lockstep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 08:50:59 +00:00
gavrielc
212fc1f1b5 docs(add-emacs): rewrite skill for copy-from-channels-branch pattern
Ports the emacs channel skill to match the other channel skills:
copy src/channels/emacs.ts + emacs/nanoclaw.el from the channels branch,
append the self-registration import, enable via EMACS_ENABLED, and wire
through the register setup step. Documents the v2 entity model (single
messaging group, platform_id="default") and drops the v1 auto-register /
symlink behavior that the old adapter did.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 10:13:36 +03:00
gavrielc
53c11a2d53 chore(skills): delete 9 irrelevant legacy skills
These shipped with the old v1 architecture and are no longer needed:

- add-reactions, add-voice-transcription, add-image-vision, add-pdf-reader,
  use-local-whisper — Chat SDK channels handle these natively now;
  the WhatsApp native (Baileys) adapter on the channels branch covers
  attachments and reactions out of the box.
- add-compact — no longer needed.
- add-telegram-swarm — Chat SDK Teams adapter handles multi-bot identity.
- channel-formatting — Chat SDK does per-channel formatting natively.
- add-gmail — was built on a legacy MCP server; deprecated.

add-emacs and use-native-credential-proxy are kept and will be ported
to the current architecture in follow-up commits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 10:13:36 +03:00