From 8cbd715ee2fcb7640103379008a97d4f6307da37 Mon Sep 17 00:00:00 2001 From: Akshan Krithick Date: Sat, 14 Mar 2026 21:33:48 -0700 Subject: [PATCH 1/3] add read-only /capabilities and /status skills --- CLAUDE.md | 2 + container/skills/capabilities/SKILL.md | 100 ++++++++++++++++++++++++ container/skills/status/SKILL.md | 104 +++++++++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 container/skills/capabilities/SKILL.md create mode 100644 container/skills/status/SKILL.md diff --git a/CLAUDE.md b/CLAUDE.md index 318d6dd..b86c0ed 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -31,6 +31,8 @@ Single Node.js process with skill-based channel system. Channels (WhatsApp, Tele | `/update-nanoclaw` | Bring upstream NanoClaw updates into a customized install | | `/qodo-pr-resolver` | Fetch and fix Qodo PR review issues interactively or in batch | | `/get-qodo-rules` | Load org- and repo-level coding rules from Qodo before code tasks | +| `/capabilities` | Show installed skills, tools, and system info (main channel, read-only) | +| `/status` | Quick health check — session, workspace, tools, tasks (main channel, read-only) | ## Development diff --git a/container/skills/capabilities/SKILL.md b/container/skills/capabilities/SKILL.md new file mode 100644 index 0000000..8e8be14 --- /dev/null +++ b/container/skills/capabilities/SKILL.md @@ -0,0 +1,100 @@ +--- +name: capabilities +description: Show what this NanoClaw instance can do — installed skills, available tools, and system info. Read-only. Use when the user asks what the bot can do, what's installed, or runs /capabilities. +--- + +# /capabilities — System Capabilities Report + +Generate a structured read-only report of what this NanoClaw instance can do. + +**Main-channel check:** Only the main channel has `/workspace/project` mounted. Run: + +```bash +test -d /workspace/project && echo "MAIN" || echo "NOT_MAIN" +``` + +If `NOT_MAIN`, respond with: +> This command is available in your main chat only. Send `/capabilities` there to see what I can do. + +Then stop — do not generate the report. + +## How to gather the information + +Run these commands and compile the results into the report format below. + +### 1. Installed skills + +List skill directories available to you: + +```bash +ls -1 /home/node/.claude/skills/ 2>/dev/null || echo "No skills found" +``` + +Each directory is an installed skill. The directory name is the skill name (e.g., `agent-browser` → `/agent-browser`). + +### 2. Available tools + +Read the allowed tools from your SDK configuration. You always have access to: +- **Core:** Bash, Read, Write, Edit, Glob, Grep +- **Web:** WebSearch, WebFetch +- **Orchestration:** Task, TaskOutput, TaskStop, TeamCreate, TeamDelete, SendMessage +- **Other:** TodoWrite, ToolSearch, Skill, NotebookEdit +- **MCP:** mcp__nanoclaw__* (messaging, tasks, group management) + +### 3. MCP server tools + +The NanoClaw MCP server exposes these tools (via `mcp__nanoclaw__*` prefix): +- `send_message` — send a message to the user/group +- `schedule_task` — schedule a recurring or one-time task +- `list_tasks` — list scheduled tasks +- `pause_task` — pause a scheduled task +- `resume_task` — resume a paused task +- `cancel_task` — cancel and delete a task +- `update_task` — update an existing task +- `register_group` — register a new chat/group (main only) + +### 4. Container skills (Bash tools) + +Check for executable tools in the container: + +```bash +which agent-browser 2>/dev/null && echo "agent-browser: available" || echo "agent-browser: not found" +``` + +### 5. Group info + +```bash +ls /workspace/group/CLAUDE.md 2>/dev/null && echo "Group memory: yes" || echo "Group memory: no" +ls /workspace/extra/ 2>/dev/null && echo "Extra mounts: $(ls /workspace/extra/ 2>/dev/null | wc -l | tr -d ' ')" || echo "Extra mounts: none" +``` + +## Report format + +Present the report as a clean, readable message. Example: + +``` +📋 *NanoClaw Capabilities* + +*Installed Skills:* +• /agent-browser — Browse the web, fill forms, extract data +• /capabilities — This report +(list all found skills) + +*Tools:* +• Core: Bash, Read, Write, Edit, Glob, Grep +• Web: WebSearch, WebFetch +• Orchestration: Task, TeamCreate, SendMessage +• MCP: send_message, schedule_task, list_tasks, pause/resume/cancel/update_task, register_group + +*Container Tools:* +• agent-browser: ✓ + +*System:* +• Group memory: yes/no +• Extra mounts: N directories +• Main channel: yes +``` + +Adapt the output based on what you actually find — don't list things that aren't installed. + +**See also:** `/status` for a quick health check of session, workspace, and tasks. diff --git a/container/skills/status/SKILL.md b/container/skills/status/SKILL.md new file mode 100644 index 0000000..3a99fcc --- /dev/null +++ b/container/skills/status/SKILL.md @@ -0,0 +1,104 @@ +--- +name: status +description: Quick read-only health check — session context, workspace mounts, tool availability, and task snapshot. Use when the user asks for system status or runs /status. +--- + +# /status — System Status Check + +Generate a quick read-only status report of the current agent environment. + +**Main-channel check:** Only the main channel has `/workspace/project` mounted. Run: + +```bash +test -d /workspace/project && echo "MAIN" || echo "NOT_MAIN" +``` + +If `NOT_MAIN`, respond with: +> This command is available in your main chat only. Send `/status` there to check system status. + +Then stop — do not generate the report. + +## How to gather the information + +Run the checks below and compile results into the report format. + +### 1. Session context + +```bash +echo "Timestamp: $(date)" +echo "Working dir: $(pwd)" +echo "Channel: main" +``` + +### 2. Workspace and mount visibility + +```bash +echo "=== Workspace ===" +ls /workspace/ 2>/dev/null +echo "=== Group folder ===" +ls /workspace/group/ 2>/dev/null | head -20 +echo "=== Extra mounts ===" +ls /workspace/extra/ 2>/dev/null || echo "none" +echo "=== IPC ===" +ls /workspace/ipc/ 2>/dev/null +``` + +### 3. Tool availability + +Confirm which tool families are available to you: + +- **Core:** Bash, Read, Write, Edit, Glob, Grep +- **Web:** WebSearch, WebFetch +- **Orchestration:** Task, TaskOutput, TaskStop, TeamCreate, TeamDelete, SendMessage +- **MCP:** mcp__nanoclaw__* (send_message, schedule_task, list_tasks, pause_task, resume_task, cancel_task, update_task, register_group) + +### 4. Container utilities + +```bash +which agent-browser 2>/dev/null && echo "agent-browser: available" || echo "agent-browser: not installed" +node --version 2>/dev/null +claude --version 2>/dev/null +``` + +### 5. Task snapshot + +Use the MCP tool to list tasks: + +``` +Call mcp__nanoclaw__list_tasks to get scheduled tasks. +``` + +If no tasks exist, report "No scheduled tasks." + +## Report format + +Present as a clean, readable message: + +``` +🔍 *NanoClaw Status* + +*Session:* +• Channel: main +• Time: 2026-03-14 09:30 UTC +• Working dir: /workspace/group + +*Workspace:* +• Group folder: ✓ (N files) +• Extra mounts: none / N directories +• IPC: ✓ (messages, tasks, input) + +*Tools:* +• Core: ✓ Web: ✓ Orchestration: ✓ MCP: ✓ + +*Container:* +• agent-browser: ✓ / not installed +• Node: vXX.X.X +• Claude Code: vX.X.X + +*Scheduled Tasks:* +• N active tasks / No scheduled tasks +``` + +Adapt based on what you actually find. Keep it concise — this is a quick health check, not a deep diagnostic. + +**See also:** `/capabilities` for a full list of installed skills and tools. From de62ef6b3f612043e614d85103c37a9fb553cd38 Mon Sep 17 00:00:00 2001 From: Akshan Krithick Date: Sat, 14 Mar 2026 21:41:56 -0700 Subject: [PATCH 2/3] format remote-control files with Prettier --- src/remote-control.test.ts | 43 +++++++++++++++++++++++++------------- src/remote-control.ts | 8 ++++--- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/remote-control.test.ts b/src/remote-control.test.ts index 4b5ab2f..1fa434b 100644 --- a/src/remote-control.test.ts +++ b/src/remote-control.test.ts @@ -45,14 +45,20 @@ describe('remote-control', () => { stdoutFileContent = ''; // Default fs mocks - mkdirSyncSpy = vi.spyOn(fs, 'mkdirSync').mockImplementation(() => undefined as any); - writeFileSyncSpy = vi.spyOn(fs, 'writeFileSync').mockImplementation(() => {}); + mkdirSyncSpy = vi + .spyOn(fs, 'mkdirSync') + .mockImplementation(() => undefined as any); + writeFileSyncSpy = vi + .spyOn(fs, 'writeFileSync') + .mockImplementation(() => {}); unlinkSyncSpy = vi.spyOn(fs, 'unlinkSync').mockImplementation(() => {}); openSyncSpy = vi.spyOn(fs, 'openSync').mockReturnValue(42 as any); closeSyncSpy = vi.spyOn(fs, 'closeSync').mockImplementation(() => {}); // readFileSync: return stdoutFileContent for the stdout file, state file, etc. - readFileSyncSpy = vi.spyOn(fs, 'readFileSync').mockImplementation(((p: string) => { + readFileSyncSpy = vi.spyOn(fs, 'readFileSync').mockImplementation((( + p: string, + ) => { if (p.endsWith('remote-control.stdout')) return stdoutFileContent; if (p.endsWith('remote-control.json')) { throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' }); @@ -74,7 +80,8 @@ describe('remote-control', () => { spawnMock.mockReturnValue(proc); // Simulate URL appearing in stdout file on first poll - stdoutFileContent = 'Session URL: https://claude.ai/code?bridge=env_abc123\n'; + stdoutFileContent = + 'Session URL: https://claude.ai/code?bridge=env_abc123\n'; vi.spyOn(process, 'kill').mockImplementation((() => true) as any); const result = await startRemoteControl('user1', 'tg:123', '/project'); @@ -157,7 +164,9 @@ describe('remote-control', () => { spawnMock.mockReturnValueOnce(proc1).mockReturnValueOnce(proc2); // First start: process alive, URL found - const killSpy = vi.spyOn(process, 'kill').mockImplementation((() => true) as any); + const killSpy = vi + .spyOn(process, 'kill') + .mockImplementation((() => true) as any); stdoutFileContent = 'https://claude.ai/code?bridge=env_first\n'; await startRemoteControl('user1', 'tg:123', '/project'); @@ -239,7 +248,9 @@ describe('remote-control', () => { const proc = createMockProcess(55555); spawnMock.mockReturnValue(proc); stdoutFileContent = 'https://claude.ai/code?bridge=env_stop\n'; - const killSpy = vi.spyOn(process, 'kill').mockImplementation((() => true) as any); + const killSpy = vi + .spyOn(process, 'kill') + .mockImplementation((() => true) as any); await startRemoteControl('user1', 'tg:123', '/project'); @@ -337,7 +348,9 @@ describe('remote-control', () => { if (p.endsWith('remote-control.json')) return JSON.stringify(session); return ''; }) as any); - const killSpy = vi.spyOn(process, 'kill').mockImplementation((() => true) as any); + const killSpy = vi + .spyOn(process, 'kill') + .mockImplementation((() => true) as any); restoreRemoteControl(); expect(getActiveSession()).not.toBeNull(); @@ -365,13 +378,15 @@ describe('remote-control', () => { restoreRemoteControl(); - return startRemoteControl('user2', 'tg:456', '/project').then((result) => { - expect(result).toEqual({ - ok: true, - url: 'https://claude.ai/code?bridge=env_restored', - }); - expect(spawnMock).not.toHaveBeenCalled(); - }); + return startRemoteControl('user2', 'tg:456', '/project').then( + (result) => { + expect(result).toEqual({ + ok: true, + url: 'https://claude.ai/code?bridge=env_restored', + }); + expect(spawnMock).not.toHaveBeenCalled(); + }, + ); }); }); }); diff --git a/src/remote-control.ts b/src/remote-control.ts index df8f646..015aa7f 100644 --- a/src/remote-control.ts +++ b/src/remote-control.ts @@ -196,9 +196,11 @@ export async function startRemoteControl( }); } -export function stopRemoteControl(): { - ok: true; -} | { ok: false; error: string } { +export function stopRemoteControl(): + | { + ok: true; + } + | { ok: false; error: string } { if (!activeSession) { return { ok: false, error: 'No active Remote Control session' }; } From 96852f686e08be28a3ee3fd2da4a74934b850b28 Mon Sep 17 00:00:00 2001 From: gavrielc Date: Wed, 18 Mar 2026 12:08:22 +0200 Subject: [PATCH 3/3] Apply suggestion from @gavrielc --- CLAUDE.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b86c0ed..318d6dd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -31,8 +31,6 @@ Single Node.js process with skill-based channel system. Channels (WhatsApp, Tele | `/update-nanoclaw` | Bring upstream NanoClaw updates into a customized install | | `/qodo-pr-resolver` | Fetch and fix Qodo PR review issues interactively or in batch | | `/get-qodo-rules` | Load org- and repo-level coding rules from Qodo before code tasks | -| `/capabilities` | Show installed skills, tools, and system info (main channel, read-only) | -| `/status` | Quick health check — session, workspace, tools, tasks (main channel, read-only) | ## Development