diff --git a/.claude/skills/add-compact/SKILL.md b/.claude/skills/add-compact/SKILL.md index 0c46165..b4b3d00 100644 --- a/.claude/skills/add-compact/SKILL.md +++ b/.claude/skills/add-compact/SKILL.md @@ -34,7 +34,7 @@ This adds: - `src/session-commands.ts` (extract and authorize session commands) - `src/session-commands.test.ts` (unit tests for command parsing and auth) - Session command interception in `src/index.ts` (both `processGroupMessages` and `startMessageLoop`) -- Slash command handling in `container/agent-runner/src/index.ts` +- Slash command handling in `runners/agent-runner/src/index.ts` ### Validate @@ -46,7 +46,7 @@ npm run build ### Rebuild container ```bash -./container/build.sh +./runners/build.sh ``` ### Restart service @@ -106,7 +106,7 @@ cd /tmp/nanoclaw-test claude # then run /add-compact npm run build npm test -./container/build.sh +./runners/build.sh # Manual: send /compact from main group, verify compaction + continuation # Manual: send @ /compact from non-main as non-admin, verify denial # Manual: send @ /compact from non-main as admin, verify allowed diff --git a/.claude/skills/add-gmail/SKILL.md b/.claude/skills/add-gmail/SKILL.md index f77bbf7..75fd55d 100644 --- a/.claude/skills/add-gmail/SKILL.md +++ b/.claude/skills/add-gmail/SKILL.md @@ -48,7 +48,7 @@ This merges in: - `src/channels/gmail.test.ts` (unit tests) - `import './gmail.js'` appended to the channel barrel file `src/channels/index.ts` - Gmail credentials mount (`~/.gmail-mcp`) in `src/container-runner.ts` -- Gmail MCP server (`@gongrzhe/server-gmail-autoauth-mcp`) and `mcp__gmail__*` allowed tool in `container/agent-runner/src/index.ts` +- Gmail MCP server (`@gongrzhe/server-gmail-autoauth-mcp`) and `mcp__gmail__*` allowed tool in `runners/agent-runner/src/index.ts` - `googleapis` npm dependency in `package.json` If the merge reports conflicts, resolve them by reading the conflicted files and understanding the intent of both sides. @@ -199,7 +199,7 @@ npx -y @gongrzhe/server-gmail-autoauth-mcp ### Tool-only mode 1. Remove `~/.gmail-mcp` mount from `src/container-runner.ts` -2. Remove `gmail` MCP server and `mcp__gmail__*` from `container/agent-runner/src/index.ts` +2. Remove `gmail` MCP server and `mcp__gmail__*` from `runners/agent-runner/src/index.ts` 3. Rebuild and restart 4. Clear stale agent-runner copies: `rm -r data/sessions/*/agent-runner-src 2>/dev/null || true` 5. Rebuild: `cd container && ./build.sh && cd .. && npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux) @@ -209,7 +209,7 @@ npx -y @gongrzhe/server-gmail-autoauth-mcp 1. Delete `src/channels/gmail.ts` and `src/channels/gmail.test.ts` 2. Remove `import './gmail.js'` from `src/channels/index.ts` 3. Remove `~/.gmail-mcp` mount from `src/container-runner.ts` -4. Remove `gmail` MCP server and `mcp__gmail__*` from `container/agent-runner/src/index.ts` +4. Remove `gmail` MCP server and `mcp__gmail__*` from `runners/agent-runner/src/index.ts` 5. Uninstall: `npm uninstall googleapis` 6. Rebuild and restart 7. Clear stale agent-runner copies: `rm -r data/sessions/*/agent-runner-src 2>/dev/null || true` diff --git a/.claude/skills/add-image-vision/SKILL.md b/.claude/skills/add-image-vision/SKILL.md index 53ef471..9065eec 100644 --- a/.claude/skills/add-image-vision/SKILL.md +++ b/.claude/skills/add-image-vision/SKILL.md @@ -40,7 +40,7 @@ This merges in: - `src/image.test.ts` (8 unit tests) - Image attachment handling in `src/channels/whatsapp.ts` - Image passing to agent in `src/index.ts` and `src/container-runner.ts` -- Image content block support in `container/agent-runner/src/index.ts` +- Image content block support in `runners/agent-runner/src/index.ts` - `sharp` npm dependency in `package.json` If the merge reports conflicts, resolve them by reading the conflicted files and understanding the intent of both sides. @@ -59,13 +59,13 @@ All tests must pass and build must be clean before proceeding. 1. Rebuild the container (agent-runner changes need a rebuild): ```bash - ./container/build.sh + ./runners/build.sh ``` 2. Sync agent-runner source to group caches: ```bash for dir in data/sessions/*/agent-runner-src/; do - cp container/agent-runner/src/*.ts "$dir" + cp runners/agent-runner/src/*.ts "$dir" done ``` diff --git a/.claude/skills/add-ollama-tool/SKILL.md b/.claude/skills/add-ollama-tool/SKILL.md index a347b49..cda5832 100644 --- a/.claude/skills/add-ollama-tool/SKILL.md +++ b/.claude/skills/add-ollama-tool/SKILL.md @@ -15,7 +15,7 @@ Tools added: ### Check if already applied -Check if `container/agent-runner/src/ollama-mcp-stdio.ts` exists. If it does, skip to Phase 3 (Configure). +Check if `runners/agent-runner/src/ollama-mcp-stdio.ts` exists. If it does, skip to Phase 3 (Configure). ### Check prerequisites @@ -59,9 +59,9 @@ git merge upstream/skill/ollama-tool ``` This merges in: -- `container/agent-runner/src/ollama-mcp-stdio.ts` (Ollama MCP server) +- `runners/agent-runner/src/ollama-mcp-stdio.ts` (Ollama MCP server) - `scripts/ollama-watch.sh` (macOS notification watcher) -- Ollama MCP config in `container/agent-runner/src/index.ts` (allowedTools + mcpServers) +- Ollama MCP config in `runners/agent-runner/src/index.ts` (allowedTools + mcpServers) - `[OLLAMA]` log surfacing in `src/container-runner.ts` - `OLLAMA_HOST` in `.env.example` @@ -73,8 +73,8 @@ Existing groups have a cached copy of the agent-runner source. Copy the new file ```bash for dir in data/sessions/*/agent-runner-src; do - cp container/agent-runner/src/ollama-mcp-stdio.ts "$dir/" - cp container/agent-runner/src/index.ts "$dir/" + cp runners/agent-runner/src/ollama-mcp-stdio.ts "$dir/" + cp runners/agent-runner/src/index.ts "$dir/" done ``` @@ -82,7 +82,7 @@ done ```bash npm run build -./container/build.sh +./runners/build.sh ``` Build must be clean before proceeding. @@ -138,9 +138,9 @@ Look for: ### Agent says "Ollama is not installed" The agent is trying to run `ollama` CLI inside the container instead of using the MCP tools. This means: -1. The MCP server wasn't registered — check `container/agent-runner/src/index.ts` has the `ollama` entry in `mcpServers` +1. The MCP server wasn't registered — check `runners/agent-runner/src/index.ts` has the `ollama` entry in `mcpServers` 2. The per-group source wasn't updated — re-copy files (see Phase 2) -3. The container wasn't rebuilt — run `./container/build.sh` +3. The container wasn't rebuilt — run `./runners/build.sh` ### "Failed to connect to Ollama" diff --git a/.claude/skills/add-parallel/SKILL.md b/.claude/skills/add-parallel/SKILL.md index f4c1982..3bc69e6 100644 --- a/.claude/skills/add-parallel/SKILL.md +++ b/.claude/skills/add-parallel/SKILL.md @@ -78,7 +78,7 @@ const allowedVars = ['CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY', 'PARALLEL_A ### 4. Configure MCP Servers in Agent Runner -Update `container/agent-runner/src/index.ts`: +Update `runners/agent-runner/src/index.ts`: Find the section where `mcpServers` is configured (around line 237-252): ```typescript @@ -219,7 +219,7 @@ AskUserQuestion: I can do deep research on [topic] using Parallel's Task API. Th Build the container with updated agent runner: ```bash -./container/build.sh +./runners/build.sh ``` Verify the build: @@ -286,5 +286,5 @@ To remove Parallel AI integration: 1. Remove from .env: `sed -i.bak '/PARALLEL_API_KEY/d' .env` 2. Revert changes to container-runner.ts and agent-runner/src/index.ts 3. Remove Web Research Tools section from groups/main/CLAUDE.md -4. Rebuild: `./container/build.sh && npm run build` +4. Rebuild: `./runners/build.sh && npm run build` 5. Restart: `launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux) diff --git a/.claude/skills/add-pdf-reader/SKILL.md b/.claude/skills/add-pdf-reader/SKILL.md index cd3736b..3126113 100644 --- a/.claude/skills/add-pdf-reader/SKILL.md +++ b/.claude/skills/add-pdf-reader/SKILL.md @@ -9,7 +9,7 @@ Adds PDF reading capability to all container agents using poppler-utils (pdftote ## Phase 1: Pre-flight -1. Check if `container/skills/pdf-reader/pdf-reader` exists — skip to Phase 3 if already applied +1. Check if `runners/skills/pdf-reader/pdf-reader` exists — skip to Phase 3 if already applied 2. Confirm WhatsApp is installed first (`skill/whatsapp` merged). This skill modifies WhatsApp channel files. ## Phase 2: Apply Code Changes @@ -34,9 +34,9 @@ git merge whatsapp/skill/pdf-reader ``` This merges in: -- `container/skills/pdf-reader/SKILL.md` (agent-facing documentation) -- `container/skills/pdf-reader/pdf-reader` (CLI script) -- `poppler-utils` in `container/Dockerfile` +- `runners/skills/pdf-reader/SKILL.md` (agent-facing documentation) +- `runners/skills/pdf-reader/pdf-reader` (CLI script) +- `poppler-utils` in `runners/Dockerfile` - PDF attachment download in `src/channels/whatsapp.ts` - PDF tests in `src/channels/whatsapp.test.ts` @@ -52,7 +52,7 @@ npx vitest run src/channels/whatsapp.test.ts ### Rebuild container ```bash -./container/build.sh +./runners/build.sh ``` ### Restart service @@ -89,7 +89,7 @@ Look for: ### Agent says pdf-reader command not found -Container needs rebuilding. Run `./container/build.sh` and restart the service. +Container needs rebuilding. Run `./runners/build.sh` and restart the service. ### PDF text extraction is empty diff --git a/.claude/skills/add-reactions/SKILL.md b/.claude/skills/add-reactions/SKILL.md index be725c3..56ce275 100644 --- a/.claude/skills/add-reactions/SKILL.md +++ b/.claude/skills/add-reactions/SKILL.md @@ -44,8 +44,8 @@ This adds: - `scripts/migrate-reactions.ts` (database migration for `reactions` table with composite PK and indexes) - `src/status-tracker.ts` (forward-only emoji state machine for message lifecycle signaling, with persistence and retry) - `src/status-tracker.test.ts` (unit tests for StatusTracker) -- `container/skills/reactions/SKILL.md` (agent-facing documentation for the `react_to_message` MCP tool) -- Reaction support in `src/db.ts`, `src/channels/whatsapp.ts`, `src/types.ts`, `src/ipc.ts`, `src/index.ts`, `src/group-queue.ts`, and `container/agent-runner/src/ipc-mcp-stdio.ts` +- `runners/skills/reactions/SKILL.md` (agent-facing documentation for the `react_to_message` MCP tool) +- Reaction support in `src/db.ts`, `src/channels/whatsapp.ts`, `src/types.ts`, `src/ipc.ts`, `src/index.ts`, `src/group-queue.ts`, and `runners/agent-runner/src/ipc-mcp-stdio.ts` ### Run database migration diff --git a/.claude/skills/add-telegram-swarm/SKILL.md b/.claude/skills/add-telegram-swarm/SKILL.md index ac4922c..a9932da 100644 --- a/.claude/skills/add-telegram-swarm/SKILL.md +++ b/.claude/skills/add-telegram-swarm/SKILL.md @@ -168,7 +168,7 @@ export async function sendPoolMessage( ### Step 3: Add sender Parameter to MCP Tool -Read `container/agent-runner/src/ipc-mcp-stdio.ts` and update the `send_message` tool to accept an optional `sender` parameter: +Read `runners/agent-runner/src/ipc-mcp-stdio.ts` and update the `send_message` tool to accept an optional `sender` parameter: Change the tool's schema from: ```typescript @@ -320,7 +320,7 @@ Also add `TELEGRAM_BOT_POOL` to the launchd plist (`~/Library/LaunchAgents/com.n ```bash npm run build -./container/build.sh # Required — MCP tool changed +./runners/build.sh # Required — MCP tool changed # macOS: launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist @@ -378,7 +378,7 @@ To remove Agent Swarm support while keeping basic Telegram: 2. Remove pool code from `src/telegram.ts` (`poolApis`, `senderBotMap`, `initBotPool`, `sendPoolMessage`) 3. Remove pool routing from IPC handler in `src/index.ts` (revert to plain `sendMessage`) 4. Remove `initBotPool` call from `main()` -5. Remove `sender` param from MCP tool in `container/agent-runner/src/ipc-mcp-stdio.ts` +5. Remove `sender` param from MCP tool in `runners/agent-runner/src/ipc-mcp-stdio.ts` 6. Remove Agent Teams section from group CLAUDE.md files 7. Remove `TELEGRAM_BOT_POOL` from `.env`, `data/env/env`, and launchd plist/systemd unit -8. Rebuild: `npm run build && ./container/build.sh && launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist && launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist` (macOS) or `npm run build && ./container/build.sh && systemctl --user restart nanoclaw` (Linux) +8. Rebuild: `npm run build && ./runners/build.sh && launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist && launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist` (macOS) or `npm run build && ./runners/build.sh && systemctl --user restart nanoclaw` (Linux) diff --git a/.claude/skills/convert-to-apple-container/SKILL.md b/.claude/skills/convert-to-apple-container/SKILL.md index caf9c22..fc62eb0 100644 --- a/.claude/skills/convert-to-apple-container/SKILL.md +++ b/.claude/skills/convert-to-apple-container/SKILL.md @@ -72,8 +72,8 @@ This merges in: - `src/container-runtime.ts` — Apple Container implementation (replaces Docker) - `src/container-runtime.test.ts` — Apple Container-specific tests - `src/container-runner.ts` — .env shadow mount fix and privilege dropping -- `container/Dockerfile` — entrypoint that shadows .env via `mount --bind` -- `container/build.sh` — default runtime set to `container` +- `runners/Dockerfile` — entrypoint that shadows .env via `mount --bind` +- `runners/build.sh` — default runtime set to `container` If the merge reports conflicts, resolve them by reading the conflicted files and understanding the intent of both sides. @@ -97,7 +97,7 @@ container system status || container system start ### Build the container image ```bash -./container/build.sh +./runners/build.sh ``` ### Test basic execution @@ -158,7 +158,7 @@ container system status ```bash # Clean rebuild — Apple Container caches aggressively container builder stop && container builder rm && container builder start -./container/build.sh +./runners/build.sh ``` **Container can't write to mounted directories:** @@ -171,5 +171,5 @@ Check directory permissions on the host. The container runs as uid 1000. | `src/container-runtime.ts` | Full replacement — Docker → Apple Container API | | `src/container-runtime.test.ts` | Full replacement — tests for Apple Container behavior | | `src/container-runner.ts` | .env shadow mount removed, main containers start as root with privilege drop | -| `container/Dockerfile` | Entrypoint: `mount --bind` for .env shadowing, `setpriv` privilege drop | -| `container/build.sh` | Default runtime: `docker` → `container` | +| `runners/Dockerfile` | Entrypoint: `mount --bind` for .env shadowing, `setpriv` privilege drop | +| `runners/build.sh` | Default runtime: `docker` → `container` | diff --git a/.claude/skills/debug/SKILL.md b/.claude/skills/debug/SKILL.md index 03c34de..2edfa81 100644 --- a/.claude/skills/debug/SKILL.md +++ b/.claude/skills/debug/SKILL.md @@ -12,7 +12,7 @@ This guide covers debugging the containerized agent execution system. ``` Host (macOS) Container (Linux VM) ───────────────────────────────────────────────────────────── -src/container-runner.ts container/agent-runner/ +src/container-runner.ts runners/agent-runner/ │ │ │ spawns container │ runs Claude Agent SDK │ with volume mounts │ with MCP servers @@ -234,11 +234,11 @@ query({ npm run build # Rebuild container (use --no-cache for clean rebuild) -./container/build.sh +./runners/build.sh # Or force full rebuild docker builder prune -af -./container/build.sh +./runners/build.sh ``` ## Checking Container Image @@ -332,7 +332,7 @@ echo -e "\n3. Container runtime running?" docker info &>/dev/null && echo "OK" || echo "NOT RUNNING - start Docker Desktop (macOS) or sudo systemctl start docker (Linux)" echo -e "\n4. Container image exists?" -echo '{}' | docker run -i --entrypoint /bin/echo nanoclaw-agent:latest "OK" 2>/dev/null || echo "MISSING - run ./container/build.sh" +echo '{}' | docker run -i --entrypoint /bin/echo nanoclaw-agent:latest "OK" 2>/dev/null || echo "MISSING - run ./runners/build.sh" echo -e "\n5. Session mount path correct?" grep -q "/home/node/.claude" src/container-runner.ts 2>/dev/null && echo "OK" || echo "WRONG - should mount to /home/node/.claude/, not /root/.claude/" diff --git a/.claude/skills/setup/SKILL.md b/.claude/skills/setup/SKILL.md index 02e9a87..e2a374f 100644 --- a/.claude/skills/setup/SKILL.md +++ b/.claude/skills/setup/SKILL.md @@ -11,7 +11,7 @@ Run setup steps automatically. Only pause when user action is required (channel **UX Note:** Use `AskUserQuestion` for all user-facing questions. -**Architecture:** NanoClaw runs agents as direct host processes (no Docker/containers). Each agent type (Claude Code, Codex) has its own runner in `container/agent-runner/` and `container/codex-runner/`. +**Architecture:** NanoClaw runs agents as direct host processes (no Docker/containers). Each agent type (Claude Code, Codex) has its own runner in `runners/agent-runner/` and `runners/codex-runner/`. ## 0. Git & Fork Setup @@ -76,12 +76,12 @@ Run `npx tsx setup/index.ts --step environment` and parse the status block. Run `npx tsx setup/index.ts --step runners` and parse the status block. This builds the agent runners that execute as host processes: -- `container/agent-runner/` — Claude Code agent (via Claude Agent SDK) -- `container/codex-runner/` — Codex agent (via Codex CLI) +- `runners/agent-runner/` — Claude Code agent (via Claude Agent SDK) +- `runners/codex-runner/` — Codex agent (via Codex CLI) -**If BUILD_OK=false:** Read `logs/setup.log` for the error. Common fix: `cd container/agent-runner && npm install && npm run build`. +**If BUILD_OK=false:** Read `logs/setup.log` for the error. Common fix: `cd runners/agent-runner && npm install && npm run build`. -**If CODEX_RUNNER=false but AGENT_RUNNER=true:** Codex runner failed to build. Not critical if you only use Claude Code. Fix: `cd container/codex-runner && npm install && npm run build`. +**If CODEX_RUNNER=false but AGENT_RUNNER=true:** Codex runner failed to build. Not critical if you only use Claude Code. Fix: `cd runners/codex-runner && npm install && npm run build`. ## 4. Claude Authentication (No Script) diff --git a/.claude/skills/update-nanoclaw/SKILL.md b/.claude/skills/update-nanoclaw/SKILL.md index b0b478c..43cb9d9 100644 --- a/.claude/skills/update-nanoclaw/SKILL.md +++ b/.claude/skills/update-nanoclaw/SKILL.md @@ -18,7 +18,7 @@ Run `/update-nanoclaw` in Claude Code. **Preview**: runs `git log` and `git diff` against the merge base to show upstream changes since your last sync. Groups changed files into categories: - **Skills** (`.claude/skills/`): unlikely to conflict unless you edited an upstream skill - **Source** (`src/`): may conflict if you modified the same files -- **Build/config** (`package.json`, `tsconfig*.json`, `container/`): review needed +- **Build/config** (`package.json`, `tsconfig*.json`, `runners/`): review needed **Update paths** (you pick one): - `merge` (default): `git merge upstream/`. Resolves all conflicts in one pass. @@ -109,7 +109,7 @@ Show file-level impact from upstream: Bucket the upstream changed files: - **Skills** (`.claude/skills/`): unlikely to conflict unless the user edited an upstream skill - **Source** (`src/`): may conflict if user modified the same files -- **Build/config** (`package.json`, `package-lock.json`, `tsconfig*.json`, `container/`, `launchd/`): review needed +- **Build/config** (`package.json`, `package-lock.json`, `tsconfig*.json`, `runners/`, `launchd/`): review needed - **Other**: docs, tests, misc Present these buckets to the user and ask them to choose one path using AskUserQuestion: diff --git a/.claude/skills/x-integration/SKILL.md b/.claude/skills/x-integration/SKILL.md index 29a7be6..3abf1e1 100644 --- a/.claude/skills/x-integration/SKILL.md +++ b/.claude/skills/x-integration/SKILL.md @@ -44,7 +44,7 @@ npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts # Verify: data/x-auth.json should exist after successful login # 2. Rebuild container to include skill -./container/build.sh +./runners/build.sh # Verify: Output shows "COPY .claude/skills/x-integration/agent.ts" # 3. Rebuild host and restart service @@ -181,7 +181,7 @@ if (!handled) { --- -**2. Container side: `container/agent-runner/src/ipc-mcp.ts`** +**2. Container side: `runners/agent-runner/src/ipc-mcp.ts`** Add import after `cron-parser` import: ```typescript @@ -196,21 +196,21 @@ Add to the end of tools array (before the closing `]`): --- -**3. Build script: `container/build.sh`** +**3. Build script: `runners/build.sh`** -Change build context from `container/` to project root (required to access `.claude/skills/`): +Change build context from `runners/` to project root (required to access `.claude/skills/`): ```bash # Find: docker build -t "${IMAGE_NAME}:${TAG}" . # Replace with: cd "$SCRIPT_DIR/.." -docker build -t "${IMAGE_NAME}:${TAG}" -f container/Dockerfile . +docker build -t "${IMAGE_NAME}:${TAG}" -f runners/Dockerfile . ``` --- -**4. Dockerfile: `container/Dockerfile`** +**4. Dockerfile: `runners/Dockerfile`** First, update the build context paths (required to access `.claude/skills/` from project root): ```dockerfile @@ -220,12 +220,12 @@ COPY agent-runner/package*.json ./ COPY agent-runner/ ./ # Replace with: -COPY container/agent-runner/package*.json ./ +COPY runners/agent-runner/package*.json ./ ... -COPY container/agent-runner/ ./ +COPY runners/agent-runner/ ./ ``` -Then add COPY line after `COPY container/agent-runner/ ./` and before `RUN npm run build`: +Then add COPY line after `COPY runners/agent-runner/ ./` and before `RUN npm run build`: ```dockerfile # Copy skill MCP tools COPY .claude/skills/x-integration/agent.ts ./src/skills/x-integration/ @@ -260,12 +260,12 @@ cat data/x-auth.json # Should show {"authenticated": true, ...} ### 3. Rebuild Container ```bash -./container/build.sh +./runners/build.sh ``` **Verify success:** ```bash -./container/build.sh 2>&1 | grep -i "agent.ts" # Should show COPY line +./runners/build.sh 2>&1 | grep -i "agent.ts" # Should show COPY line ``` ### 4. Restart Service @@ -403,7 +403,7 @@ If MCP tools not found in container: ```bash # Verify build copies skill -./container/build.sh 2>&1 | grep -i skill +./runners/build.sh 2>&1 | grep -i skill # Check container has the file docker run nanoclaw-agent ls -la /app/src/skills/ diff --git a/CLAUDE.md b/CLAUDE.md index 6342cef..915a319 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -18,8 +18,8 @@ Two systemd services (`nanoclaw`, `nanoclaw-codex`) share the same codebase but | `src/config.ts` | Trigger pattern, paths, intervals | | `src/task-scheduler.ts` | Runs scheduled tasks | | `src/db.ts` | SQLite operations | -| `container/agent-runner/` | Claude Code runner (Agent SDK) | -| `container/codex-runner/` | Codex runner (SDK, `codex exec` wrapper) | +| `runners/agent-runner/` | Claude Code runner (Agent SDK) | +| `runners/codex-runner/` | Codex runner (SDK, `codex exec` wrapper) | | `groups/{name}/CLAUDE.md` | Per-group memory (isolated) | ## Skills diff --git a/README.md b/README.md index 27aaae1..25df2a7 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ nanoclaw/ │ └── channels/ │ ├── registry.ts # Channel self-registration system │ └── discord.ts # Discord: mentions, images, typing, file attachments -├── container/ +├── runners/ │ ├── agent-runner/ # Claude Code runner (Agent SDK, multimodal input) │ ├── codex-runner/ # Codex runner (app-server JSON-RPC, auto-continue) │ └── skills/ # Shared agent skills (browser, etc.) @@ -77,7 +77,7 @@ nanoclaw/ ### Codex App-Server Integration -The Codex runner (`container/codex-runner/`) communicates with `codex app-server` via JSON-RPC over stdio: +The Codex runner (`runners/codex-runner/`) communicates with `codex app-server` via JSON-RPC over stdio: - **Session persistence**: Thread IDs stored in DB, sessions saved as JSONL on disk - **Streaming**: `item/agentMessage/delta` notifications for real-time text @@ -98,7 +98,7 @@ Bidirectional image support through Discord: Skills are managed from a single source of truth (`~/.claude/skills/` on the server) and automatically synced to all agent session directories at process start: -- Claude Code sessions: `~/.claude/skills/` + project `container/skills/` +- Claude Code sessions: `~/.claude/skills/` + project `runners/skills/` - Codex sessions: Same sources, synced to per-group `.codex/` directories - Skills auto-register as slash commands (`/name`) in Claude Code and `$name` in Codex diff --git a/docs/SPEC.md b/docs/SPEC.md index d2b4723..fd6e535 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -268,7 +268,7 @@ nanoclaw/ │ ├── task-scheduler.ts # Runs scheduled tasks when due │ └── container-runner.ts # Spawns agents in containers │ -├── container/ +├── runners/ │ ├── Dockerfile # Container image (runs as 'node' user, includes Claude Code CLI) │ ├── build.sh # Build script for container image │ ├── agent-runner/ # Code that runs inside the container diff --git a/package.json b/package.json index e5e98e5..8831677 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "dist/index.js", "scripts": { "build": "tsc", - "build:runners": "cd container/agent-runner && npm install && npm run build && cd ../codex-runner && npm install && npm run build", + "build:runners": "cd runners/agent-runner && npm install && npm run build && cd ../codex-runner && npm install && npm run build", "start": "node dist/index.js", "dev": "tsx src/index.ts", "typecheck": "tsc --noEmit", diff --git a/container/agent-runner/package-lock.json b/runners/agent-runner/package-lock.json similarity index 100% rename from container/agent-runner/package-lock.json rename to runners/agent-runner/package-lock.json diff --git a/container/agent-runner/package.json b/runners/agent-runner/package.json similarity index 100% rename from container/agent-runner/package.json rename to runners/agent-runner/package.json diff --git a/container/agent-runner/src/index.ts b/runners/agent-runner/src/index.ts similarity index 100% rename from container/agent-runner/src/index.ts rename to runners/agent-runner/src/index.ts diff --git a/container/agent-runner/src/ipc-mcp-stdio.ts b/runners/agent-runner/src/ipc-mcp-stdio.ts similarity index 100% rename from container/agent-runner/src/ipc-mcp-stdio.ts rename to runners/agent-runner/src/ipc-mcp-stdio.ts diff --git a/container/agent-runner/tsconfig.json b/runners/agent-runner/tsconfig.json similarity index 100% rename from container/agent-runner/tsconfig.json rename to runners/agent-runner/tsconfig.json diff --git a/container/codex-runner/package-lock.json b/runners/codex-runner/package-lock.json similarity index 100% rename from container/codex-runner/package-lock.json rename to runners/codex-runner/package-lock.json diff --git a/container/codex-runner/package.json b/runners/codex-runner/package.json similarity index 100% rename from container/codex-runner/package.json rename to runners/codex-runner/package.json diff --git a/container/codex-runner/src/index.ts b/runners/codex-runner/src/index.ts similarity index 100% rename from container/codex-runner/src/index.ts rename to runners/codex-runner/src/index.ts diff --git a/container/codex-runner/tsconfig.json b/runners/codex-runner/tsconfig.json similarity index 100% rename from container/codex-runner/tsconfig.json rename to runners/codex-runner/tsconfig.json diff --git a/container/skills/agent-browser/SKILL.md b/runners/skills/agent-browser/SKILL.md similarity index 100% rename from container/skills/agent-browser/SKILL.md rename to runners/skills/agent-browser/SKILL.md diff --git a/src/agent-runner.ts b/src/agent-runner.ts index 1664726..71354df 100644 --- a/src/agent-runner.ts +++ b/src/agent-runner.ts @@ -82,14 +82,14 @@ function prepareGroupEnvironment( } // Sync skills into each group's .claude/ session dir - // Sources: 1) user's global ~/.claude/skills 2) project workDir/.claude/skills 3) container/skills/ + // Sources: 1) user's global ~/.claude/skills 2) project workDir/.claude/skills 3) runners/skills/ const workDirClaude = group.workDir ? path.join(group.workDir, '.claude') : null; const skillSources = [ path.join(os.homedir(), '.claude', 'skills'), ...(workDirClaude ? [path.join(workDirClaude, 'skills')] : []), - path.join(projectRoot, 'container', 'skills'), + path.join(projectRoot, 'runners', 'skills'), ]; const skillsDst = path.join(groupSessionsDir, 'skills'); for (const src of skillSources) { @@ -128,7 +128,7 @@ function prepareGroupEnvironment( // Determine runner directory const agentType = group.agentType || 'claude-code'; const runnerDirName = agentType === 'codex' ? 'codex-runner' : 'agent-runner'; - const runnerDir = path.join(projectRoot, 'container', runnerDirName); + const runnerDir = path.join(projectRoot, 'runners', runnerDirName); // Build environment variables for the runner process const envVars = readEnvFile([ @@ -222,10 +222,10 @@ function prepareGroupEnvironment( } } // Sync skills into Codex session dir - // SSOT: ~/.claude/skills/ (shared with Claude Code) + container/skills/ + // SSOT: ~/.claude/skills/ (shared with Claude Code) + runners/skills/ const codexSkillSources = [ path.join(os.homedir(), '.claude', 'skills'), - path.join(projectRoot, 'container', 'skills'), + path.join(projectRoot, 'runners', 'skills'), ]; const codexSkillsDst = path.join(sessionCodexDir, 'skills'); for (const src of codexSkillSources) { @@ -245,7 +245,7 @@ function prepareGroupEnvironment( // Inject nanoclaw MCP server into Codex config.toml const mcpServerPath = path.join( projectRoot, - 'container', + 'runners', 'agent-runner', 'dist', 'ipc-mcp-stdio.js', @@ -333,7 +333,7 @@ export async function runAgentProcess( if (!fs.existsSync(distEntry)) { logger.error( { runnerDir }, - 'Runner not built. Run: cd container/agent-runner && npm install && npm run build', + 'Runner not built. Run: cd runners/agent-runner && npm install && npm run build', ); return { status: 'error',