@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
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# ⚠️ STOP — READ THIS FIRST IF YOU ARE CLAUDE ⚠️
|
|
2
|
+
|
|
3
|
+
**If you are reading this because you just ran `git pull`, `git merge`, `git fetch && git merge`, or any equivalent to bring in upstream changes — and you see merge conflicts or a large diff involving this file — HALT IMMEDIATELY.**
|
|
4
|
+
|
|
5
|
+
This is parachute-agent (formerly paraclaw), a ground-up rewrite with breaking changes throughout. It cannot be merged into an existing NanoClaw v1 install. Attempting to resolve the conflicts by hand, run builds, or "fix" anything will corrupt the user's install and burn tokens for no result.
|
|
6
|
+
|
|
7
|
+
**Do this instead:**
|
|
8
|
+
1. Abort the merge: `git merge --abort` (or `git reset --hard ORIG_HEAD` if the merge already completed).
|
|
9
|
+
2. Tell the user, verbatim: *"This is parachute-agent — it can't be merged into your existing NanoClaw install. Run `bash migrate-v2.sh` to migrate instead."*
|
|
10
|
+
3. Wait for the user to confirm before doing anything else. Do not attempt the migration yourself.
|
|
11
|
+
|
|
12
|
+
If you are a fresh install (you ran `git clone`, not `git pull`) and there are no conflicts, ignore this banner and continue below.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# parachute-agent
|
|
17
|
+
|
|
18
|
+
Parachute's per-session containerized AI agent companion. (Formerly **paraclaw**, renamed in 0.1.0.) See [README.md](README.md) for philosophy and setup. Architecture lives in `docs/`.
|
|
19
|
+
|
|
20
|
+
## Quick Context
|
|
21
|
+
|
|
22
|
+
The host is a single Node process that orchestrates per-session agent containers. Platform messages land via channel adapters, route through an entity model (users → messaging groups → agent groups → sessions), get written into the session's inbound DB, and wake a container. The agent-runner inside the container polls the DB, calls Claude, and writes back to the outbound DB. The host polls the outbound DB and delivers through the same adapter.
|
|
23
|
+
|
|
24
|
+
**Everything is a message.** There is no IPC, no file watcher, no stdin piping between host and container. The two session DBs are the sole IO surface.
|
|
25
|
+
|
|
26
|
+
## Entity Model
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
users (id "<channel>:<handle>", kind, display_name)
|
|
30
|
+
user_roles (user_id, role, agent_group_id) — owner | admin (global or scoped)
|
|
31
|
+
agent_group_members (user_id, agent_group_id) — unprivileged access gate
|
|
32
|
+
user_dms (user_id, channel_type, messaging_group_id) — cold-DM cache
|
|
33
|
+
|
|
34
|
+
agent_groups (workspace, memory, CLAUDE.md, personality, container config)
|
|
35
|
+
↕ many-to-many via messaging_group_agents (session_mode, trigger_rules, priority)
|
|
36
|
+
messaging_groups (one chat/channel on one platform; unknown_sender_policy)
|
|
37
|
+
|
|
38
|
+
sessions (agent_group_id + messaging_group_id + thread_id → per-session container)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Privilege is user-level (owner/admin), not agent-group-level. See [docs/isolation-model.md](docs/isolation-model.md) for the three isolation levels (`agent-shared`, `shared`, separate agents).
|
|
42
|
+
|
|
43
|
+
## Two-DB Session Split
|
|
44
|
+
|
|
45
|
+
Each session has **two** SQLite files under `data/sessions/<agent_group_id>/<session_id>/`:
|
|
46
|
+
|
|
47
|
+
- `inbound.db` — host writes, container reads. `messages_in`, routing, destinations, pending_questions, processing_ack.
|
|
48
|
+
- `outbound.db` — container writes, host reads. `messages_out`, session_state.
|
|
49
|
+
|
|
50
|
+
Exactly one writer per file — no cross-mount lock contention. Heartbeat is a file touch at `/workspace/.heartbeat`, not a DB update. Host uses even `seq` numbers, container uses odd.
|
|
51
|
+
|
|
52
|
+
## Central DB
|
|
53
|
+
|
|
54
|
+
`data/v2.db` holds everything that isn't per-session: users, user_roles, agent_groups, messaging_groups, wiring, pending_approvals, user_dms, chat_sdk_* (for the Chat SDK bridge), schema_version. Migrations live at `src/db/migrations/`.
|
|
55
|
+
|
|
56
|
+
## Key Files
|
|
57
|
+
|
|
58
|
+
| File | Purpose |
|
|
59
|
+
|------|---------|
|
|
60
|
+
| `src/index.ts` | Entry point: init DB, migrations, channel adapters, delivery polls, sweep, shutdown |
|
|
61
|
+
| `src/router.ts` | Inbound routing: messaging group → agent group → session → `inbound.db` → wake |
|
|
62
|
+
| `src/delivery.ts` | Polls `outbound.db`, delivers via adapter, handles system actions (schedule, approvals, etc.) |
|
|
63
|
+
| `src/host-sweep.ts` | 60s sweep: `processing_ack` sync, stale detection, due-message wake, recurrence |
|
|
64
|
+
| `src/session-manager.ts` | Resolves sessions; opens `inbound.db` / `outbound.db`; manages heartbeat path |
|
|
65
|
+
| `src/container-runner.ts` | Spawns per-agent-group Docker containers with session DB + outbox mounts, decrypts + injects assigned secrets |
|
|
66
|
+
| `src/container-runtime.ts` | Runtime selection (Docker vs Apple containers), orphan cleanup |
|
|
67
|
+
| `src/modules/permissions/access.ts` | `canAccessAgentGroup` — owner / global admin / scoped admin / member resolution against `user_roles` + `agent_group_members` |
|
|
68
|
+
| `src/modules/approvals/primitive.ts` | `pickApprover`, `pickApprovalDelivery`, `requestApproval`, approval-handler registry |
|
|
69
|
+
| `src/command-gate.ts` | Router-side admin command gate — queries `user_roles` directly (no env var, no container-side check) |
|
|
70
|
+
| `src/secrets/` | AES-GCM secret store: master key on disk + ciphertext in central DB, scoped per agent group |
|
|
71
|
+
| `src/user-dm.ts` | Cold-DM resolution + `user_dms` cache |
|
|
72
|
+
| `src/group-init.ts` | Per-agent-group filesystem scaffold (CLAUDE.md, skills, agent-runner-src overlay) |
|
|
73
|
+
| `src/db/` | DB layer — agent_groups, messaging_groups, sessions, user_roles, user_dms, pending_*, migrations |
|
|
74
|
+
| `src/channels/` | Channel adapter infra (registry, Chat SDK bridge) plus the trunk-baked Discord and Telegram adapters; other channels are skill-installed from the `channels` branch |
|
|
75
|
+
| `src/providers/` | Host-side provider container-config (`claude` baked in; `opencode` etc. installed from the `providers` branch) |
|
|
76
|
+
| `container/agent-runner/src/` | Agent-runner: poll loop, formatter, provider abstraction, MCP tools, destinations |
|
|
77
|
+
| `container/skills/` | Container skills mounted into every agent session |
|
|
78
|
+
| `groups/<folder>/` | Per-agent-group filesystem (CLAUDE.md, skills, per-group `agent-runner-src/` overlay) |
|
|
79
|
+
| `scripts/init-first-agent.ts` | Bootstrap the first DM-wired agent (used by `/init-first-agent` skill) |
|
|
80
|
+
|
|
81
|
+
## Channels and Providers
|
|
82
|
+
|
|
83
|
+
Trunk bakes in the two adapters needed for the `/channels/new` fast path — **Discord** (`src/channels/discord.ts`) and **Telegram** (`src/channels/telegram.ts`) — along with their token validators (`src/web/{discord,telegram}-validate.ts`) and the `POST /api/channels/{adapter}/test` route. Anything else lives on long-lived sibling branches and is copied in by skills:
|
|
84
|
+
|
|
85
|
+
- **`channels` branch** — Slack, WhatsApp, Teams, Linear, GitHub, iMessage, Webex, Resend, Matrix, Google Chat, WhatsApp Cloud (+ helpers, tests, channel-specific setup steps). Installed via `/add-<channel>` skills.
|
|
86
|
+
- **`providers` branch** — OpenCode (and any future non-default agent providers). Installed via `/add-opencode`.
|
|
87
|
+
|
|
88
|
+
Each `/add-<name>` skill is idempotent: `git fetch origin <branch>` → copy module(s) into the standard paths → append a self-registration import to the relevant barrel → `pnpm install <pkg>@<pinned-version>` → build.
|
|
89
|
+
|
|
90
|
+
## Self-Modification
|
|
91
|
+
|
|
92
|
+
One tier of agent self-modification today:
|
|
93
|
+
|
|
94
|
+
1. **`install_packages` / `add_mcp_server`** — changes to the per-agent-group container config only (apt/npm deps, wire an existing MCP server). Single admin approval per request; on approve, the handler in `src/modules/self-mod/apply.ts` rebuilds the image when needed (`install_packages` only) and restarts the container. `container/agent-runner/src/mcp-tools/self-mod.ts`.
|
|
95
|
+
|
|
96
|
+
A second tier (direct source-level self-edits via a draft/activate flow) is planned but not yet implemented.
|
|
97
|
+
|
|
98
|
+
## Secrets / Credentials
|
|
99
|
+
|
|
100
|
+
parachute-agent owns its credential store. API keys, OAuth tokens, and auth credentials are stored locally as AES-GCM ciphertext in the central DB, with the master key at `~/.parachute/agent/master.key` (chmod 0600, generated on first boot — pre-0.1.0 installs auto-migrate from `~/.parachute/claw/master.key` on startup). Code in `src/secrets/` decrypts the rows assigned to a given agent group at container spawn and injects them as env vars; nothing goes through chat context.
|
|
101
|
+
|
|
102
|
+
Surfaces:
|
|
103
|
+
- **Web UI** — `/agent/secrets` lists, creates, updates, deletes secrets and assigns them to agent groups (mirrors the `selective` / `all` allow-list semantics).
|
|
104
|
+
- **HTTP API** — `/api/secrets` (GET / POST / PATCH / DELETE) is the same code path the UI uses; scope-gated by `agent:admin`.
|
|
105
|
+
- **Per-agent assignment** — every secret carries `assigned_mode` (`all` = injected into every group; `selective` = injected only into groups in `secret_assignments`).
|
|
106
|
+
|
|
107
|
+
### Approval-gated credential use
|
|
108
|
+
|
|
109
|
+
Approval flows for credential use are parachute-agent-native: a module (or self-mod handler) calls `requestApproval()` from `src/modules/approvals/primitive.ts`, which persists a `pending_approvals` row, picks an approver via `pickApprover` (scoped admins → global admins → owners, all from `user_roles` in the central DB), and routes a card via `pickApprovalDelivery`. The approver decides via either the chat card or `POST /api/approvals/:id/decide` from the UI; both go through `handleApprovalsResponse`.
|
|
110
|
+
|
|
111
|
+
## Skills
|
|
112
|
+
|
|
113
|
+
Four types of skills. See [CONTRIBUTING.md](CONTRIBUTING.md) for the full taxonomy.
|
|
114
|
+
|
|
115
|
+
- **Channel/provider install skills** — copy the relevant module(s) in from the `channels` or `providers` branch, wire imports, install pinned deps (e.g. `/add-discord`, `/add-slack`, `/add-whatsapp`, `/add-opencode`).
|
|
116
|
+
- **Utility skills** — ship code files alongside `SKILL.md` (e.g. `/claw`).
|
|
117
|
+
- **Operational skills** — instruction-only workflows (`/debug`, `/customize`, `/update-nanoclaw`).
|
|
118
|
+
- **Container skills** — loaded inside agent containers at runtime (`container/skills/`: `welcome`, `self-customize`, `agent-browser`, `slack-formatting`).
|
|
119
|
+
|
|
120
|
+
| Skill | When to Use |
|
|
121
|
+
|-------|-------------|
|
|
122
|
+
| `/customize` | Adding channels, integrations, behavior changes |
|
|
123
|
+
| `/debug` | Container issues, logs, troubleshooting |
|
|
124
|
+
| `/update-nanoclaw` | Bring upstream updates into a customized install |
|
|
125
|
+
|
|
126
|
+
## MCP server
|
|
127
|
+
|
|
128
|
+
parachute-agent exposes its host-side admin surface (the things `/api/*` and `/agent/*` mediate from the web UI: agent-groups, sessions, channel wires, secrets metadata, approvals) as MCP tools. The same registry serves both transports — handlers call internal helpers directly, not back through HTTP, so there's no extra round-trip and no second auth seam to keep in sync.
|
|
129
|
+
|
|
130
|
+
| Transport | Endpoint | Auth | Effective scope |
|
|
131
|
+
|-----------|----------|------|-----------------|
|
|
132
|
+
| stdio | `bun src/mcp/stdio.ts` | ambient (filesystem trust) | `agent:admin` |
|
|
133
|
+
| HTTP | `POST /mcp` on port 1944 | hub-issued JWT (`Authorization: Bearer …`) | strongest `agent:*` scope on the JWT grant (legacy `claw:*` grants normalize to `agent:*` through 0.1.x) |
|
|
134
|
+
|
|
135
|
+
Wire stdio into Claude Code:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
claude mcp add parachute-agent bun /absolute/path/to/parachute-agent/src/mcp/stdio.ts
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Tools advertise as `mcp__parachute_agent__<verb>-<noun>` client-side: `list-agent-groups`, `create-agent-group`, `attach-vault`, `detach-vault`, `list-sessions`, `close-session`, `list-channels`, `update-channel-wire`, `delete-channel-wire`, `list-secrets`, `put-secret`, `delete-secret`, `assign-secret`, `list-approvals`, `decide-approval`, `get-activity`. The remaining stubs (`start-oauth`, `revoke-integration`) are advertised but `disabled` until the matching server endpoints land — they're filtered out of `tools/list` and refused on `tools/call`.
|
|
142
|
+
|
|
143
|
+
Secret values **never** traverse MCP. `list-secrets` and `put-secret` return row metadata only; the plaintext flows in once on `put-secret` and lands in the encrypted DB column. Container injection happens at session-spawn time, not over the tool surface.
|
|
144
|
+
|
|
145
|
+
Stdio gotcha: parachute-agent's `log.ts` writes info-level messages to `process.stdout`, which corrupts JSON-RPC frames. `src/mcp/stdio.ts` promotes `LOG_LEVEL` to `warn` before any log-using import. Don't move that block below the dynamic imports.
|
|
146
|
+
|
|
147
|
+
## Contributing
|
|
148
|
+
|
|
149
|
+
Before creating a PR, adding a skill, or preparing any contribution, you MUST read [CONTRIBUTING.md](CONTRIBUTING.md). It covers accepted change types, the four skill types and their guidelines, `SKILL.md` format rules, and the pre-submission checklist.
|
|
150
|
+
|
|
151
|
+
## Development
|
|
152
|
+
|
|
153
|
+
Run commands directly — don't tell the user to run them.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Host (Node + pnpm)
|
|
157
|
+
pnpm run dev # Host with hot reload
|
|
158
|
+
pnpm run build # Compile host TypeScript (src/)
|
|
159
|
+
./container/build.sh # Rebuild agent container image (parachute-agent-image-<slug>:latest)
|
|
160
|
+
pnpm test # Host tests (vitest)
|
|
161
|
+
|
|
162
|
+
# Agent-runner (Bun — separate package tree under container/agent-runner/)
|
|
163
|
+
cd container/agent-runner && bun install # After editing agent-runner deps
|
|
164
|
+
cd container/agent-runner && bun test # Container tests (bun:test)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Container typecheck is a separate tsconfig — if you edit `container/agent-runner/src/`, run `pnpm exec tsc -p container/agent-runner/tsconfig.json --noEmit` from root (or `bun run typecheck` from `container/agent-runner/`).
|
|
168
|
+
|
|
169
|
+
Service management is owned by the hub install path (`parachute install parachute-agent`), which generates the launchd plist / systemd unit. Existing pre-0.1.0 installs still use the old `computer.parachute.claw-<slug>` / `paraclaw-<slug>` labels until the operator re-runs the hub installer; the new label is `computer.parachute.agent-<slug>` / `parachute-agent-<slug>`. Substitute `<slug>` with the 8-char hash from `getInstallSlug()` — each checkout gets its own service so two installs on one host don't collide:
|
|
170
|
+
```bash
|
|
171
|
+
# macOS (launchd)
|
|
172
|
+
launchctl load ~/Library/LaunchAgents/computer.parachute.agent-<slug>.plist
|
|
173
|
+
launchctl unload ~/Library/LaunchAgents/computer.parachute.agent-<slug>.plist
|
|
174
|
+
launchctl kickstart -k gui/$(id -u)/computer.parachute.agent-<slug> # restart
|
|
175
|
+
|
|
176
|
+
# Linux (systemd)
|
|
177
|
+
systemctl --user start|stop|restart parachute-agent-<slug>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Host logs: `logs/parachute-agent.log` (normal) and `logs/parachute-agent.error.log` (errors only — some delivery/approval failures only show up here). On 0.1.0 first boot, any pre-existing `logs/paraclaw{,.error}.log` are renamed in place so the historical file stays accessible under the new name. The supervisor unit (launchd plist / systemd unit, generated by `parachute install parachute-agent`) is what controls *where new entries are written*; until the operator re-runs the installer, the supervisor still routes stdout to `paraclaw.log` and a fresh file is recreated under the legacy name on each daemon respawn. Re-running the installer regenerates the unit so subsequent boots write to `parachute-agent.log`.
|
|
181
|
+
|
|
182
|
+
## Supply Chain Security (pnpm)
|
|
183
|
+
|
|
184
|
+
This project uses pnpm with `minimumReleaseAge: 4320` (3 days) in `pnpm-workspace.yaml`. New package versions must exist on the npm registry for 3 days before pnpm will resolve them.
|
|
185
|
+
|
|
186
|
+
**Rules — do not bypass without explicit human approval:**
|
|
187
|
+
- **`minimumReleaseAgeExclude`**: Never add entries without human sign-off. If a package must bypass the release age gate, the human must approve and the entry must pin the exact version being excluded (e.g. `package@1.2.3`), never a range.
|
|
188
|
+
- **`onlyBuiltDependencies`**: Never add packages to this list without human approval — build scripts execute arbitrary code during install.
|
|
189
|
+
- **`pnpm install --frozen-lockfile`** should be used in CI, automation, and container builds. Never run bare `pnpm install` in those contexts.
|
|
190
|
+
|
|
191
|
+
## Docs Index
|
|
192
|
+
|
|
193
|
+
| Doc | Purpose |
|
|
194
|
+
|-----|---------|
|
|
195
|
+
| [docs/architecture.md](docs/architecture.md) | Full architecture writeup |
|
|
196
|
+
| [docs/api-details.md](docs/api-details.md) | Host API + DB schema details |
|
|
197
|
+
| [docs/db.md](docs/db.md) | DB architecture overview: three-DB model, cross-mount rules, readers/writers map |
|
|
198
|
+
| [docs/db-central.md](docs/db-central.md) | Central DB (`data/v2.db`) — every table + migration system |
|
|
199
|
+
| [docs/db-session.md](docs/db-session.md) | Per-session `inbound.db` + `outbound.db` schemas + seq parity |
|
|
200
|
+
| [docs/agent-runner-details.md](docs/agent-runner-details.md) | Agent-runner internals + MCP tool interface |
|
|
201
|
+
| [docs/isolation-model.md](docs/isolation-model.md) | Three-level channel isolation model |
|
|
202
|
+
| [docs/setup-wiring.md](docs/setup-wiring.md) | What's wired, what's open in the setup flow |
|
|
203
|
+
| [docs/architecture-diagram.md](docs/architecture-diagram.md) | Diagram version of the architecture |
|
|
204
|
+
| [docs/build-and-runtime.md](docs/build-and-runtime.md) | Runtime split (Node host + Bun container), lockfiles, image build surface, CI, key invariants |
|
|
205
|
+
|
|
206
|
+
## Container Build Cache
|
|
207
|
+
|
|
208
|
+
The container buildkit caches the build context aggressively. `--no-cache` alone does NOT invalidate COPY steps — the builder's volume retains stale files. To force a truly clean rebuild, prune the builder then re-run `./container/build.sh`.
|
|
209
|
+
|
|
210
|
+
## Container Runtime (Bun)
|
|
211
|
+
|
|
212
|
+
The agent container runs on **Bun**; the host runs on **Node** (pnpm). They communicate only via session DBs — no shared modules. Details and rationale: [docs/build-and-runtime.md](docs/build-and-runtime.md).
|
|
213
|
+
|
|
214
|
+
**Gotchas — trigger + action:**
|
|
215
|
+
|
|
216
|
+
- **Adding or bumping a runtime dep in `container/agent-runner/`** → edit `package.json`, then `cd container/agent-runner && bun install` and commit the updated `bun.lock`. Do not run `pnpm install` there — agent-runner is not a pnpm workspace.
|
|
217
|
+
- **Bumping `@anthropic-ai/claude-agent-sdk`, `@modelcontextprotocol/sdk`, or any agent-runner runtime dep** → no `minimumReleaseAge` policy applies to this tree. Check the release date on npm, pin deliberately, never `bun update` blindly.
|
|
218
|
+
- **Writing a new named-param SQL insert/update in the container** → use `$name` in both SQL and JS keys: `.run({ $id: msg.id })`. `bun:sqlite` does not auto-strip the prefix the way `better-sqlite3` does on the host. Positional `?` params work normally.
|
|
219
|
+
- **Adding a test in `container/agent-runner/src/`** → import from `bun:test`, not `vitest`. Vitest runs on Node and can't load `bun:sqlite`. `vitest.config.ts` excludes this tree.
|
|
220
|
+
- **Adding a Node CLI the agent invokes at runtime** (like `agent-browser`, `claude-code`, `vercel`) → put it in the Dockerfile's pnpm global-install block, pinned to an exact version via a new `ARG`. Don't use `bun install -g` — that bypasses the pnpm supply-chain policy.
|
|
221
|
+
- **Changing the Dockerfile entrypoint or the dynamic-spawn command** (`src/container-runner.ts` line ~301) → keep `exec bun ...` so signals forward cleanly. The image has no `/app/dist`; don't reintroduce a tsc build step.
|
|
222
|
+
- **Changing session-DB pragmas** (`container/agent-runner/src/db/connection.ts`) → `journal_mode=DELETE` is load-bearing for cross-mount visibility. Read the comment block at the top of the file first.
|
|
223
|
+
|
|
224
|
+
## Web UI (mount-aware)
|
|
225
|
+
|
|
226
|
+
The parachute-agent SPA in `web/ui/` is served at the origin root in dev (`/`) and under a mount prefix in prod (`/agent/` when running behind the parachute hub on tailnet). The hub owns `/`; an absolute `/api/...` from the browser goes to the hub origin, NOT parachute-agent — and the hub 404s on it. Anything the bundle sends to parachute-agent must include the mount prefix.
|
|
227
|
+
|
|
228
|
+
**Rule:** every URL the UI builds for `fetch`, router basenames, or OAuth redirects must be derived from `import.meta.env.BASE_URL`, not hardcoded with a leading `/`. Same bundle has to work whether the deploy lands at `/`, `/agent/`, or `/some/other/mount/`.
|
|
229
|
+
|
|
230
|
+
Pattern (BASE_URL has a trailing slash; trim it for joining):
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
const API_BASE = `${import.meta.env.BASE_URL.replace(/\/$/, "")}/api`;
|
|
234
|
+
const cb = `${window.location.origin}${import.meta.env.BASE_URL}oauth/callback`;
|
|
235
|
+
<BrowserRouter basename={import.meta.env.BASE_URL.replace(/\/$/, "")}>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
The server-side mirror lives in `web/server/src/server.ts`: `MOUNT` (from `PARACHUTE_AGENT_WEB_MOUNT`, with legacy `PARACLAW_WEB_MOUNT` accepted through 0.1.x) is stripped uniformly before dispatch so `/api/*` and static-serve both see paths without the prefix.
|
|
239
|
+
|
|
240
|
+
### SPA build is wired into install
|
|
241
|
+
|
|
242
|
+
`web/ui/dist/` is gitignored. The root `package.json` runs `build:spa` from a `postinstall` hook so a fresh `pnpm install` produces a working `/agent/*` without a manual rebuild step. If `static-serve` 503s with "UI bundle not found", the install most likely fired with `--ignore-scripts` (which suppresses `postinstall` lifecycle hooks) — fall back to `pnpm run build:spa` to rebuild manually.
|
|
243
|
+
|
|
244
|
+
## CJK font support
|
|
245
|
+
|
|
246
|
+
Agent containers ship without CJK fonts by default (~200MB saved). If you notice signals the user works with Chinese/Japanese/Korean content — conversing in CJK, CJK timezone (e.g., `Asia/Tokyo`, `Asia/Shanghai`, `Asia/Seoul`, `Asia/Taipei`, `Asia/Hong_Kong`), system locale hint, or mentions of needing to render CJK in screenshots/PDFs/scraped pages — offer to enable it:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# Ensure .env has INSTALL_CJK_FONTS=true (overwrite or append)
|
|
250
|
+
grep -q '^INSTALL_CJK_FONTS=' .env && sed -i.bak 's/^INSTALL_CJK_FONTS=.*/INSTALL_CJK_FONTS=true/' .env && rm -f .env.bak || echo 'INSTALL_CJK_FONTS=true' >> .env
|
|
251
|
+
|
|
252
|
+
# Rebuild and restart so new sessions pick up the new image
|
|
253
|
+
./container/build.sh
|
|
254
|
+
launchctl kickstart -k gui/$(id -u)/computer.parachute.agent-<slug> # macOS
|
|
255
|
+
# systemctl --user restart parachute-agent-<slug> # Linux
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
`container/build.sh` reads `INSTALL_CJK_FONTS` from `.env` and passes it through as a Docker build-arg. Without CJK fonts, Chromium-rendered screenshots and PDFs containing CJK text show tofu (empty rectangles) instead of characters.
|
|
259
|
+
|
|
260
|
+
## ⚠ Sandbox isolation — DO NOT clobber the live install
|
|
261
|
+
|
|
262
|
+
If you spin a parachute-agent sandbox **on the same host as a live install**, three things must be different from the live install or you will reap its containers and clobber its DB. This bit Aaron once (paraclaw#91); guard against repeating it.
|
|
263
|
+
|
|
264
|
+
### What collides
|
|
265
|
+
|
|
266
|
+
| Atom | Default | Why a same-host sandbox collides |
|
|
267
|
+
|------|---------|----------------------------------|
|
|
268
|
+
| `INSTALL_SLUG` | `sha1(cwd)[:8]` | Same project root → same slug → `cleanupOrphans` reaps live containers via the `parachute-agent-install=<slug>` label (and the legacy `paraclaw-install=<slug>` label, reaped through 0.1.x) |
|
|
269
|
+
| Central DB + `master.key` | `~/.parachute/agent/` | Both installs share the operator-owned home dir |
|
|
270
|
+
| Webhook port | `WEBHOOK_PORT` (default 3000) | Two listeners on one port → `EADDRINUSE` |
|
|
271
|
+
| Web port | `PARACHUTE_AGENT_WEB_PORT` (default 1944) | Same. Legacy `PARACLAW_WEB_PORT` accepted through 0.1.x with a deprecation warning |
|
|
272
|
+
|
|
273
|
+
### Safe sandbox pattern
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
# 1. New cwd → new INSTALL_SLUG. Use a worktree, not a fresh checkout —
|
|
277
|
+
# same-branch state, isolated filesystem.
|
|
278
|
+
git worktree add /tmp/parachute-agent-sandbox <branch>
|
|
279
|
+
cd /tmp/parachute-agent-sandbox
|
|
280
|
+
|
|
281
|
+
# 2. Fresh PARACHUTE_HOME → fresh DB + fresh master.key. PARACHUTE_HOME is
|
|
282
|
+
# the canonical override (parachute-hub, vault, scribe all honor it);
|
|
283
|
+
# parachute-agent joined the convention as paraclaw#91. Both atoms
|
|
284
|
+
# reroute together so the sandbox's encrypted-secret reads stay
|
|
285
|
+
# self-consistent.
|
|
286
|
+
export PARACHUTE_HOME=/tmp/parachute-agent-sandbox-home
|
|
287
|
+
|
|
288
|
+
# 3. Different ports — pick anything free. Don't rely on default 1944/3000.
|
|
289
|
+
export PARACHUTE_AGENT_WEB_PORT=2944
|
|
290
|
+
export WEBHOOK_PORT=3944
|
|
291
|
+
|
|
292
|
+
# 4. Bootstrap state programmatically (init-first-agent / API). Don't
|
|
293
|
+
# copy the live DB — defeats the isolation.
|
|
294
|
+
pnpm install
|
|
295
|
+
pnpm run dev
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Don't do
|
|
299
|
+
|
|
300
|
+
- `cd <live-parachute-agent>` and run sandbox there with overrides — same INSTALL_SLUG, `cleanupOrphans` reaps live containers regardless of DB-path overrides.
|
|
301
|
+
- Override only `PARACHUTE_AGENT_CENTRAL_DB_PATH` — `master.key` still lands at `~/.parachute/agent/master.key` if `PARACHUTE_HOME` is unset, and you'll cross-decrypt against the live key.
|
|
302
|
+
- Set `HOME=/tmp/...` instead of `PARACHUTE_HOME` — affects every other tool's home-dir lookup. parachute-agent honors HOME for ergonomic compat, but `PARACHUTE_HOME` is the precise knob for "reroute parachute-agent's persistent state."
|
|
303
|
+
- Combine `PARACHUTE_HOME` with `PARACHUTE_AGENT_CENTRAL_DB_PATH` unless you understand the split — the DB lands at the explicit override path but `master.key` still follows `PARACHUTE_HOME` (sits at `<PARACHUTE_HOME>/agent/master.key`). Exporting just the DB file alone yields unreadable ciphertext on the receiving side. The split is intentional — the override lets you put the DB on a different volume — but the two atoms only travel together when you let both default off `PARACHUTE_HOME`.
|
|
304
|
+
|
|
305
|
+
### After the sandbox
|
|
306
|
+
|
|
307
|
+
`git worktree remove /tmp/parachute-agent-sandbox && rm -rf /tmp/parachute-agent-sandbox-home` cleans up. Containers tagged with the sandbox's INSTALL_SLUG won't conflict with the live install's, but a long-lived sandbox accumulates them — `docker ps -a --filter label=parachute-agent-install=<sandbox-slug>` to see what's left.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity
|
|
10
|
+
and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment for our
|
|
18
|
+
community include:
|
|
19
|
+
|
|
20
|
+
* Demonstrating empathy and kindness toward other people
|
|
21
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
22
|
+
* Giving and gracefully accepting constructive feedback
|
|
23
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
24
|
+
and learning from the experience
|
|
25
|
+
* Focusing on what is best not just for us as individuals, but for the
|
|
26
|
+
overall community
|
|
27
|
+
|
|
28
|
+
Examples of unacceptable behavior include:
|
|
29
|
+
|
|
30
|
+
* The use of sexualized language or imagery, and sexual attention or
|
|
31
|
+
advances of any kind
|
|
32
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
33
|
+
* Public or private harassment
|
|
34
|
+
* Publishing others' private information, such as a physical or email
|
|
35
|
+
address, without their explicit permission
|
|
36
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
|
37
|
+
professional setting
|
|
38
|
+
|
|
39
|
+
## Enforcement Responsibilities
|
|
40
|
+
|
|
41
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
42
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
43
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
44
|
+
or harmful.
|
|
45
|
+
|
|
46
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
|
47
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
48
|
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
49
|
+
decisions when appropriate.
|
|
50
|
+
|
|
51
|
+
## Scope
|
|
52
|
+
|
|
53
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
54
|
+
an individual is officially representing the community in public spaces.
|
|
55
|
+
Examples of representing our community include using an official e-mail address,
|
|
56
|
+
posting via an official social media account, or acting as an appointed
|
|
57
|
+
representative at an online or offline event.
|
|
58
|
+
|
|
59
|
+
## Enforcement
|
|
60
|
+
|
|
61
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
62
|
+
reported to the community leaders responsible for enforcement at
|
|
63
|
+
community@nanoclaw.dev.
|
|
64
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
65
|
+
|
|
66
|
+
All community leaders are obligated to respect the privacy and security of the
|
|
67
|
+
reporter of any incident.
|
|
68
|
+
|
|
69
|
+
## Enforcement Guidelines
|
|
70
|
+
|
|
71
|
+
Community leaders will follow these Community Impact Guidelines in determining
|
|
72
|
+
the consequences for any action they deem in violation of this Code of Conduct:
|
|
73
|
+
|
|
74
|
+
### 1. Correction
|
|
75
|
+
|
|
76
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
77
|
+
unprofessional or unwelcome in the community.
|
|
78
|
+
|
|
79
|
+
**Consequence**: A private, written warning from community leaders, providing
|
|
80
|
+
clarity around the nature of the violation and an explanation of why the
|
|
81
|
+
behavior was inappropriate. A public apology may be requested.
|
|
82
|
+
|
|
83
|
+
### 2. Warning
|
|
84
|
+
|
|
85
|
+
**Community Impact**: A violation through a single incident or series
|
|
86
|
+
of actions.
|
|
87
|
+
|
|
88
|
+
**Consequence**: A warning with consequences for continued behavior. No
|
|
89
|
+
interaction with the people involved, including unsolicited interaction with
|
|
90
|
+
those enforcing the Code of Conduct, for a specified period of time. This
|
|
91
|
+
includes avoiding interactions in community spaces as well as external channels
|
|
92
|
+
like social media. Violating these terms may lead to a temporary or
|
|
93
|
+
permanent ban.
|
|
94
|
+
|
|
95
|
+
### 3. Temporary Ban
|
|
96
|
+
|
|
97
|
+
**Community Impact**: A serious violation of community standards, including
|
|
98
|
+
sustained inappropriate behavior.
|
|
99
|
+
|
|
100
|
+
**Consequence**: A temporary ban from any sort of interaction or public
|
|
101
|
+
communication with the community for a specified period of time. No public or
|
|
102
|
+
private interaction with the people involved, including unsolicited interaction
|
|
103
|
+
with those enforcing the Code of Conduct, is allowed during this period.
|
|
104
|
+
Violating these terms may lead to a permanent ban.
|
|
105
|
+
|
|
106
|
+
### 4. Permanent Ban
|
|
107
|
+
|
|
108
|
+
**Community Impact**: Demonstrating a pattern of violation of community
|
|
109
|
+
standards, including sustained inappropriate behavior, harassment of an
|
|
110
|
+
individual, or aggression toward or disparagement of classes of individuals.
|
|
111
|
+
|
|
112
|
+
**Consequence**: A permanent ban from any sort of public interaction within
|
|
113
|
+
the community.
|
|
114
|
+
|
|
115
|
+
## Attribution
|
|
116
|
+
|
|
117
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
118
|
+
version 2.0, available at
|
|
119
|
+
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
|
120
|
+
|
|
121
|
+
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
|
122
|
+
enforcement ladder](https://github.com/mozilla/diversity).
|
|
123
|
+
|
|
124
|
+
[homepage]: https://www.contributor-covenant.org
|
|
125
|
+
|
|
126
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
|
127
|
+
https://www.contributor-covenant.org/faq. Translations are available at
|
|
128
|
+
https://www.contributor-covenant.org/translations.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Before You Start
|
|
4
|
+
|
|
5
|
+
1. **Check for existing work.** Search open PRs and issues before starting:
|
|
6
|
+
```bash
|
|
7
|
+
gh pr list --repo ParachuteComputer/paraclaw --search "<your feature>"
|
|
8
|
+
gh issue list --repo ParachuteComputer/paraclaw --search "<your feature>"
|
|
9
|
+
```
|
|
10
|
+
If a related PR or issue exists, build on it rather than duplicating effort.
|
|
11
|
+
|
|
12
|
+
2. **Check alignment.** Read the [Philosophy section in README.md](README.md#philosophy). Source code changes should only be things 90%+ of users need. Skills can be more niche, but should still be useful beyond a single person's setup.
|
|
13
|
+
|
|
14
|
+
3. **One thing per PR.** Each PR should do one thing — one bug fix, one skill, one simplification. Don't mix unrelated changes in a single PR.
|
|
15
|
+
|
|
16
|
+
## Source Code Changes
|
|
17
|
+
|
|
18
|
+
**Accepted:** Bug fixes, security fixes, simplifications, reducing code.
|
|
19
|
+
|
|
20
|
+
**Not accepted:** Features, capabilities, compatibility, enhancements. These should be skills.
|
|
21
|
+
|
|
22
|
+
## Skills
|
|
23
|
+
|
|
24
|
+
parachute-agent uses [Claude Code skills](https://code.claude.com/docs/en/skills) — markdown files with optional supporting files that teach Claude how to do something. There are four types of skills in parachute-agent, each serving a different purpose.
|
|
25
|
+
|
|
26
|
+
### Why skills?
|
|
27
|
+
|
|
28
|
+
Every user should have clean and minimal code that does exactly what they need. Skills let users selectively add features to their fork without inheriting code for features they don't want.
|
|
29
|
+
|
|
30
|
+
### Skill types
|
|
31
|
+
|
|
32
|
+
#### 1. Feature skills (branch-based)
|
|
33
|
+
|
|
34
|
+
Add capabilities to parachute-agent by merging a git branch. The SKILL.md contains setup instructions; the actual code lives on a `skill/*` branch.
|
|
35
|
+
|
|
36
|
+
**Location:** `.claude/skills/` on `main` (instructions only), code on `skill/*` branch
|
|
37
|
+
|
|
38
|
+
**Examples:** `/add-telegram`, `/add-slack`, `/add-discord`, `/add-gmail`
|
|
39
|
+
|
|
40
|
+
**How they work:**
|
|
41
|
+
1. User runs `/add-telegram`
|
|
42
|
+
2. Claude follows the SKILL.md: fetches and merges the `skill/telegram` branch
|
|
43
|
+
3. Claude walks through interactive setup (env vars, bot creation, etc.)
|
|
44
|
+
|
|
45
|
+
**Contributing a feature skill:**
|
|
46
|
+
1. Fork `ParachuteComputer/paraclaw` and branch from `main`
|
|
47
|
+
2. Make the code changes (new files, modified source, updated `package.json`, etc.)
|
|
48
|
+
3. Add a SKILL.md in `.claude/skills/<name>/` with setup instructions — step 1 should be merging the branch
|
|
49
|
+
4. Open a PR. We'll create the `skill/<name>` branch from your work
|
|
50
|
+
|
|
51
|
+
See `/add-telegram` for a good example. See [docs/skills-as-branches.md](docs/skills-as-branches.md) for the full system design.
|
|
52
|
+
|
|
53
|
+
#### 2. Utility skills (with code files)
|
|
54
|
+
|
|
55
|
+
Standalone tools that ship code files alongside the SKILL.md. The SKILL.md tells Claude how to install the tool; the code lives in the skill directory itself (e.g. in a `scripts/` subfolder).
|
|
56
|
+
|
|
57
|
+
**Location:** `.claude/skills/<name>/` with supporting files
|
|
58
|
+
|
|
59
|
+
**Examples:** `/claw` (Python CLI in `scripts/claw`)
|
|
60
|
+
|
|
61
|
+
**Key difference from feature skills:** No branch merge needed. The code is self-contained in the skill directory and gets copied into place during installation.
|
|
62
|
+
|
|
63
|
+
**Guidelines:**
|
|
64
|
+
- Put code in separate files, not inline in the SKILL.md
|
|
65
|
+
- Use `${CLAUDE_SKILL_DIR}` to reference files in the skill directory
|
|
66
|
+
- SKILL.md contains installation instructions, usage docs, and troubleshooting
|
|
67
|
+
|
|
68
|
+
#### 3. Operational skills (instruction-only)
|
|
69
|
+
|
|
70
|
+
Workflows and guides with no code changes. The SKILL.md is the entire skill — Claude follows the instructions to perform a task.
|
|
71
|
+
|
|
72
|
+
**Location:** `.claude/skills/` on `main`
|
|
73
|
+
|
|
74
|
+
**Examples:** `/setup`, `/debug`, `/customize`, `/update-skills`
|
|
75
|
+
|
|
76
|
+
**Guidelines:**
|
|
77
|
+
- Pure instructions — no code files, no branch merges
|
|
78
|
+
- Use `AskUserQuestion` for interactive prompts
|
|
79
|
+
- These stay on `main` and are always available to every user
|
|
80
|
+
|
|
81
|
+
#### 4. Container skills (agent runtime)
|
|
82
|
+
|
|
83
|
+
Skills that run inside the agent container, not on the host. These teach the container agent how to use tools, format output, or perform tasks. They are synced into each group's `.claude/skills/` directory when a container starts.
|
|
84
|
+
|
|
85
|
+
**Location:** `container/skills/<name>/`
|
|
86
|
+
|
|
87
|
+
**Examples:** `agent-browser` (web browsing), `capabilities` (/capabilities command), `status` (/status command), `slack-formatting` (Slack mrkdwn syntax)
|
|
88
|
+
|
|
89
|
+
**Key difference:** These are NOT invoked by the user on the host. They're loaded by Claude Code inside the container and influence how the agent behaves.
|
|
90
|
+
|
|
91
|
+
**Guidelines:**
|
|
92
|
+
- Follow the same SKILL.md + frontmatter format
|
|
93
|
+
- Use `allowed-tools` frontmatter to scope tool permissions
|
|
94
|
+
- Keep them focused — the agent's context window is shared across all container skills
|
|
95
|
+
|
|
96
|
+
### SKILL.md format
|
|
97
|
+
|
|
98
|
+
All skills use the [Claude Code skills standard](https://code.claude.com/docs/en/skills):
|
|
99
|
+
|
|
100
|
+
```markdown
|
|
101
|
+
---
|
|
102
|
+
name: my-skill
|
|
103
|
+
description: What this skill does and when to use it.
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
Instructions here...
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Rules:**
|
|
110
|
+
- Keep SKILL.md **under 500 lines** — move detail to separate reference files
|
|
111
|
+
- `name`: lowercase, alphanumeric + hyphens, max 64 chars
|
|
112
|
+
- `description`: required — Claude uses this to decide when to invoke the skill
|
|
113
|
+
- Put code in separate files, not inline in the markdown
|
|
114
|
+
- See the [skills standard](https://code.claude.com/docs/en/skills) for all available frontmatter fields
|
|
115
|
+
|
|
116
|
+
## Testing
|
|
117
|
+
|
|
118
|
+
Test your contribution on a fresh clone before submitting. For skills, run the skill end-to-end and verify it works.
|
|
119
|
+
|
|
120
|
+
### web/ui test harness
|
|
121
|
+
|
|
122
|
+
The frontend bundle in `web/ui/` is intentionally outside the pnpm workspace (the `build:spa` script uses `--ignore-workspace`). A root-level `pnpm install` populates `web/ui/node_modules` and builds `web/ui/dist/` automatically via the `postinstall` hook — usually no extra step is needed.
|
|
123
|
+
|
|
124
|
+
If you ran `pnpm install --ignore-scripts` (the postinstall is suppressed), or you want to run web/ui tests on their own, install its deps and run the test runner directly:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
cd web/ui && pnpm install --frozen-lockfile --ignore-workspace && pnpm test
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Otherwise the test runner exits with a missing-dependency error (the exact symptom — module-not-found on `@vitejs/plugin-react`, missing test framework, etc. — depends on which entry point your package manager hits first).
|
|
131
|
+
|
|
132
|
+
## Pull Requests
|
|
133
|
+
|
|
134
|
+
### Before opening
|
|
135
|
+
|
|
136
|
+
1. **Link related issues.** If your PR resolves an open issue, include `Closes #123` in the description so it's auto-closed on merge.
|
|
137
|
+
2. **Test thoroughly.** Run the feature yourself. For skills, test on a fresh clone.
|
|
138
|
+
3. **Check the right box** in the PR template. Labels are auto-applied based on your selection:
|
|
139
|
+
|
|
140
|
+
| Checkbox | Label |
|
|
141
|
+
|----------|-------|
|
|
142
|
+
| Feature skill | `PR: Skill` + `PR: Feature` |
|
|
143
|
+
| Utility skill | `PR: Skill` |
|
|
144
|
+
| Operational/container skill | `PR: Skill` |
|
|
145
|
+
| Fix | `PR: Fix` |
|
|
146
|
+
| Simplification | `PR: Refactor` |
|
|
147
|
+
| Documentation | `PR: Docs` |
|
|
148
|
+
|
|
149
|
+
### PR description
|
|
150
|
+
|
|
151
|
+
Keep it concise. Remove any template sections that don't apply. The description should cover:
|
|
152
|
+
|
|
153
|
+
- **What** — what the PR adds or changes
|
|
154
|
+
- **Why** — the motivation
|
|
155
|
+
- **How it works** — brief explanation of the approach
|
|
156
|
+
- **How it was tested** — what you did to verify it works
|
|
157
|
+
- **Usage** — how the user invokes it (for skills)
|
|
158
|
+
|
|
159
|
+
Don't pad the description. A few clear sentences are better than lengthy paragraphs.
|
package/CONTRIBUTORS.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Contributors
|
|
2
|
+
|
|
3
|
+
Thanks to everyone who has contributed to NanoClaw!
|
|
4
|
+
|
|
5
|
+
- [Alakazam03](https://github.com/Alakazam03) — Vaibhav Aggarwal
|
|
6
|
+
- [tydev-new](https://github.com/tydev-new)
|
|
7
|
+
- [pottertech](https://github.com/pottertech) — Skip Potter
|
|
8
|
+
- [rgarcia](https://github.com/rgarcia) — Rafael
|
|
9
|
+
- [AmaxGuan](https://github.com/AmaxGuan) — Lingfeng Guan
|
|
10
|
+
- [happydog-intj](https://github.com/happydog-intj) — happy dog
|
|
11
|
+
- [bindoon](https://github.com/bindoon) — 潕量
|
|
12
|
+
- [taslim](https://github.com/taslim) — Taslim
|
|
13
|
+
- [baijunjie](https://github.com/baijunjie) — BaiJunjie
|
|
14
|
+
- [Michaelliv](https://github.com/Michaelliv) — Michael
|
|
15
|
+
- [kk17](https://github.com/kk17) — Kyle Zhike Chen
|
|
16
|
+
- [flobo3](https://github.com/flobo3) — Flo
|
|
17
|
+
- [edwinwzhe](https://github.com/edwinwzhe) — Edwin He
|
|
18
|
+
- [scottgl9](https://github.com/scottgl9) — Scott Glover
|
|
19
|
+
- [cschmidt](https://github.com/cschmidt) — Carl Schmidt
|
|
20
|
+
- [leonalfredbot-ship-it](https://github.com/leonalfredbot-ship-it) — Alfred-the-buttler
|
|
21
|
+
- [moktamd](https://github.com/moktamd)
|
|
22
|
+
- [gurixs-carson](https://github.com/gurixs-carson)
|
|
23
|
+
- [MrBlaise](https://github.com/MrBlaise) — Balázs Rostás
|
|
24
|
+
- [lbsnrs](https://github.com/lbsnrs) — Andreas Liebschner
|
|
25
|
+
- [spencer-whitman](https://github.com/spencer-whitman)
|
|
26
|
+
- [lazure-ocean](https://github.com/lazure-ocean) — Cyril Ionov
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gavriel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|