@openparachute/agent 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/scheduled_tasks.lock +1 -0
- package/.claude/settings.json +5 -0
- package/.claude/skills/add-atomic-chat-tool/SKILL.md +243 -0
- package/.claude/skills/add-atomic-chat-tool/atomic-chat-mcp-stdio.ts +229 -0
- package/.claude/skills/add-codex/SKILL.md +161 -0
- package/.claude/skills/add-dashboard/SKILL.md +138 -0
- package/.claude/skills/add-dashboard/resources/dashboard-pusher.ts +495 -0
- package/.claude/skills/add-emacs/SKILL.md +296 -0
- package/.claude/skills/add-gcal-tool/SKILL.md +210 -0
- package/.claude/skills/add-gchat/REMOVE.md +6 -0
- package/.claude/skills/add-gchat/SKILL.md +92 -0
- package/.claude/skills/add-gchat/VERIFY.md +3 -0
- package/.claude/skills/add-github/REMOVE.md +6 -0
- package/.claude/skills/add-github/SKILL.md +148 -0
- package/.claude/skills/add-github/VERIFY.md +3 -0
- package/.claude/skills/add-gmail-tool/SKILL.md +229 -0
- package/.claude/skills/add-imessage/REMOVE.md +6 -0
- package/.claude/skills/add-imessage/SKILL.md +113 -0
- package/.claude/skills/add-imessage/VERIFY.md +3 -0
- package/.claude/skills/add-karpathy-llm-wiki/SKILL.md +110 -0
- package/.claude/skills/add-karpathy-llm-wiki/llm-wiki.md +75 -0
- package/.claude/skills/add-linear/REMOVE.md +6 -0
- package/.claude/skills/add-linear/SKILL.md +168 -0
- package/.claude/skills/add-linear/VERIFY.md +3 -0
- package/.claude/skills/add-macos-statusbar/SKILL.md +133 -0
- package/.claude/skills/add-macos-statusbar/add/src/statusbar.swift +147 -0
- package/.claude/skills/add-matrix/REMOVE.md +6 -0
- package/.claude/skills/add-matrix/SKILL.md +148 -0
- package/.claude/skills/add-matrix/VERIFY.md +3 -0
- package/.claude/skills/add-ollama-provider/SKILL.md +179 -0
- package/.claude/skills/add-ollama-tool/SKILL.md +193 -0
- package/.claude/skills/add-opencode/SKILL.md +229 -0
- package/.claude/skills/add-parallel/SKILL.md +290 -0
- package/.claude/skills/add-resend/REMOVE.md +6 -0
- package/.claude/skills/add-resend/SKILL.md +93 -0
- package/.claude/skills/add-resend/VERIFY.md +3 -0
- package/.claude/skills/add-signal/REMOVE.md +13 -0
- package/.claude/skills/add-signal/SKILL.md +318 -0
- package/.claude/skills/add-signal/VERIFY.md +5 -0
- package/.claude/skills/add-slack/REMOVE.md +6 -0
- package/.claude/skills/add-slack/SKILL.md +112 -0
- package/.claude/skills/add-slack/VERIFY.md +3 -0
- package/.claude/skills/add-teams/REMOVE.md +6 -0
- package/.claude/skills/add-teams/SKILL.md +207 -0
- package/.claude/skills/add-teams/VERIFY.md +3 -0
- package/.claude/skills/add-vercel/SKILL.md +147 -0
- package/.claude/skills/add-vercel/container-skills/vercel-cli/SKILL.md +103 -0
- package/.claude/skills/add-webex/REMOVE.md +6 -0
- package/.claude/skills/add-webex/SKILL.md +88 -0
- package/.claude/skills/add-webex/VERIFY.md +3 -0
- package/.claude/skills/add-wechat/REMOVE.md +49 -0
- package/.claude/skills/add-wechat/SKILL.md +170 -0
- package/.claude/skills/add-wechat/scripts/wire-dm.ts +172 -0
- package/.claude/skills/add-whatsapp/SKILL.md +264 -0
- package/.claude/skills/add-whatsapp-cloud/REMOVE.md +6 -0
- package/.claude/skills/add-whatsapp-cloud/SKILL.md +95 -0
- package/.claude/skills/add-whatsapp-cloud/VERIFY.md +3 -0
- package/.claude/skills/claw/SKILL.md +131 -0
- package/.claude/skills/claw/scripts/claw +374 -0
- package/.claude/skills/convert-to-apple-container/SKILL.md +212 -0
- package/.claude/skills/customize/SKILL.md +110 -0
- package/.claude/skills/debug/SKILL.md +349 -0
- package/.claude/skills/get-qodo-rules/SKILL.md +122 -0
- package/.claude/skills/get-qodo-rules/references/output-format.md +41 -0
- package/.claude/skills/get-qodo-rules/references/pagination.md +33 -0
- package/.claude/skills/get-qodo-rules/references/repository-scope.md +26 -0
- package/.claude/skills/init-first-agent/SKILL.md +120 -0
- package/.claude/skills/init-onecli/SKILL.md +270 -0
- package/.claude/skills/manage-channels/SKILL.md +87 -0
- package/.claude/skills/manage-mounts/SKILL.md +47 -0
- package/.claude/skills/migrate-from-openclaw/MIGRATE_CRONS.md +100 -0
- package/.claude/skills/migrate-from-openclaw/SKILL.md +447 -0
- package/.claude/skills/migrate-from-openclaw/scripts/discover-openclaw.ts +734 -0
- package/.claude/skills/migrate-from-openclaw/scripts/extract-channel-credentials.ts +476 -0
- package/.claude/skills/migrate-nanoclaw/SKILL.md +484 -0
- package/.claude/skills/migrate-nanoclaw/diagnostics.md +51 -0
- package/.claude/skills/qodo-pr-resolver/SKILL.md +326 -0
- package/.claude/skills/qodo-pr-resolver/resources/providers.md +329 -0
- package/.claude/skills/update-nanoclaw/SKILL.md +243 -0
- package/.claude/skills/update-nanoclaw/diagnostics.md +48 -0
- package/.claude/skills/update-skills/SKILL.md +130 -0
- package/.claude/skills/use-native-credential-proxy/SKILL.md +167 -0
- package/.claude/skills/x-integration/SKILL.md +417 -0
- package/.claude/skills/x-integration/agent.ts +243 -0
- package/.claude/skills/x-integration/host.ts +155 -0
- package/.claude/skills/x-integration/lib/browser.ts +148 -0
- package/.claude/skills/x-integration/lib/config.ts +62 -0
- package/.claude/skills/x-integration/scripts/like.ts +56 -0
- package/.claude/skills/x-integration/scripts/post.ts +66 -0
- package/.claude/skills/x-integration/scripts/quote.ts +80 -0
- package/.claude/skills/x-integration/scripts/reply.ts +74 -0
- package/.claude/skills/x-integration/scripts/retweet.ts +62 -0
- package/.claude/skills/x-integration/scripts/setup.ts +87 -0
- package/.github/CODEOWNERS +10 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +18 -0
- package/.github/workflows/bump-version.yml +35 -0
- package/.github/workflows/ci.yml +39 -0
- package/.github/workflows/label-pr.yml +40 -0
- package/.github/workflows/update-tokens.yml +43 -0
- package/.husky/pre-commit +1 -0
- package/.mcp.json +3 -0
- package/.nvmrc +1 -0
- package/.parachute/module.json +14 -0
- package/.prettierrc +4 -0
- package/CHANGELOG.md +215 -0
- package/CLAUDE.md +307 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +159 -0
- package/CONTRIBUTORS.md +26 -0
- package/LICENSE +21 -0
- package/README.md +190 -0
- package/README_ja.md +194 -0
- package/README_zh.md +194 -0
- package/assets/nanoclaw-favicon.png +0 -0
- package/assets/nanoclaw-icon.png +0 -0
- package/assets/nanoclaw-logo-dark.png +0 -0
- package/assets/nanoclaw-logo.png +0 -0
- package/assets/nanoclaw-profile.jpeg +0 -0
- package/assets/nanoclaw-sales.png +0 -0
- package/assets/social-preview.jpg +0 -0
- package/config-examples/mount-allowlist.json +25 -0
- package/container/.dockerignore +2 -0
- package/container/CLAUDE.md +21 -0
- package/container/Dockerfile +121 -0
- package/container/agent-runner/bun.lock +243 -0
- package/container/agent-runner/package.json +22 -0
- package/container/agent-runner/scripts/sdk-signal-probe.ts +169 -0
- package/container/agent-runner/src/config.ts +55 -0
- package/container/agent-runner/src/db/connection.ts +267 -0
- package/container/agent-runner/src/db/index.ts +20 -0
- package/container/agent-runner/src/db/messages-in.ts +138 -0
- package/container/agent-runner/src/db/messages-out.ts +143 -0
- package/container/agent-runner/src/db/session-routing.ts +30 -0
- package/container/agent-runner/src/db/session-state.test.ts +100 -0
- package/container/agent-runner/src/db/session-state.ts +79 -0
- package/container/agent-runner/src/destinations.ts +135 -0
- package/container/agent-runner/src/formatter.test.ts +167 -0
- package/container/agent-runner/src/formatter.ts +260 -0
- package/container/agent-runner/src/index.ts +110 -0
- package/container/agent-runner/src/integration.test.ts +121 -0
- package/container/agent-runner/src/mcp-tools/agents.instructions.md +26 -0
- package/container/agent-runner/src/mcp-tools/agents.ts +66 -0
- package/container/agent-runner/src/mcp-tools/core.instructions.md +27 -0
- package/container/agent-runner/src/mcp-tools/core.ts +262 -0
- package/container/agent-runner/src/mcp-tools/index.ts +22 -0
- package/container/agent-runner/src/mcp-tools/interactive.instructions.md +22 -0
- package/container/agent-runner/src/mcp-tools/interactive.ts +169 -0
- package/container/agent-runner/src/mcp-tools/scheduling.instructions.md +40 -0
- package/container/agent-runner/src/mcp-tools/scheduling.ts +299 -0
- package/container/agent-runner/src/mcp-tools/self-mod.instructions.md +25 -0
- package/container/agent-runner/src/mcp-tools/self-mod.ts +120 -0
- package/container/agent-runner/src/mcp-tools/server.ts +54 -0
- package/container/agent-runner/src/mcp-tools/types.ts +6 -0
- package/container/agent-runner/src/poll-loop.test.ts +248 -0
- package/container/agent-runner/src/poll-loop.ts +437 -0
- package/container/agent-runner/src/providers/claude.ts +379 -0
- package/container/agent-runner/src/providers/factory.test.ts +19 -0
- package/container/agent-runner/src/providers/factory.ts +13 -0
- package/container/agent-runner/src/providers/index.ts +6 -0
- package/container/agent-runner/src/providers/mock.ts +77 -0
- package/container/agent-runner/src/providers/provider-registry.ts +33 -0
- package/container/agent-runner/src/providers/types.ts +82 -0
- package/container/agent-runner/src/scheduling/task-script.ts +121 -0
- package/container/agent-runner/src/timezone.test.ts +93 -0
- package/container/agent-runner/src/timezone.ts +107 -0
- package/container/agent-runner/tsconfig.json +14 -0
- package/container/build.sh +48 -0
- package/container/entrypoint.sh +16 -0
- package/container/skills/agent-browser/SKILL.md +159 -0
- package/container/skills/frontend-engineer/SKILL.md +157 -0
- package/container/skills/self-customize/SKILL.md +87 -0
- package/container/skills/slack-formatting/SKILL.md +94 -0
- package/container/skills/vercel-cli/SKILL.md +111 -0
- package/container/skills/welcome/SKILL.md +85 -0
- package/docs/APPLE-CONTAINER-NETWORKING.md +90 -0
- package/docs/BRANCH-FORK-MAINTENANCE.md +81 -0
- package/docs/README.md +25 -0
- package/docs/SDK_DEEP_DIVE.md +643 -0
- package/docs/SECURITY.md +162 -0
- package/docs/agent-runner-details.md +749 -0
- package/docs/api-details.md +365 -0
- package/docs/architecture-diagram.html +422 -0
- package/docs/architecture-diagram.md +215 -0
- package/docs/architecture.md +751 -0
- package/docs/audit/2026-04-30-channel-endpoint-audit.md +36 -0
- package/docs/build-and-runtime.md +80 -0
- package/docs/cross-mount-stress/README.md +112 -0
- package/docs/cross-mount-stress/container-writer-retry.mjs +55 -0
- package/docs/cross-mount-stress/container-writer-slow.mjs +42 -0
- package/docs/cross-mount-stress/container-writer.mjs +47 -0
- package/docs/cross-mount-stress/host-writer-retry.mjs +55 -0
- package/docs/cross-mount-stress/host-writer-slow.mjs +43 -0
- package/docs/cross-mount-stress/host-writer.mjs +47 -0
- package/docs/db-central.md +316 -0
- package/docs/db-session.md +183 -0
- package/docs/db.md +119 -0
- package/docs/design/2026-04-29-vault-management-ui.md +231 -0
- package/docs/design/2026-04-30-channel-wiring-rework.md +234 -0
- package/docs/design/2026-05-01-channel-wiring-approvals-deep-dive.md +272 -0
- package/docs/design/2026-05-02-channel-policy-and-approval-routing.md +250 -0
- package/docs/docker-sandboxes.md +359 -0
- package/docs/isolation-model.md +88 -0
- package/docs/ollama.md +79 -0
- package/docs/parachute-integration.md +109 -0
- package/docs/post-night-rebirth-reflections.md +151 -0
- package/eslint.config.js +32 -0
- package/package.json +54 -0
- package/pnpm-workspace.yaml +8 -0
- package/repo-tokens/README.md +113 -0
- package/repo-tokens/action.yml +186 -0
- package/repo-tokens/badge.svg +23 -0
- package/repo-tokens/examples/green.svg +14 -0
- package/repo-tokens/examples/red.svg +14 -0
- package/repo-tokens/examples/yellow-green.svg +14 -0
- package/repo-tokens/examples/yellow.svg +14 -0
- package/scripts/chat.ts +101 -0
- package/scripts/cleanup-sessions.sh +150 -0
- package/scripts/init-cli-agent.ts +171 -0
- package/scripts/init-first-agent.ts +377 -0
- package/scripts/parachute.ts +158 -0
- package/scripts/run-migrations.ts +105 -0
- package/scripts/sanity-live-poll.ts +95 -0
- package/scripts/seed-discord.ts +79 -0
- package/scripts/test-v2-agent.ts +106 -0
- package/scripts/test-v2-channel-e2e.ts +265 -0
- package/scripts/test-v2-host.ts +184 -0
- package/src/channels/adapter.ts +214 -0
- package/src/channels/ask-question.ts +46 -0
- package/src/channels/channel-registry.test.ts +421 -0
- package/src/channels/channel-registry.ts +313 -0
- package/src/channels/chat-sdk-bridge.test.ts +84 -0
- package/src/channels/chat-sdk-bridge.ts +652 -0
- package/src/channels/cli.ts +276 -0
- package/src/channels/discord.ts +90 -0
- package/src/channels/index.ts +17 -0
- package/src/channels/telegram-markdown-sanitize.test.ts +78 -0
- package/src/channels/telegram-markdown-sanitize.ts +55 -0
- package/src/channels/telegram-pairing.test.ts +254 -0
- package/src/channels/telegram-pairing.ts +339 -0
- package/src/channels/telegram.ts +279 -0
- package/src/channels/trust-hint.test.ts +48 -0
- package/src/channels/trust-hint.ts +75 -0
- package/src/claude-md-compose.migrate.test.ts +64 -0
- package/src/claude-md-compose.ts +205 -0
- package/src/command-gate.ts +63 -0
- package/src/config.test.ts +93 -0
- package/src/config.ts +108 -0
- package/src/container-config.ts +167 -0
- package/src/container-runner.test.ts +32 -0
- package/src/container-runner.ts +576 -0
- package/src/container-runtime.test.ts +169 -0
- package/src/container-runtime.ts +92 -0
- package/src/db/_bun-sqlite-shim.ts +88 -0
- package/src/db/agent-activity.test.ts +155 -0
- package/src/db/agent-activity.ts +121 -0
- package/src/db/agent-groups.ts +77 -0
- package/src/db/connection.migrate.test.ts +143 -0
- package/src/db/connection.ts +224 -0
- package/src/db/db-v2.test.ts +440 -0
- package/src/db/dropped-messages.ts +44 -0
- package/src/db/index.ts +40 -0
- package/src/db/messaging-groups.ts +252 -0
- package/src/db/migrations/001-initial.ts +112 -0
- package/src/db/migrations/002-chat-sdk-state.ts +36 -0
- package/src/db/migrations/008-dropped-messages.ts +27 -0
- package/src/db/migrations/009-drop-pending-credentials.ts +13 -0
- package/src/db/migrations/010-engage-modes.ts +103 -0
- package/src/db/migrations/011-pending-sender-approvals.ts +40 -0
- package/src/db/migrations/012-channel-registration.ts +48 -0
- package/src/db/migrations/013-approval-render-metadata.ts +27 -0
- package/src/db/migrations/014-secrets.ts +44 -0
- package/src/db/migrations/015-secrets-drop-host-pattern.ts +18 -0
- package/src/db/migrations/016-secret-assignments.ts +30 -0
- package/src/db/migrations/017-agent-activity.ts +40 -0
- package/src/db/migrations/018-oauth-app-configs.ts +34 -0
- package/src/db/migrations/019-oauth-app-connections.ts +48 -0
- package/src/db/migrations/020-agent-app-connections.ts +28 -0
- package/src/db/migrations/021-pending-oauth-states.ts +35 -0
- package/src/db/migrations/022-app-connections-provider.ts +25 -0
- package/src/db/migrations/023-agent-group-secret-mode.test.ts +124 -0
- package/src/db/migrations/023-agent-group-secret-mode.ts +65 -0
- package/src/db/migrations/024-collapse-approvals.test.ts +249 -0
- package/src/db/migrations/024-collapse-approvals.ts +182 -0
- package/src/db/migrations/025-secret-mode-check.test.ts +155 -0
- package/src/db/migrations/025-secret-mode-check.ts +49 -0
- package/src/db/migrations/026-user-dms-bot-id.test.ts +116 -0
- package/src/db/migrations/026-user-dms-bot-id.ts +54 -0
- package/src/db/migrations/027-provider-credentials.ts +41 -0
- package/src/db/migrations/_test-helpers.ts +41 -0
- package/src/db/migrations/index.ts +127 -0
- package/src/db/migrations/module-agent-to-agent-destinations.ts +84 -0
- package/src/db/migrations/module-approvals-pending-approvals.ts +42 -0
- package/src/db/migrations/module-approvals-title-options.ts +40 -0
- package/src/db/schema.ts +258 -0
- package/src/db/session-db.test.ts +93 -0
- package/src/db/session-db.ts +325 -0
- package/src/db/sessions.ts +241 -0
- package/src/delivery.test.ts +148 -0
- package/src/delivery.ts +445 -0
- package/src/env.ts +74 -0
- package/src/group-folder.test.ts +35 -0
- package/src/group-folder.ts +44 -0
- package/src/group-init.ts +92 -0
- package/src/host-core.test.ts +456 -0
- package/src/host-sweep.test.ts +146 -0
- package/src/host-sweep.ts +287 -0
- package/src/index.ts +227 -0
- package/src/install-slug.ts +33 -0
- package/src/log.test.ts +81 -0
- package/src/log.ts +117 -0
- package/src/mcp/http.ts +72 -0
- package/src/mcp/server.ts +92 -0
- package/src/mcp/stdio.ts +51 -0
- package/src/mcp/tools/activity.ts +88 -0
- package/src/mcp/tools/agent-groups.ts +183 -0
- package/src/mcp/tools/approvals.ts +122 -0
- package/src/mcp/tools/channels.ts +199 -0
- package/src/mcp/tools/index.ts +27 -0
- package/src/mcp/tools/oauth.ts +48 -0
- package/src/mcp/tools/secrets.ts +169 -0
- package/src/mcp/tools/sessions.ts +135 -0
- package/src/mcp/types.ts +51 -0
- package/src/modules/agent-to-agent/agent-route.test.ts +46 -0
- package/src/modules/agent-to-agent/agent-route.ts +223 -0
- package/src/modules/agent-to-agent/create-agent.ts +127 -0
- package/src/modules/agent-to-agent/db/agent-destinations.ts +135 -0
- package/src/modules/agent-to-agent/index.ts +22 -0
- package/src/modules/agent-to-agent/write-destinations.ts +59 -0
- package/src/modules/approvals/agent.md +45 -0
- package/src/modules/approvals/index.ts +21 -0
- package/src/modules/approvals/picks.test.ts +291 -0
- package/src/modules/approvals/primitive.ts +279 -0
- package/src/modules/approvals/project.md +27 -0
- package/src/modules/approvals/response-handler.ts +87 -0
- package/src/modules/index.ts +24 -0
- package/src/modules/interactive/agent.md +21 -0
- package/src/modules/interactive/index.ts +69 -0
- package/src/modules/interactive/project.md +12 -0
- package/src/modules/mount-security/index.ts +448 -0
- package/src/modules/mount-security/migrate.test.ts +91 -0
- package/src/modules/permissions/access.ts +28 -0
- package/src/modules/permissions/channel-approval.test.ts +389 -0
- package/src/modules/permissions/channel-approval.ts +188 -0
- package/src/modules/permissions/db/agent-group-members.ts +44 -0
- package/src/modules/permissions/db/pending-channel-approvals.test.ts +86 -0
- package/src/modules/permissions/db/pending-channel-approvals.ts +66 -0
- package/src/modules/permissions/db/pending-sender-approvals.ts +60 -0
- package/src/modules/permissions/db/user-dms.ts +58 -0
- package/src/modules/permissions/db/user-roles.ts +85 -0
- package/src/modules/permissions/db/users.ts +38 -0
- package/src/modules/permissions/index.ts +421 -0
- package/src/modules/permissions/permissions.test.ts +358 -0
- package/src/modules/permissions/sender-approval.test.ts +470 -0
- package/src/modules/permissions/sender-approval.ts +165 -0
- package/src/modules/permissions/user-dm.ts +200 -0
- package/src/modules/provider-credentials/db.ts +121 -0
- package/src/modules/provider-credentials/index.ts +12 -0
- package/src/modules/provider-credentials/spawn.test.ts +206 -0
- package/src/modules/provider-credentials/spawn.ts +114 -0
- package/src/modules/scheduling/actions.ts +113 -0
- package/src/modules/scheduling/db.test.ts +282 -0
- package/src/modules/scheduling/db.ts +148 -0
- package/src/modules/scheduling/index.ts +34 -0
- package/src/modules/scheduling/recurrence.test.ts +98 -0
- package/src/modules/scheduling/recurrence.ts +54 -0
- package/src/modules/self-mod/agent.md +30 -0
- package/src/modules/self-mod/apply.ts +85 -0
- package/src/modules/self-mod/index.ts +30 -0
- package/src/modules/self-mod/project.md +39 -0
- package/src/modules/self-mod/request.ts +91 -0
- package/src/modules/typing/index.ts +165 -0
- package/src/oauth/agent-app-connections.ts +103 -0
- package/src/oauth/app-configs.test.ts +64 -0
- package/src/oauth/app-configs.ts +114 -0
- package/src/oauth/app-connections.test.ts +109 -0
- package/src/oauth/app-connections.ts +178 -0
- package/src/oauth/crypto.ts +56 -0
- package/src/oauth/flow.ts +104 -0
- package/src/oauth/providers/google.test.ts +38 -0
- package/src/oauth/providers/google.ts +46 -0
- package/src/oauth/providers/index.ts +48 -0
- package/src/oauth/state-store.test.ts +54 -0
- package/src/oauth/state-store.ts +93 -0
- package/src/parachute/README.md +27 -0
- package/src/parachute/create-agent.test.ts +83 -0
- package/src/parachute/create-agent.ts +122 -0
- package/src/parachute/group-status.test.ts +165 -0
- package/src/parachute/group-status.ts +136 -0
- package/src/parachute/types.ts +41 -0
- package/src/parachute/vault-mcp.test.ts +251 -0
- package/src/parachute/vault-mcp.ts +232 -0
- package/src/platform-id.test.ts +104 -0
- package/src/platform-id.ts +109 -0
- package/src/providers/index.ts +6 -0
- package/src/providers/provider-container-registry.ts +58 -0
- package/src/response-registry.ts +45 -0
- package/src/router.ts +530 -0
- package/src/secrets/crypto.test.ts +45 -0
- package/src/secrets/crypto.ts +55 -0
- package/src/secrets/index.ts +355 -0
- package/src/secrets/master-key.ts +70 -0
- package/src/secrets/secrets.test.ts +354 -0
- package/src/session-manager.migrate.test.ts +59 -0
- package/src/session-manager.ts +433 -0
- package/src/startup-bootstrap.test.ts +226 -0
- package/src/startup-bootstrap.ts +207 -0
- package/src/state-sqlite.ts +182 -0
- package/src/timezone.test.ts +64 -0
- package/src/timezone.ts +37 -0
- package/src/types.ts +230 -0
- package/src/web/auth.test.ts +335 -0
- package/src/web/auth.ts +214 -0
- package/src/web/discord-validate.test.ts +77 -0
- package/src/web/discord-validate.ts +88 -0
- package/src/web/hub-discovery.test.ts +98 -0
- package/src/web/hub-discovery.ts +69 -0
- package/src/web/routes/activity.ts +106 -0
- package/src/web/routes/agent-provider.test.ts +282 -0
- package/src/web/routes/agent-provider.ts +309 -0
- package/src/web/routes/approvals.ts +185 -0
- package/src/web/routes/apps.ts +434 -0
- package/src/web/routes/channels-mg-detail.test.ts +324 -0
- package/src/web/routes/channels-mga-detail.test.ts +425 -0
- package/src/web/routes/channels.ts +489 -0
- package/src/web/routes/oauth-providers.ts +42 -0
- package/src/web/routes/secrets.test.ts +175 -0
- package/src/web/routes/secrets.ts +282 -0
- package/src/web/routes/sessions.ts +123 -0
- package/src/web/routes/settings.test.ts +106 -0
- package/src/web/routes/settings.ts +247 -0
- package/src/web/routes/setup-status.ts +205 -0
- package/src/web/routes/vaults.test.ts +389 -0
- package/src/web/routes/vaults.ts +225 -0
- package/src/web/server-version.test.ts +16 -0
- package/src/web/server.ts +1003 -0
- package/src/web/services-manifest.test.ts +120 -0
- package/src/web/services-manifest.ts +61 -0
- package/src/web/static-serve.test.ts +255 -0
- package/src/web/static-serve.ts +104 -0
- package/src/web/telegram-validate.test.ts +116 -0
- package/src/web/telegram-validate.ts +107 -0
- package/src/web/vault-proxy.test.ts +214 -0
- package/src/web/vault-proxy.ts +120 -0
- package/src/web/wire-channel.ts +181 -0
- package/src/webhook-server.ts +134 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +18 -0
- package/web/README.md +63 -0
- package/web/ui/index.html +13 -0
- package/web/ui/package.json +35 -0
- package/web/ui/pnpm-lock.yaml +2164 -0
- package/web/ui/scripts/verify-base.mjs +31 -0
- package/web/ui/src/App.tsx +88 -0
- package/web/ui/src/components/ActivityFeed.tsx +444 -0
- package/web/ui/src/components/AgentGroupPicker.tsx +263 -0
- package/web/ui/src/components/AgentProviderCards.tsx +220 -0
- package/web/ui/src/components/CredentialForm.tsx +214 -0
- package/web/ui/src/components/ScopeGrants.tsx +74 -0
- package/web/ui/src/components/StatusDot.tsx +43 -0
- package/web/ui/src/components/VaultPicker.tsx +127 -0
- package/web/ui/src/components/setup/AdapterInstallStep.tsx +178 -0
- package/web/ui/src/components/setup/AgentGroupStep.tsx +43 -0
- package/web/ui/src/components/setup/ChannelPickStep.tsx +74 -0
- package/web/ui/src/components/setup/DoneStep.tsx +49 -0
- package/web/ui/src/components/setup/PrereqStep.tsx +129 -0
- package/web/ui/src/components/setup/TestConnectionStep.tsx +108 -0
- package/web/ui/src/components/setup/TestMessageStep.tsx +104 -0
- package/web/ui/src/components/setup/WireChannelStep.tsx +166 -0
- package/web/ui/src/components/setup/types.ts +105 -0
- package/web/ui/src/lib/api.test.ts +410 -0
- package/web/ui/src/lib/api.ts +1210 -0
- package/web/ui/src/lib/auth.test.ts +139 -0
- package/web/ui/src/lib/auth.ts +348 -0
- package/web/ui/src/lib/channel-adapters.ts +136 -0
- package/web/ui/src/main.tsx +19 -0
- package/web/ui/src/routes/ApprovalsList.tsx +294 -0
- package/web/ui/src/routes/Apps.tsx +613 -0
- package/web/ui/src/routes/ChannelWireDetail.test.tsx +233 -0
- package/web/ui/src/routes/ChannelWireDetail.tsx +403 -0
- package/web/ui/src/routes/ChannelsList.tsx +158 -0
- package/web/ui/src/routes/GroupDetail.tsx +755 -0
- package/web/ui/src/routes/GroupList.tsx +187 -0
- package/web/ui/src/routes/MessagingGroupDetail.test.tsx +233 -0
- package/web/ui/src/routes/MessagingGroupDetail.tsx +306 -0
- package/web/ui/src/routes/NewGroupWizard.tsx +390 -0
- package/web/ui/src/routes/OAuthCallback.tsx +56 -0
- package/web/ui/src/routes/SecretsList.tsx +921 -0
- package/web/ui/src/routes/SessionsList.tsx +220 -0
- package/web/ui/src/routes/SettingsAgentProvider.tsx +109 -0
- package/web/ui/src/routes/SettingsApprovals.tsx +234 -0
- package/web/ui/src/routes/SetupWizard.tsx +219 -0
- package/web/ui/src/routes/VaultDetail.test.tsx +361 -0
- package/web/ui/src/routes/VaultDetail.tsx +960 -0
- package/web/ui/src/routes/VaultsList.tsx +295 -0
- package/web/ui/src/routes/WireChannelPage.tsx +413 -0
- package/web/ui/src/styles.css +608 -0
- package/web/ui/src/test/setup.ts +23 -0
- package/web/ui/src/vite-env.d.ts +10 -0
- package/web/ui/tsconfig.json +20 -0
- package/web/ui/vite.config.ts +34 -0
- package/web/ui/vitest.config.ts +25 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: add-github
|
|
3
|
+
description: Add GitHub channel integration via Chat SDK. PR and issue comment threads as conversations.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Add GitHub Channel
|
|
7
|
+
|
|
8
|
+
Adds GitHub support via the Chat SDK bridge. The agent participates in PR and issue comment threads.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
You need a **dedicated GitHub bot account** (not your personal account). The adapter uses this account to post replies and filters out its own messages to avoid loops. Create a free GitHub account for your bot (e.g. `my-org-bot`), then invite it as a collaborator with write access to the repos you want monitored.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
NanoClaw doesn't ship channels in trunk. This skill copies the GitHub adapter in from the `channels` branch.
|
|
17
|
+
|
|
18
|
+
### Pre-flight (idempotent)
|
|
19
|
+
|
|
20
|
+
Skip to **Credentials** if all of these are already in place:
|
|
21
|
+
|
|
22
|
+
- `src/channels/github.ts` exists
|
|
23
|
+
- `src/channels/index.ts` contains `import './github.js';`
|
|
24
|
+
- `@chat-adapter/github` is listed in `package.json` dependencies
|
|
25
|
+
|
|
26
|
+
Otherwise continue. Every step below is safe to re-run.
|
|
27
|
+
|
|
28
|
+
### 1. Fetch the channels branch
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git fetch origin channels
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Copy the adapter
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git show origin/channels:src/channels/github.ts > src/channels/github.ts
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 3. Append the self-registration import
|
|
41
|
+
|
|
42
|
+
Append to `src/channels/index.ts` (skip if the line is already present):
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import './github.js';
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 4. Install the adapter package (pinned)
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm install @chat-adapter/github@4.26.0
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 5. Build
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pnpm run build
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Credentials
|
|
61
|
+
|
|
62
|
+
### 1. Create a Personal Access Token for the bot account
|
|
63
|
+
|
|
64
|
+
Log in as your **bot account**, then:
|
|
65
|
+
|
|
66
|
+
1. Go to [Settings > Developer Settings > Personal Access Tokens](https://github.com/settings/tokens)
|
|
67
|
+
2. Create a **Fine-grained token** with:
|
|
68
|
+
- Repository access: select the repos you want the bot to monitor
|
|
69
|
+
- Permissions: **Pull requests** (Read & Write), **Issues** (Read & Write)
|
|
70
|
+
3. Copy the token
|
|
71
|
+
|
|
72
|
+
### 2. Set up a webhook on each repo
|
|
73
|
+
|
|
74
|
+
On each repo (logged in as the repo owner/admin):
|
|
75
|
+
|
|
76
|
+
1. Go to **Settings** > **Webhooks** > **Add webhook**
|
|
77
|
+
2. Payload URL: `https://your-domain/webhook/github` (the shared webhook server, default port 3000)
|
|
78
|
+
3. Content type: `application/json`
|
|
79
|
+
4. Secret: generate a random string (e.g. `openssl rand -hex 20`)
|
|
80
|
+
5. Events: select **Issue comments** and **Pull request review comments**
|
|
81
|
+
|
|
82
|
+
### 3. Configure environment
|
|
83
|
+
|
|
84
|
+
Add to `.env`:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
GITHUB_TOKEN=github_pat_...
|
|
88
|
+
GITHUB_WEBHOOK_SECRET=your-webhook-secret
|
|
89
|
+
GITHUB_BOT_USERNAME=your-bot-username
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`GITHUB_BOT_USERNAME` must match the bot account's GitHub username exactly. This is used for @-mention detection — the agent responds when someone writes `@your-bot-username` in a PR or issue comment.
|
|
93
|
+
|
|
94
|
+
Sync to container: `mkdir -p data/env && cp .env data/env/env`
|
|
95
|
+
|
|
96
|
+
## Wiring
|
|
97
|
+
|
|
98
|
+
Ask the user: **Is this a private or public repo?**
|
|
99
|
+
|
|
100
|
+
- **Private repo** — use `unknown_sender_policy: 'public'`. Only collaborators can comment anyway, so it's safe to let all comments through.
|
|
101
|
+
- **Public repo** — use `unknown_sender_policy: 'strict'`. Only registered members can trigger the agent, preventing strangers from consuming agent resources. Add trusted collaborators as members (see below).
|
|
102
|
+
|
|
103
|
+
Run `/manage-channels` to wire the GitHub channel to an agent group, or insert manually:
|
|
104
|
+
|
|
105
|
+
```sql
|
|
106
|
+
-- Create messaging group (one per repo)
|
|
107
|
+
INSERT INTO messaging_groups (id, channel_type, platform_id, name, is_group, unknown_sender_policy, created_at)
|
|
108
|
+
VALUES ('mg-github-myrepo', 'github', 'github:owner/repo', 'owner/repo', 1, '<policy>', datetime('now'));
|
|
109
|
+
|
|
110
|
+
-- Wire to agent group
|
|
111
|
+
INSERT INTO messaging_group_agents (id, messaging_group_id, agent_group_id, trigger_rules, response_scope, session_mode, priority, created_at)
|
|
112
|
+
VALUES ('mga-github-myrepo', 'mg-github-myrepo', '<your-agent-group-id>', '', 'all', 'per-thread', 10, datetime('now'));
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Replace `<policy>` with `public` or `strict` based on the user's choice above.
|
|
116
|
+
|
|
117
|
+
### Adding members (for strict mode)
|
|
118
|
+
|
|
119
|
+
When using `strict`, add each GitHub user who should be able to trigger the agent:
|
|
120
|
+
|
|
121
|
+
```sql
|
|
122
|
+
-- Add user (kind = 'github', id = 'github:<numeric-user-id>')
|
|
123
|
+
INSERT OR IGNORE INTO users (id, kind, display_name, created_at)
|
|
124
|
+
VALUES ('github:<user-id>', 'github', '<username>', datetime('now'));
|
|
125
|
+
|
|
126
|
+
-- Grant membership to the agent group
|
|
127
|
+
INSERT OR IGNORE INTO agent_group_members (user_id, agent_group_id)
|
|
128
|
+
VALUES ('github:<user-id>', '<agent-group-id>');
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
To find a GitHub user's numeric ID: `gh api users/<username> --jq .id`
|
|
132
|
+
|
|
133
|
+
Use `per-thread` session mode so each PR/issue gets its own agent session.
|
|
134
|
+
|
|
135
|
+
## Next Steps
|
|
136
|
+
|
|
137
|
+
If you're in the middle of `/setup`, return to the setup flow now.
|
|
138
|
+
|
|
139
|
+
Otherwise, restart the service (`systemctl --user restart nanoclaw` or `launchctl kickstart -k gui/$(id -u)/com.nanoclaw`) to pick up the new channel.
|
|
140
|
+
|
|
141
|
+
## Channel Info
|
|
142
|
+
|
|
143
|
+
- **type**: `github`
|
|
144
|
+
- **terminology**: GitHub has "repositories" containing "pull requests" and "issues." Each PR or issue comment thread is a separate conversation.
|
|
145
|
+
- **how-to-find-id**: The platform ID is `github:owner/repo` (e.g. `github:acme/backend`). Each PR/issue becomes its own thread automatically.
|
|
146
|
+
- **supports-threads**: yes (PR and issue comment threads are native conversations)
|
|
147
|
+
- **typical-use**: Webhook-driven — the agent receives PR and issue comment events and responds in comment threads when @-mentioned. After the first mention, the thread is subscribed and the agent responds to all follow-up comments.
|
|
148
|
+
- **default-isolation**: Use `per-thread` session mode. Each PR or issue gets its own isolated agent session. Typically wire to a dedicated agent group if the repo contains sensitive code.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: add-gmail-tool
|
|
3
|
+
description: Add Gmail as an MCP tool (read, search, send, label, draft) using OneCLI-managed OAuth. The agent gets Gmail tools in every enabled group; OneCLI injects real tokens at request time so no raw credentials are ever in the container or on disk in usable form.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Add Gmail Tool (OneCLI-native)
|
|
7
|
+
|
|
8
|
+
This skill wires the [`@gongrzhe/server-gmail-autoauth-mcp`](https://www.npmjs.com/package/@gongrzhe/server-gmail-autoauth-mcp) stdio MCP server into selected agent groups. The MCP server reads stub credentials containing the `onecli-managed` placeholder; the OneCLI gateway intercepts outbound calls to `gmail.googleapis.com` and injects the real OAuth bearer from its vault.
|
|
9
|
+
|
|
10
|
+
Tools exposed (from `gmail-mcp@1.1.11`, surfaced to the agent as `mcp__gmail__<name>`): `search_emails`, `read_email`, `send_email`, `draft_email`, `delete_email`, `modify_email`, `batch_modify_emails`, `batch_delete_emails`, `download_attachment`, `list_email_labels`, `create_label`, `update_label`, `delete_label`, `get_or_create_label`, `list_filters`, `get_filter`, `create_filter`, `create_filter_from_template`, `delete_filter`.
|
|
11
|
+
|
|
12
|
+
**Why this pattern:** v2's invariant is that containers never receive raw API keys — OneCLI is the sole credential path (see CHANGELOG v2.0.0). The stub-file pattern satisfies this: the container sees `"onecli-managed"` placeholders, the gateway swaps them in flight.
|
|
13
|
+
|
|
14
|
+
## Phase 1: Pre-flight
|
|
15
|
+
|
|
16
|
+
### Verify OneCLI has Gmail connected
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
onecli apps get --provider gmail
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Expected: `"connection": { "status": "connected" }` with scopes including `gmail.readonly`, `gmail.modify`, `gmail.send`.
|
|
23
|
+
|
|
24
|
+
If not connected, tell the user:
|
|
25
|
+
|
|
26
|
+
> Open the OneCLI web UI at http://127.0.0.1:10254, go to Apps → Gmail, and click Connect. Sign in with the Google account you want the agent to act as.
|
|
27
|
+
|
|
28
|
+
### Verify stub credentials exist
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
ls -la ~/.gmail-mcp/gcp-oauth.keys.json ~/.gmail-mcp/credentials.json 2>&1
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If both exist and contain `"onecli-managed"`:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
grep -l onecli-managed ~/.gmail-mcp/gcp-oauth.keys.json ~/.gmail-mcp/credentials.json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
...skip to Phase 2.
|
|
41
|
+
|
|
42
|
+
If either file exists but does **not** contain `onecli-managed`, **STOP** and tell the user — these are real OAuth credentials from a previous non-OneCLI install. Back them up, then delete before proceeding. The OneCLI migration normally handles this; if it didn't, something is wrong.
|
|
43
|
+
|
|
44
|
+
If both files are absent, write them now:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
mkdir -p ~/.gmail-mcp
|
|
48
|
+
cat > ~/.gmail-mcp/gcp-oauth.keys.json <<'EOF'
|
|
49
|
+
{
|
|
50
|
+
"installed": {
|
|
51
|
+
"client_id": "onecli-managed.apps.googleusercontent.com",
|
|
52
|
+
"client_secret": "onecli-managed",
|
|
53
|
+
"redirect_uris": ["http://localhost:3000/oauth2callback"]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
EOF
|
|
57
|
+
cat > ~/.gmail-mcp/credentials.json <<'EOF'
|
|
58
|
+
{
|
|
59
|
+
"access_token": "onecli-managed",
|
|
60
|
+
"refresh_token": "onecli-managed",
|
|
61
|
+
"token_type": "Bearer",
|
|
62
|
+
"expiry_date": 99999999999999,
|
|
63
|
+
"scope": "https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.modify https://www.googleapis.com/auth/gmail.send"
|
|
64
|
+
}
|
|
65
|
+
EOF
|
|
66
|
+
chmod 600 ~/.gmail-mcp/gcp-oauth.keys.json ~/.gmail-mcp/credentials.json
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Verify mount allowlist covers the path
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cat ~/.config/nanoclaw/mount-allowlist.json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`~/.gmail-mcp` must sit under an `allowedRoots` entry (e.g. `/home/<user>`). If it doesn't, tell the user to run `/manage-mounts` first or add their home directory.
|
|
76
|
+
|
|
77
|
+
### Check agent secret-mode
|
|
78
|
+
|
|
79
|
+
For each target agent group, confirm OneCLI will inject Gmail secrets into its container. Find the OneCLI agent ID that matches the group's `agentGroupId`:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
onecli agents list
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
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:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
onecli secrets list # find Gmail secret IDs (OneCLI creates one per connected app)
|
|
89
|
+
onecli agents set-secrets --id <agent-id> --secret-ids <gmail-secret-id>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Phase 2: Apply Code Changes
|
|
93
|
+
|
|
94
|
+
### Check if already applied
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
grep -q 'GMAIL_MCP_VERSION' container/Dockerfile && \
|
|
98
|
+
grep -q "mcp__gmail__\*" container/agent-runner/src/providers/claude.ts && \
|
|
99
|
+
echo "ALREADY APPLIED — skip to Phase 3"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Add MCP server to Dockerfile
|
|
103
|
+
|
|
104
|
+
Edit `container/Dockerfile`. Find the pinned-version ARG block:
|
|
105
|
+
|
|
106
|
+
```dockerfile
|
|
107
|
+
ARG CLAUDE_CODE_VERSION=2.1.116
|
|
108
|
+
ARG AGENT_BROWSER_VERSION=latest
|
|
109
|
+
ARG VERCEL_VERSION=latest
|
|
110
|
+
ARG BUN_VERSION=1.3.12
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Add a new line:
|
|
114
|
+
|
|
115
|
+
```dockerfile
|
|
116
|
+
ARG GMAIL_MCP_VERSION=1.1.11
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Then find the last pnpm global-install `RUN` block (the one that installs `@anthropic-ai/claude-code`) and add a new block after it, before `# ---- Entrypoint`:
|
|
120
|
+
|
|
121
|
+
```dockerfile
|
|
122
|
+
RUN --mount=type=cache,target=/root/.cache/pnpm \
|
|
123
|
+
pnpm install -g \
|
|
124
|
+
"@gongrzhe/server-gmail-autoauth-mcp@${GMAIL_MCP_VERSION}" \
|
|
125
|
+
"zod-to-json-schema@3.22.5"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Pinned version matters — `minimumReleaseAge` in `pnpm-workspace.yaml` gates trunk installs, and CLAUDE.md requires a fixed ARG version for all Node CLIs installed into the image.
|
|
129
|
+
|
|
130
|
+
**Why the `zod-to-json-schema` pin:** `@gongrzhe/server-gmail-autoauth-mcp@1.1.11` has loose deps (`zod-to-json-schema: ^3.22.1`, `zod: ^3.22.4`). pnpm resolves `zod-to-json-schema` to the latest 3.25.x, which imports `zod/v3` — a subpath that only exists in `zod>=3.25`. But `zod` resolves to `3.24.x` (highest satisfying `^3.22.4` without breaking peer ranges). Result: `ERR_PACKAGE_PATH_NOT_EXPORTED` at import time. Pinning `zod-to-json-schema` to a pre-v3-subpath version avoids it. Re-check if you bump `GMAIL_MCP_VERSION`.
|
|
131
|
+
|
|
132
|
+
### Add tools to allowlist
|
|
133
|
+
|
|
134
|
+
Edit `container/agent-runner/src/providers/claude.ts`. Find `'mcp__nanoclaw__*',` in `TOOL_ALLOWLIST` and add `'mcp__gmail__*',` after it.
|
|
135
|
+
|
|
136
|
+
### Rebuild the container image
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
./container/build.sh
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Must complete cleanly. The new `pnpm install -g` layer is ~60s first time (cached on rebuild).
|
|
143
|
+
|
|
144
|
+
## Phase 3: Wire Per-Agent-Group
|
|
145
|
+
|
|
146
|
+
For each agent group that should have Gmail (ask the user — typically their personal DM and CLI agents, sometimes shared household agents), edit `groups/<folder>/container.json` to add the mount and MCP server.
|
|
147
|
+
|
|
148
|
+
Merge these into the group's `container.json`:
|
|
149
|
+
|
|
150
|
+
```jsonc
|
|
151
|
+
{
|
|
152
|
+
"mcpServers": {
|
|
153
|
+
"gmail": {
|
|
154
|
+
"command": "gmail-mcp",
|
|
155
|
+
"args": [],
|
|
156
|
+
"env": {
|
|
157
|
+
"GMAIL_OAUTH_PATH": "/workspace/extra/.gmail-mcp/gcp-oauth.keys.json",
|
|
158
|
+
"GMAIL_CREDENTIALS_PATH": "/workspace/extra/.gmail-mcp/credentials.json"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"additionalMounts": [
|
|
163
|
+
{
|
|
164
|
+
"hostPath": "/home/<user>/.gmail-mcp",
|
|
165
|
+
"containerPath": ".gmail-mcp",
|
|
166
|
+
"readonly": false
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Substitute `<user>` with the host user's home (use `echo $HOME`, don't assume `~` will expand — `container-runner.ts` does expand `~` via `expandPath`, but an explicit absolute path is clearer and matches what `/manage-mounts` writes).
|
|
173
|
+
|
|
174
|
+
**Why the container path is relative:** `mount-security` rejects absolute `containerPath` values. Additional mounts are prefixed with `/workspace/extra/`, so `containerPath: ".gmail-mcp"` lands at `/workspace/extra/.gmail-mcp`. The MCP server's `GMAIL_OAUTH_PATH` / `GMAIL_CREDENTIALS_PATH` env vars point at that absolute location inside the container.
|
|
175
|
+
|
|
176
|
+
## Phase 4: Build and Restart
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
pnpm run build
|
|
180
|
+
systemctl --user restart nanoclaw # Linux
|
|
181
|
+
# launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Phase 5: Verify
|
|
185
|
+
|
|
186
|
+
### Test from the wired agent
|
|
187
|
+
|
|
188
|
+
Tell the user:
|
|
189
|
+
|
|
190
|
+
> In your `<agent-name>` chat, send: **"list my gmail labels"** or **"search my inbox for invoices from last month"**.
|
|
191
|
+
>
|
|
192
|
+
> The agent should use `mcp__gmail__list_labels` / `mcp__gmail__search`. The first call may take a second or two while the MCP server starts and OneCLI does the token exchange.
|
|
193
|
+
|
|
194
|
+
### Check logs if the tool isn't working
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
tail -100 logs/nanoclaw.log logs/nanoclaw.error.log | grep -iE 'gmail|mcp'
|
|
198
|
+
# Per-container logs — session-scoped:
|
|
199
|
+
ls data/v2-sessions/*/stderr.log | head
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Common signals:
|
|
203
|
+
- `command not found: gmail-mcp` → image wasn't rebuilt or PATH doesn't include `/pnpm` (should — `ENV PATH="$PNPM_HOME:$PATH"` in Dockerfile).
|
|
204
|
+
- `ENOENT: no such file or directory, open '/workspace/extra/.gmail-mcp/credentials.json'` → mount is missing. Check `~/.config/nanoclaw/mount-allowlist.json` includes a parent of `~/.gmail-mcp`.
|
|
205
|
+
- `401 Unauthorized` from `gmail.googleapis.com` → OneCLI isn't injecting. Check the agent's secret mode (`onecli agents secrets --id <agent-id>`) and that the Gmail app is connected (`onecli apps get --provider gmail`).
|
|
206
|
+
- Agent says "I don't have Gmail tools" → `mcp__gmail__*` wasn't added to `TOOL_ALLOWLIST`, or the agent-runner wasn't rebuilt (image cache — run `./container/build.sh` again with `--no-cache` if suspicious).
|
|
207
|
+
|
|
208
|
+
## Removal
|
|
209
|
+
|
|
210
|
+
1. Delete the `"gmail"` entry from `mcpServers` and the `.gmail-mcp` entry from `additionalMounts` in each group's `container.json`.
|
|
211
|
+
2. Remove `'mcp__gmail__*'` from `TOOL_ALLOWLIST` in `container/agent-runner/src/providers/claude.ts`.
|
|
212
|
+
3. Remove the `GMAIL_MCP_VERSION` ARG and the `pnpm install -g @gongrzhe/server-gmail-autoauth-mcp` block from `container/Dockerfile`.
|
|
213
|
+
4. `pnpm run build && ./container/build.sh && systemctl --user restart nanoclaw`.
|
|
214
|
+
5. (Optional) `rm -rf ~/.gmail-mcp/` if no other host-side tool needs the stubs.
|
|
215
|
+
6. (Optional) Disconnect Gmail in OneCLI: `onecli apps disconnect --provider gmail`.
|
|
216
|
+
|
|
217
|
+
## Notes
|
|
218
|
+
|
|
219
|
+
- **Stub format is OneCLI-prescribed.** The `access_token: "onecli-managed"` pattern with `expiry_date: 99999999999999` tells the Google auth client the token is valid; OneCLI intercepts the outgoing Gmail API call and rewrites `Authorization: Bearer onecli-managed` to the real token. `expiry_date: 0` (refresh-interception) is an alternative the OneCLI docs describe — both work but OneCLI's own `migrate` command writes the far-future variant, which is what this skill assumes.
|
|
220
|
+
- **Scopes are set at OAuth connect time.** If the agent needs scopes beyond what's currently connected (e.g. the user later wants `calendar.readonly` for combined email/calendar workflows), disconnect and reconnect Gmail in the OneCLI web UI with the expanded scope set.
|
|
221
|
+
- **This is tool-only.** Inbound email as a channel (emails trigger the agent) is a separate piece of work — it needs a `src/channels/gmail.ts` adapter that polls the inbox and routes to a messaging group. The pre-v2 qwibitai skill had this; it has not been ported to v2's channel architecture as of v2.0.0.
|
|
222
|
+
|
|
223
|
+
## Credits & references
|
|
224
|
+
|
|
225
|
+
- **MCP server:** [`@gongrzhe/server-gmail-autoauth-mcp`](https://github.com/GongRzhe/Gmail-MCP-Server) by GongRzhe — MIT-licensed.
|
|
226
|
+
- **OneCLI credential stubs:** pattern documented at `https://onecli.sh/docs/guides/credential-stubs/gmail.md`.
|
|
227
|
+
- **Skill pattern:** modeled on [`add-atomic-chat-tool`](../add-atomic-chat-tool/SKILL.md) and [`add-vercel`](../add-vercel/SKILL.md).
|
|
228
|
+
- **Addresses:** [issue #1500](https://github.com/qwibitai/nanoclaw/issues/1500) (proxy Gmail/Calendar OAuth tokens through credential proxy) for the Gmail side.
|
|
229
|
+
- **Related PRs:** [#1810](https://github.com/qwibitai/nanoclaw/pull/1810) (pre-install Gmail/Notion MCP) overlaps on the "install the MCP server in the image" idea but bundles many unrelated changes; this skill is the focused OneCLI-native version.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Remove iMessage Channel
|
|
2
|
+
|
|
3
|
+
1. Comment out `import './imessage.js'` in `src/channels/index.ts`
|
|
4
|
+
2. Remove iMessage env vars (`IMESSAGE_ENABLED`, `IMESSAGE_LOCAL`, `IMESSAGE_SERVER_URL`, `IMESSAGE_API_KEY`) from `.env`
|
|
5
|
+
3. `pnpm uninstall chat-adapter-imessage`
|
|
6
|
+
4. Rebuild and restart
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: add-imessage
|
|
3
|
+
description: Add iMessage channel integration via Chat SDK. Local (macOS) or remote (Photon API) mode.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Add iMessage Channel
|
|
7
|
+
|
|
8
|
+
Adds iMessage support via the Chat SDK bridge. Two modes: local (macOS with Full Disk Access) or remote (Photon API).
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
NanoClaw doesn't ship channels in trunk. This skill copies the iMessage adapter in from the `channels` branch.
|
|
13
|
+
|
|
14
|
+
### Pre-flight (idempotent)
|
|
15
|
+
|
|
16
|
+
Skip to **Credentials** if all of these are already in place:
|
|
17
|
+
|
|
18
|
+
- `src/channels/imessage.ts` exists
|
|
19
|
+
- `src/channels/index.ts` contains `import './imessage.js';`
|
|
20
|
+
- `chat-adapter-imessage` is listed in `package.json` dependencies
|
|
21
|
+
|
|
22
|
+
Otherwise continue. Every step below is safe to re-run.
|
|
23
|
+
|
|
24
|
+
### 1. Fetch the channels branch
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git fetch origin channels
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Copy the adapter
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git show origin/channels:src/channels/imessage.ts > src/channels/imessage.ts
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 3. Append the self-registration import
|
|
37
|
+
|
|
38
|
+
Append to `src/channels/index.ts` (skip if the line is already present):
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import './imessage.js';
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 4. Install the adapter package (pinned)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm install chat-adapter-imessage@0.1.1
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 5. Build
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pnpm run build
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Credentials
|
|
57
|
+
|
|
58
|
+
### Local Mode (macOS)
|
|
59
|
+
|
|
60
|
+
Requirements: macOS with Full Disk Access granted to the Node.js binary.
|
|
61
|
+
|
|
62
|
+
The Node binary path is buried deep (e.g. `~/.nvm/versions/node/v22.x.x/bin/node`). To make it easy, open the folder in Finder so the user can drag the file into System Settings:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
open "$(dirname "$(which node)")"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Then tell the user:
|
|
69
|
+
|
|
70
|
+
1. Open **System Settings** > **Privacy & Security** > **Full Disk Access**
|
|
71
|
+
2. Click **+**, then drag the `node` file from the Finder window that just opened
|
|
72
|
+
3. Toggle it on
|
|
73
|
+
|
|
74
|
+
Stop and wait for the user to confirm before continuing.
|
|
75
|
+
|
|
76
|
+
### Remote Mode (Photon API)
|
|
77
|
+
|
|
78
|
+
1. Set up a [Photon](https://photon.im) account
|
|
79
|
+
2. Get your server URL and API key
|
|
80
|
+
|
|
81
|
+
### Configure environment
|
|
82
|
+
|
|
83
|
+
**Local mode** -- add to `.env`:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
IMESSAGE_ENABLED=true
|
|
87
|
+
IMESSAGE_LOCAL=true
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Remote mode** -- add to `.env`:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
IMESSAGE_LOCAL=false
|
|
94
|
+
IMESSAGE_SERVER_URL=https://your-photon-server.com
|
|
95
|
+
IMESSAGE_API_KEY=your-api-key
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Sync to container: `mkdir -p data/env && cp .env data/env/env`
|
|
99
|
+
|
|
100
|
+
## Next Steps
|
|
101
|
+
|
|
102
|
+
If you're in the middle of `/setup`, return to the setup flow now.
|
|
103
|
+
|
|
104
|
+
Otherwise, run `/manage-channels` to wire this channel to an agent group.
|
|
105
|
+
|
|
106
|
+
## Channel Info
|
|
107
|
+
|
|
108
|
+
- **type**: `imessage`
|
|
109
|
+
- **terminology**: iMessage has "conversations." Each conversation is with a contact identified by phone number or email address. Group chats are also supported.
|
|
110
|
+
- **how-to-find-id**: The platform ID is the contact's phone number (e.g. `+15551234567`) or email address. For group chats, the ID is assigned by iMessage internally.
|
|
111
|
+
- **supports-threads**: no
|
|
112
|
+
- **typical-use**: Interactive 1:1 chat — personal messaging
|
|
113
|
+
- **default-isolation**: Same agent group if you're the only person messaging the bot across iMessage and other channels. Separate agent group if different contacts should have information isolation.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: add-karpathy-llm-wiki
|
|
3
|
+
description: Add a persistent wiki knowledge base to a NanoClaw group. Based on Karpathy's LLM Wiki pattern. Triggers on "add wiki", "wiki", "knowledge base", "llm wiki", "karpathy wiki".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Add Karpathy LLM Wiki
|
|
7
|
+
|
|
8
|
+
Set up a persistent wiki knowledge base on NanoClaw, based on Karpathy's LLM Wiki pattern.
|
|
9
|
+
|
|
10
|
+
## Step 1: Read the pattern
|
|
11
|
+
|
|
12
|
+
Read `${CLAUDE_SKILL_DIR}/llm-wiki.md` — this is the full LLM Wiki idea as written by Karpathy. Understand it thoroughly before proceeding. Summarize the core idea to the user briefly, then discuss what they want to build.
|
|
13
|
+
|
|
14
|
+
## Step 2: Choose a group
|
|
15
|
+
|
|
16
|
+
AskUserQuestion: "Which group should have the wiki?"
|
|
17
|
+
|
|
18
|
+
1. **Main group** — add to your existing main chat
|
|
19
|
+
2. **Dedicated group** — create a new group just for the wiki
|
|
20
|
+
3. **Other** — pick an existing group
|
|
21
|
+
|
|
22
|
+
If dedicated: ask which channel and chat, then register with `pnpm exec tsx setup/index.ts --step register`.
|
|
23
|
+
|
|
24
|
+
## Step 3: Design collaboratively
|
|
25
|
+
|
|
26
|
+
Discuss with the user based on the pattern:
|
|
27
|
+
- What's the wiki's domain or topic?
|
|
28
|
+
- What kinds of sources will they add? (URLs, PDFs, images, voice notes, books, transcripts)
|
|
29
|
+
- Do they want the full three-layer architecture or a lighter version?
|
|
30
|
+
- Any specific conventions they care about? (The pattern intentionally leaves this open.)
|
|
31
|
+
|
|
32
|
+
Based on this discussion, create three things:
|
|
33
|
+
|
|
34
|
+
### 3a. Directory structure
|
|
35
|
+
|
|
36
|
+
Create `wiki/` and `sources/` directories in the group folder. Create initial `index.md` and `log.md` per the pattern's Indexing and Logging section. Adapt to the user's domain.
|
|
37
|
+
|
|
38
|
+
### 3b. Container skill
|
|
39
|
+
|
|
40
|
+
Create a `container/skills/wiki/SKILL.md` tailored to this user's wiki. This is the schema layer from the pattern — it tells the agent how to maintain the wiki. Base it on the pattern's Operations section (ingest, query, lint) and the conventions you agreed on with the user. Don't over-prescribe — the pattern says "your LLM figures out the rest."
|
|
41
|
+
|
|
42
|
+
### 3c. Group CLAUDE.md
|
|
43
|
+
|
|
44
|
+
Edit the group's CLAUDE.md to add a wiki section. This is critical — it's what turns the agent into a wiki maintainer. It should:
|
|
45
|
+
|
|
46
|
+
- Explain the wiki system concisely: what it is, the three layers (sources, wiki, schema), the three operations (ingest, query, lint)
|
|
47
|
+
- Index the key files and folders (`wiki/`, `sources/`, `wiki/index.md`, `wiki/log.md`)
|
|
48
|
+
- Point to the container skill for detailed workflow
|
|
49
|
+
- **Ingest discipline:** Be very explicit that when the user provides multiple files or points at a folder with many files, the agent MUST process them one at a time. For each file: read it, discuss takeaways, create/update all wiki pages (summary, entities, concepts, cross-references, index, log), and completely finish with that file before moving to the next. Never batch-read all files and then process them together — this produces shallow, generic pages instead of the deep integration the pattern requires.
|
|
50
|
+
|
|
51
|
+
## Step 4: Source handling capabilities
|
|
52
|
+
|
|
53
|
+
Based on the source types the user plans to ingest (discussed in Step 3), check whether the agent can already handle those formats — some are supported natively, others need a skill (e.g. `/add-image-vision`, `/add-pdf-reader`, `/add-voice-transcription`). If a needed capability isn't installed, check if there's an available skill for it and help the user get it set up.
|
|
54
|
+
|
|
55
|
+
### URL handling note
|
|
56
|
+
|
|
57
|
+
claude has built-in `WebFetch`, but it returns a summary, not the full document. For wiki ingestion of a URL where the full text matters, the container skill and CLAUDE.md should instruct claude to use bash commands to download full files instead. For example:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
curl -sLo sources/filename.pdf "<url>"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If the document is a webpage, then claude can use fetch or `agent-browser` to open the page and extract full text if available. The container skill and CLAUDE.md should note this so claude gets full content for sources rather than summaries.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Step 5: Optional lint schedule
|
|
67
|
+
|
|
68
|
+
AskUserQuestion: "Want periodic wiki health checks?"
|
|
69
|
+
|
|
70
|
+
1. **Weekly**
|
|
71
|
+
2. **Monthly**
|
|
72
|
+
3. **Skip** — lint manually
|
|
73
|
+
|
|
74
|
+
If yes, create a NanoClaw scheduled task that runs in the wiki group. This is NOT a Claude Code cron job — it's a NanoClaw group task that runs in the agent container. Insert it into the SQLite database:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pnpm exec tsx -e "
|
|
78
|
+
const Database = require('better-sqlite3');
|
|
79
|
+
const { CronExpressionParser } = require('cron-parser');
|
|
80
|
+
const db = new Database('store/messages.db');
|
|
81
|
+
const interval = CronExpressionParser.parse('<cron-expr>', { tz: process.env.TZ || 'UTC' });
|
|
82
|
+
const nextRun = interval.next().toISOString();
|
|
83
|
+
db.prepare('INSERT INTO scheduled_tasks (id, group_folder, chat_jid, prompt, schedule_type, schedule_value, context_mode, next_run, status, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').run(
|
|
84
|
+
'wiki-lint',
|
|
85
|
+
'<group_folder>',
|
|
86
|
+
'<chat_jid>',
|
|
87
|
+
'Run a wiki lint pass per the wiki container skill. Check for contradictions, orphan pages, stale content, missing cross-references, and gaps. Report findings and offer to fix issues.',
|
|
88
|
+
'cron',
|
|
89
|
+
'<cron-expr>',
|
|
90
|
+
'group',
|
|
91
|
+
nextRun,
|
|
92
|
+
'active',
|
|
93
|
+
new Date().toISOString()
|
|
94
|
+
);
|
|
95
|
+
db.close();
|
|
96
|
+
"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Use the group's `folder` and `chat_jid` from the registered groups table. Cron expressions: `0 10 * * 0` (weekly Sunday 10am) or `0 10 1 * *` (monthly 1st at 10am).
|
|
100
|
+
|
|
101
|
+
## Step 6: Build and restart
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pnpm run build
|
|
105
|
+
./container/build.sh
|
|
106
|
+
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
|
|
107
|
+
# Linux: systemctl --user restart nanoclaw
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Tell the user to test by sending a source to the wiki group.
|