From 877d2a370a6efd9b0a7f6ab7dd1d023efc605f02 Mon Sep 17 00:00:00 2001 From: Ira Abramov Date: Thu, 7 May 2026 13:06:33 +0300 Subject: [PATCH 1/2] 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 --- .claude/skills/add-gmail-tool/SKILL.md | 9 ++++-- .claude/skills/add-opencode/SKILL.md | 13 +++++--- .claude/skills/add-signal/SKILL.md | 5 +++ .claude/skills/add-vercel/SKILL.md | 12 +++---- .claude/skills/debug/SKILL.md | 45 +++++++++++++++++++++++++- .claude/skills/init-onecli/SKILL.md | 35 ++++++++++++++++++++ 6 files changed, 104 insertions(+), 15 deletions(-) diff --git a/.claude/skills/add-gmail-tool/SKILL.md b/.claude/skills/add-gmail-tool/SKILL.md index 095c2851f..03df0e292 100644 --- a/.claude/skills/add-gmail-tool/SKILL.md +++ b/.claude/skills/add-gmail-tool/SKILL.md @@ -82,11 +82,14 @@ For each target agent group, confirm OneCLI will inject Gmail secrets into its c onecli agents list ``` -If that agent's `secretMode` is `all`, you're done — Gmail secrets (identified by OneCLI's Gmail hostPattern) will auto-inject. If it's `selective`, explicitly assign the Gmail secrets: +If that agent's `secretMode` is `all`, you're done — Gmail secrets (identified by OneCLI's Gmail hostPattern) will auto-inject. If it's `selective`, explicitly assign the Gmail secrets using the safe merge pattern (`set-secrets` replaces the entire list — always read first): ```bash -onecli secrets list # find Gmail secret IDs (OneCLI creates one per connected app) -onecli agents set-secrets --id --secret-ids +GMAIL_IDS=$(onecli secrets list | jq -r '[.data[] | select(.name | test("(?i)gmail")) | .id] | join(",")') +CURRENT=$(onecli agents secrets --id | jq -r '[.data[]] | join(",")') +MERGED=$(printf '%s' "$CURRENT,$GMAIL_IDS" | tr ',' '\n' | sort -u | paste -sd ',' -) +onecli agents set-secrets --id --secret-ids "$MERGED" +onecli agents secrets --id ``` ## Phase 2: Apply Code Changes diff --git a/.claude/skills/add-opencode/SKILL.md b/.claude/skills/add-opencode/SKILL.md index 555f0fe16..841baaa88 100644 --- a/.claude/skills/add-opencode/SKILL.md +++ b/.claude/skills/add-opencode/SKILL.md @@ -132,12 +132,15 @@ Credentials: register provider API keys in OneCLI with the matching `--host-patt After adding a secret, **grant the agent access** — agents in `selective` mode only receive secrets they've been explicitly assigned: -```bash -# Find the agent id and secret id, then: -onecli agents set-secrets --id --secret-ids , -``` +Use the safe merge pattern — `set-secrets` replaces the entire list, so always read first: -Always include existing secret IDs in the list — `set-secrets` replaces, not appends. +```bash +AGENT_ID=$(onecli agents list | jq -r '.data[] | select(.identifier=="") | .id') +CURRENT=$(onecli agents secrets --id "$AGENT_ID" | jq -r '[.data[]] | join(",")') +MERGED=$(printf '%s' "$CURRENT," | tr ',' '\n' | sort -u | paste -sd ',' -) +onecli agents set-secrets --id "$AGENT_ID" --secret-ids "$MERGED" +onecli agents secrets --id "$AGENT_ID" +``` #### Example: DeepSeek diff --git a/.claude/skills/add-signal/SKILL.md b/.claude/skills/add-signal/SKILL.md index 7dcc8ad2c..2f81b487d 100644 --- a/.claude/skills/add-signal/SKILL.md +++ b/.claude/skills/add-signal/SKILL.md @@ -284,6 +284,11 @@ If you see `Signal daemon not reachable at 127.0.0.1:7583` and `SIGNAL_MANAGE_DA 1. Channel initialized: `grep "Signal channel connected" logs/nanoclaw.log | tail -1` 2. Channel wired: `sqlite3 data/v2.db "SELECT mg.platform_id, mg.name FROM messaging_groups mg JOIN messaging_group_agents mga ON mg.id = mga.messaging_group_id WHERE mg.channel_type='signal'"` 3. Service running: `launchctl print gui/$(id -u)/com.nanoclaw` (macOS) / `systemctl --user status nanoclaw` (Linux) +4. **Check for duplicate service instances** — if `logs/nanoclaw.error.log` shows `No adapter for channel type channelType="signal"` despite the adapter starting, two NanoClaw processes are racing. See the `/debug` skill section "No adapter for channel type / Messages silently lost" for the full fix. + +### Messages delivered but never arrive (null platformMsgId) + +Signal responses show `platformMsgId=undefined` in the main log. This means the delivery poll ran but found no adapter — likely a duplicate service instance issue (see above). Affected messages cannot be retried; the user must resend. ### Lost connection mid-session diff --git a/.claude/skills/add-vercel/SKILL.md b/.claude/skills/add-vercel/SKILL.md index dbd9780b8..be3b20116 100644 --- a/.claude/skills/add-vercel/SKILL.md +++ b/.claude/skills/add-vercel/SKILL.md @@ -90,12 +90,12 @@ onecli secrets list | grep -i vercel OneCLI uses selective secret mode — secrets must be explicitly assigned to each agent. Get the Vercel secret ID from the output above, then assign it to every agent: ```bash -# For each agent, add the Vercel secret to its assigned secrets list. -# First get current assignments, then set them with the new secret appended. -VERCEL_SECRET_ID=$(onecli secrets list 2>/dev/null | grep -B2 "Vercel" | grep '"id"' | head -1 | sed 's/.*"id": "//;s/".*//') -for agent in $(onecli agents list 2>/dev/null | grep '"id"' | sed 's/.*"id": "//;s/".*//'); do - CURRENT=$(onecli agents secrets --id "$agent" 2>/dev/null | grep '"' | grep -v hint | grep -v data | sed 's/.*"//;s/".*//' | tr '\n' ',' | sed 's/,$//') - onecli agents set-secrets --id "$agent" --secret-ids "${CURRENT:+$CURRENT,}$VERCEL_SECRET_ID" +# set-secrets replaces the entire list — read and merge for each agent. +VERCEL_SECRET_ID=$(onecli secrets list | jq -r '.data[] | select(.name | test("(?i)vercel")) | .id' | head -1) +for agent in $(onecli agents list | jq -r '.data[].id'); do + CURRENT=$(onecli agents secrets --id "$agent" | jq -r '[.data[]] | join(",")') + MERGED=$(printf '%s' "$CURRENT,$VERCEL_SECRET_ID" | tr ',' '\n' | sort -u | paste -sd ',' -) + onecli agents set-secrets --id "$agent" --secret-ids "$MERGED" done ``` diff --git a/.claude/skills/debug/SKILL.md b/.claude/skills/debug/SKILL.md index 128b8c380..25c5dcf70 100644 --- a/.claude/skills/debug/SKILL.md +++ b/.claude/skills/debug/SKILL.md @@ -57,7 +57,50 @@ Debug level shows: ## Common Issues -### 1. "Claude Code process exited with code 1" +### 1. "No adapter for channel type" / Messages silently lost (null platformMsgId) + +**Symptom:** The bot stops replying. `logs/nanoclaw.error.log` shows repeated: +``` +WARN No adapter for channel type channelType="telegram" +WARN No adapter for channel type channelType="signal" +``` +The main log shows "Message delivered" entries with `platformMsgId=undefined` — meaning the delivery poll ran, found no adapter, and permanently marked the message as delivered without sending it. + +**Root cause: two NanoClaw service instances running simultaneously.** + +When a second service instance (often `nanoclaw-v2-.service` running alongside `nanoclaw.service`) is active with a stale binary, it has no channel adapters registered. Its delivery poll races against the working instance and wins — permanently marking outbound messages as delivered without ever sending them. + +**Diagnosis:** +```bash +# Check for duplicate running instances +ps aux | grep 'nanoclaw/dist/index.js' | grep -v grep + +# Check which services are active +systemctl --user list-units 'nanoclaw*' --all + +# Confirm channel adapters registered by the current process +grep "Channel adapter started" logs/nanoclaw.log | tail -10 +``` + +**Fix:** +1. Identify which service has the correct binary and EnvironmentFile (the one showing `signal`, `telegram`, `cli` all started in the log). +2. Stop and disable the stale duplicate service: + ```bash + systemctl --user stop nanoclaw.service # or whichever is the old one + systemctl --user disable nanoclaw.service + ``` +3. If the remaining service unit is missing `EnvironmentFile`, add it: + ```bash + # Edit the service unit — add this line under [Service]: + # EnvironmentFile=/home/iraa/nanoclaw/.env + systemctl --user daemon-reload + systemctl --user restart nanoclaw-v2-.service + ``` +4. Verify only one instance runs: `ps aux | grep nanoclaw/dist/index.js | grep -v grep` + +**Note:** Messages that were marked delivered with a null `platform_message_id` cannot be automatically retried — they are permanently lost. The user must resend their message. + +### 2. "Claude Code process exited with code 1" **Check the container log file** in `groups/{folder}/logs/container-*.log` diff --git a/.claude/skills/init-onecli/SKILL.md b/.claude/skills/init-onecli/SKILL.md index b3d441fd8..ab64b73df 100644 --- a/.claude/skills/init-onecli/SKILL.md +++ b/.claude/skills/init-onecli/SKILL.md @@ -259,6 +259,41 @@ Tell the user: - To manage secrets: `onecli secrets list`, or open ${ONECLI_URL} - To add rate limits or policies: `onecli rules create --help` +## Granting secrets to agents (safe merge) + +`set-secrets` **replaces** the agent's entire secret list — it never appends. Always read the current list first and merge before calling it. This pattern is canonical across all skills that assign secrets: + +```bash +AGENT_ID=$(onecli agents list | jq -r '.data[] | select(.identifier=="") | .id') +CURRENT=$(onecli agents secrets --id "$AGENT_ID" | jq -r '[.data[]] | join(",")') +MERGED=$(printf '%s' "$CURRENT," | tr ',' '\n' | sort -u | paste -sd ',' -) +onecli agents set-secrets --id "$AGENT_ID" --secret-ids "$MERGED" +onecli agents secrets --id "$AGENT_ID" +``` + +- `` — the `agentGroupId` field in `groups//container.json` +- `` — the `id` from `onecli secrets list` +- Multiple new secrets: append them comma-separated before the `printf` step + +### git over HTTPS + +OneCLI's proxy injects credentials proactively — `injections_applied=1` appears in `docker logs onecli` even when git sends no auth header. However, OneCLI sets `SSL_CERT_FILE` for Node/Python/Deno but not `GIT_SSL_CAINFO`. Without it, git rejects the OneCLI MITM certificate. + +**Auth format matters**: GitHub's git smart HTTP protocol (`github.com`) requires `Basic` auth, not `Bearer`. GitHub's REST API (`api.github.com`) accepts `Bearer`. These must be configured as separate secrets with different formats — see `/add-github` for the full setup. + +If an agent uses `git` or `gh`, add to `data/v2-sessions//.claude-shared/settings.json`: + +```json +"GIT_SSL_CAINFO": "/tmp/onecli-combined-ca.pem", +"GIT_TERMINAL_PROMPT": "0", +"GIT_CONFIG_COUNT": "1", +"GIT_CONFIG_KEY_0": "credential.helper", +"GIT_CONFIG_VALUE_0": "", +"GH_TOKEN": "ghp_onecli_proxy_replaces_this" +``` + +**Debugging injection**: `docker logs onecli 2>&1 | grep "github.com"` shows every request with `injections_applied=N` and the HTTP status. If `injections_applied=1` but status is still 401, the injected credential value is wrong or uses the wrong auth format for that endpoint. + ## Troubleshooting **"OneCLI gateway not reachable" in logs:** The gateway isn't running. Check with `curl -sf ${ONECLI_URL}/health`. Start it with `onecli start` if needed. From 1594a0c682cb2fee431bd6e565d3a7336e5e730b Mon Sep 17 00:00:00 2001 From: gavrielc Date: Fri, 8 May 2026 00:10:24 +0300 Subject: [PATCH 2/2] Apply suggestion from @gavrielc --- .claude/skills/debug/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.claude/skills/debug/SKILL.md b/.claude/skills/debug/SKILL.md index 25c5dcf70..524ff0c70 100644 --- a/.claude/skills/debug/SKILL.md +++ b/.claude/skills/debug/SKILL.md @@ -92,7 +92,7 @@ grep "Channel adapter started" logs/nanoclaw.log | tail -10 3. If the remaining service unit is missing `EnvironmentFile`, add it: ```bash # Edit the service unit — add this line under [Service]: - # EnvironmentFile=/home/iraa/nanoclaw/.env + # EnvironmentFile=/home/[user]/nanoclaw/.env systemctl --user daemon-reload systemctl --user restart nanoclaw-v2-.service ```