NanoClaw 是一個只有幾個核心檔案的個人 Claude 助理,透過 WhatsApp 與你對話,每次對話都在獨立的 Linux Container 中執行。它的設計哲學直接挑戰了「功能越多越好」的常見思維——整個系統只有一個 Node.js process、一個 SQLite 資料庫、一個 polling loop,卻實現了多群組隔離、排程任務、檔案系統安全等企業級功能。讀完這份原始碼,你會學到如何用 Container 隔離取代應用層權限檢查、如何透過 filesystem-based IPC 讓沙箱內的 agent 與外界安全通訊,以及「Skills over Features」的 AI-native 擴展模式。
NanoClaw GitHub Repository — 專案原始碼,包含本文解讀的所有設計實作
專案概覽
NanoClaw 是一個運行在 macOS/Linux 上的個人 Claude 助理。使用者透過 WhatsApp 傳送訊息,系統將訊息路由到 Claude Agent SDK,在 Apple Container 或 Docker 容器中執行 agent 回覆。
技術棧:TypeScript / Node.js、SQLite(better-sqlite3)、WhatsApp Web(baileys)、Claude Agent SDK、Apple Container / Docker
規模:核心 host process 僅 8 個 TypeScript 檔案(src/ 目錄),容器內 agent runner 僅 2 個檔案。整個 codebase 的邏輯程式碼不超過 1500 行。
架構總覽
WhatsApp (baileys) ──▶ SQLite ──▶ Polling Loop ──▶ Container (Claude Agent SDK) ──▶ Response
│
▼
IPC via Filesystem
│
▼
Host 處理 messages/tasks
nanoclaw/
├── src/ # Host process(全部核心邏輯)
│ ├── index.ts # 入口:WhatsApp 連線、訊息路由、IPC watcher
│ ├── container-runner.ts # 容器生命週期:mount 組裝、spawn、輸出解析
│ ├── db.ts # SQLite schema 與所有查詢
│ ├── task-scheduler.ts # 排程任務引擎
│ ├── mount-security.ts # 掛載安全驗證(allowlist 機制)
│ ├── config.ts # 常數與環境變數
│ ├── types.ts # TypeScript 型別定義
│ └── utils.ts # JSON 讀寫工具
├── container/ # 容器映像
│ ├── Dockerfile # Agent 執行環境
│ └── agent-runner/src/ # 容器內程式碼
│ ├── index.ts # Agent 啟動器(Claude Agent SDK query)
│ └── ipc-mcp.ts # MCP Server:agent 的對外通訊介面
├── groups/ # 每個群組的隔離記憶空間
│ ├── main/CLAUDE.md # 主頻道 prompt(有管理員權限)
│ └── global/CLAUDE.md # 全域共享 prompt
└── .claude/skills/ # Claude Code Skills(擴展機制)
├── setup/SKILL.md
├── customize/SKILL.md
├── debug/SKILL.md
└── add-gmail/SKILL.md
Code language: PHP (php)核心設計解析
設計一:Single Process + Polling Loop 取代事件驅動架構
NanoClaw 的核心是一個極為簡單的 polling loop:每 2 秒從 SQLite 撈取新訊息,依序處理。這個設計刻意避開了 event-driven 架構的複雜度。
src/index.ts — 主入口,包含訊息路由、WhatsApp 連線和 IPC watcher 三大核心邏輯
async function startMessageLoop(): Promise<void> {
if (messageLoopRunning) {
logger.debug('Message loop already running, skipping duplicate start');
return;
}
messageLoopRunning = true;
while (true) {
try {
const jids = Object.keys(registeredGroups);
const { messages } = getNewMessages(jids, lastTimestamp, ASSISTANT_NAME);
for (const msg of messages) {
try {
await processMessage(msg);
// Only advance timestamp after successful processing for at-least-once delivery
lastTimestamp = msg.timestamp;
saveState();
} catch (err) {
logger.error({ err, msg: msg.id }, 'Error processing message, will retry');
break; // Stop processing this batch - failed message will be retried next loop
}
}
} catch (err) {
logger.error({ err }, 'Error in message loop');
}
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
}
}
Code language: JavaScript (javascript)這段程式碼中有幾個值得注意的設計決策:
- At-least-once delivery:
lastTimestamp只在訊息成功處理後才前進。如果處理失敗,下次 loop 會重試同一則訊息。 - Guard flag 防止重複啟動:
messageLoopRunning確保 WhatsApp 重連時不會產生多個 polling loop。 - Sequential processing:訊息嚴格依序處理,
break中斷整個 batch 而非跳過失敗訊息——保證訊息順序。
這種「笨方法」的可靠性遠高於複雜的 message queue 系統,因為狀態機非常簡單:只有一個 timestamp 和一個 while loop。
設計二:Container 隔離作為主要安全邊界
NanoClaw 最核心的設計理念是:安全不靠應用層權限檢查,靠 OS 級隔離。每次 agent 執行都在一個全新的 Container 中,只有明確 mount 的目錄才對 agent 可見。
src/container-runner.ts — 容器生命週期管理,組裝 volume mounts 並 spawn 容器 process
function buildVolumeMounts(
group: RegisteredGroup,
isMain: boolean,
): VolumeMount[] {
const mounts: VolumeMount[] = [];
if (isMain) {
// Main gets the entire project root mounted
mounts.push({
hostPath: projectRoot,
containerPath: '/workspace/project',
readonly: false,
});
mounts.push({
hostPath: path.join(GROUPS_DIR, group.folder),
containerPath: '/workspace/group',
readonly: false,
});
} else {
// Other groups only get their own folder
mounts.push({
hostPath: path.join(GROUPS_DIR, group.folder),
containerPath: '/workspace/group',
readonly: false,
});
// Global memory directory (read-only for non-main)
const globalDir = path.join(GROUPS_DIR, 'global');
if (fs.existsSync(globalDir)) {
mounts.push({
hostPath: globalDir,
containerPath: '/workspace/global',
readonly: true,
});
}
}
// Per-group IPC namespace: each group gets its own IPC directory
const groupIpcDir = path.join(DATA_DIR, 'ipc', group.folder);
mounts.push({
hostPath: groupIpcDir,
containerPath: '/workspace/ipc',
readonly: false,
});
// ...
}
這裡的設計差異非常鮮明:
- Main group:掛載整個專案目錄,有完整讀寫權限——因為它是使用者自己的 self-chat,是 trusted
- Non-main groups:只能看到自己的資料夾和 read-only 的全域記憶——因為群組中可能有其他人,是 untrusted
- IPC 目錄按群組隔離:每個群組有自己的
/workspace/ipc,無法跨群組通訊
這個分層信任模型不需要任何應用層的 if (user.hasPermission(...)) 檢查。Agent 在容器裡想做什麼都行——但它的世界就只有那幾個 mount point。
設計三:Filesystem-based IPC——讓沙箱 Agent 安全地與外界通訊
Container 內的 agent 無法直接存取 host 上的 WhatsApp 連線或 SQLite 資料庫。NanoClaw 設計了一套基於 filesystem 的 IPC 協議:agent 將操作寫成 JSON 檔案到 IPC 目錄,host process 定期掃描並執行。
container/agent-runner/src/ipc-mcp.ts — 容器內的 MCP Server,將 agent 的操作意圖序列化為 JSON 檔案
function writeIpcFile(dir: string, data: object): string {
fs.mkdirSync(dir, { recursive: true });
const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`;
const filepath = path.join(dir, filename);
// Atomic write: temp file then rename
const tempPath = `${filepath}.tmp`;
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2));
fs.renameSync(tempPath, filepath);
return filename;
}
Code language: JavaScript (javascript)而 host 端的 IPC watcher 會驗證每個操作的授權:
src/index.ts — IPC watcher 以群組目錄名稱為身份識別,驗證操作授權
// Authorization: verify this group can send to this chatJid
const targetGroup = registeredGroups[data.chatJid];
if (isMain || (targetGroup && targetGroup.folder === sourceGroup)) {
await sendMessage(data.chatJid, `${ASSISTANT_NAME}: ${data.text}`);
} else {
logger.warn(
{ chatJid: data.chatJid, sourceGroup },
'Unauthorized IPC message attempt blocked',
);
}
Code language: JavaScript (javascript)這個設計的精妙之處在於:群組的身份不由 IPC payload 決定,而由 IPC 目錄路徑決定。因為每個群組的 IPC 目錄是分開 mount 的,agent 無法偽造身份——它只能寫入 /workspace/ipc,而 host 知道這個目錄對應哪個群組。
設計四:Sentinel Markers 解決容器輸出解析問題
Container 的 stdout 裡混合了 agent 的 debug log 和最終結果。NanoClaw 用一對「哨兵標記」來可靠地提取 JSON 輸出:
src/container-runner.ts — 用 sentinel markers 從混雜的 stdout 中精確提取結構化輸出
const OUTPUT_START_MARKER = '---NANOCLAW_OUTPUT_START---';
const OUTPUT_END_MARKER = '---NANOCLAW_OUTPUT_END---';
// Extract JSON between sentinel markers for robust parsing
const startIdx = stdout.indexOf(OUTPUT_START_MARKER);
const endIdx = stdout.indexOf(OUTPUT_END_MARKER);
let jsonLine: string;
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
jsonLine = stdout.slice(startIdx + OUTPUT_START_MARKER.length, endIdx).trim();
} else {
// Fallback: last non-empty line (backwards compatibility)
const lines = stdout.trim().split('\n');
jsonLine = lines[lines.length - 1];
}
const output: ContainerOutput = JSON.parse(jsonLine);
Code language: JavaScript (javascript)這是一個務實的工程決策:與其要求容器內所有 log 走 stderr(很難控制第三方庫的行為),不如在 stdout 中用明確的界線標記來區分「雜訊」和「訊號」。同時保留了 fallback 機制確保向後相容。
設計五:外部 Allowlist 的掛載安全模型
NanoClaw 的 mount security 設計了一個防篡改機制:allowlist 存放在 ~/.config/nanoclaw/mount-allowlist.json——在專案目錄之外,永遠不會被 mount 進任何容器。
src/mount-security.ts — 掛載安全驗證,包含 symlink 解析、blocked patterns 和多層授權邏輯
const DEFAULT_BLOCKED_PATTERNS = [
'.ssh', '.gnupg', '.gpg', '.aws', '.azure', '.gcloud',
'.kube', '.docker', 'credentials', '.env', '.netrc',
'.npmrc', '.pypirc', 'id_rsa', 'id_ed25519',
'private_key', '.secret',
];
Code language: JavaScript (javascript)function findAllowedRoot(realPath: string, allowedRoots: AllowedRoot[]): AllowedRoot | null {
for (const root of allowedRoots) {
const expandedRoot = expandPath(root.path);
const realRoot = getRealPath(expandedRoot);
if (realRoot === null) continue;
// Check if realPath is under realRoot
const relative = path.relative(realRoot, realPath);
if (!relative.startsWith('..') && !path.isAbsolute(relative)) {
return root;
}
}
return null;
}
Code language: JavaScript (javascript)驗證流程有三層防護:
- Blocked patterns:無論設定如何,
.ssh、.env等敏感路徑永遠被阻擋 - Symlink resolution:用
fs.realpathSync()解析真實路徑,防止 symlink traversal attack - Allowed roots:只有在允許的根目錄下的路徑才能被 mount
- Non-main read-only:非主群組的額外掛載強制為 read-only
這個設計的核心原則是:安全設定放在 agent 不可觸及的地方。
設計六:MCP Server 作為 Agent 的能力邊界
容器內的 agent 透過 Claude Agent SDK 的 MCP(Model Context Protocol)機制獲得能力。NanoClaw 用 createSdkMcpServer 定義了一組精心設計的工具:
container/agent-runner/src/ipc-mcp.ts — 定義 agent 可用的 MCP tools,每個 tool 都帶有詳細的使用指引
export function createIpcMcp(ctx: IpcMcpContext) {
return createSdkMcpServer({
name: 'nanoclaw',
version: '1.0.0',
tools: [
tool('send_message', 'Send a message to the current WhatsApp group...', {
text: z.string().describe('The message text to send')
}, async (args) => {
const data = { type: 'message', chatJid, text: args.text, ... };
const filename = writeIpcFile(MESSAGES_DIR, data);
return { content: [{ type: 'text', text: `Message queued for delivery (${filename})` }] };
}),
tool('schedule_task',
`Schedule a recurring or one-time task...
CONTEXT MODE - Choose based on task type:
• "group": Task runs in the group's conversation context...
• "isolated": Task runs in a fresh session...`,
{ prompt: z.string(), schedule_type: z.enum(['cron', 'interval', 'once']), ... },
async (args) => { /* validation + IPC write */ }
),
// list_tasks, pause_task, resume_task, cancel_task, register_group...
]
});
}
Code language: JavaScript (javascript)注意 schedule_task 工具的 description 有多長——它包含了 context mode 的選擇指引、cron 表達式格式說明、時區處理注意事項。這些 description 本質上是寫給 Claude 看的「使用手冊」,直接影響 agent 的行為品質。
而 agent runner 的 allowedTools 設定精確控制了 agent 可用的能力:
container/agent-runner/src/index.ts — Agent 啟動邏輯,配置 Claude Agent SDK 的 query 參數
for await (const message of query({
prompt,
options: {
cwd: '/workspace/group',
resume: input.sessionId,
allowedTools: [
'Bash', 'Read', 'Write', 'Edit', 'Glob', 'Grep',
'WebSearch', 'WebFetch',
'mcp__nanoclaw__*'
],
permissionMode: 'bypassPermissions',
allowDangerouslySkipPermissions: true,
settingSources: ['project'],
mcpServers: { nanoclaw: ipcMcp },
hooks: { PreCompact: [{ hooks: [createPreCompactHook()] }] }
}
})) { ... }
Code language: JavaScript (javascript)bypassPermissions + allowDangerouslySkipPermissions 看起來很危險——但因為 agent 在容器內,Bash 命令只能影響容器環境。這是「Container 隔離取代權限檢查」理念的直接體現。
設計七:PreCompact Hook 實現對話記憶歸檔
NanoClaw 利用 Claude Agent SDK 的 Hook 機制,在對話被壓縮前自動歸檔完整 transcript:
container/agent-runner/src/index.ts — PreCompact Hook 將完整對話歸檔為 Markdown 檔案
function createPreCompactHook(): HookCallback {
return async (input, _toolUseId, _context) => {
const preCompact = input as PreCompactHookInput;
const transcriptPath = preCompact.transcript_path;
if (!transcriptPath || !fs.existsSync(transcriptPath)) return {};
const content = fs.readFileSync(transcriptPath, 'utf-8');
const messages = parseTranscript(content);
const summary = getSessionSummary(sessionId, transcriptPath);
const name = summary ? sanitizeFilename(summary) : generateFallbackName();
const conversationsDir = '/workspace/group/conversations';
fs.mkdirSync(conversationsDir, { recursive: true });
const date = new Date().toISOString().split('T')[0];
const filename = `${date}-${name}.md`;
fs.writeFileSync(filePath, markdown);
return {};
};
}
Code language: JavaScript (javascript)這解決了一個實際問題:Claude 的 context window 有限,長對話會被壓縮摘要。但使用者可能想回顧完整對話內容。PreCompact Hook 在壓縮觸發前將完整對話以 Markdown 格式存檔,未來可被 agent 搜索。
設計八:Per-Group CLAUDE.md 作為 Agent Persona 與記憶
每個群組有自己的 CLAUDE.md,agent 在該群組的容器中以此為 system prompt。這是 NanoClaw 的「記憶」機制:
groups/global/CLAUDE.md — 全域 prompt,定義 agent 基礎人格與行為規範
# Andy
You are Andy, a personal assistant...
## Long Tasks
If a request requires significant work, use `mcp__nanoclaw__send_message` to acknowledge first:
1. Send a brief message: what you understood and what you'll do
2. Do the work
3. Exit with the final answer
## Memory
The `conversations/` folder contains searchable history of past conversations.
When you learn something important:
- Create files for structured data (e.g., `customers.md`, `preferences.md`)
- Add recurring context directly to this CLAUDE.md
Code language: PHP (php)groups/main/CLAUDE.md — 主頻道 prompt,包含管理員特權指引和群組管理操作流程
主群組的 CLAUDE.md 則額外包含管理員操作指引——如何查詢可用群組、如何註冊新群組、如何設定額外的目錄掛載。這些「操作手冊」直接寫在 prompt 裡,agent 就「知道」如何執行管理任務。
這個設計讓 NanoClaw 的「設定檔」就是自然語言。想改變 agent 行為?直接修改 CLAUDE.md。想讓 agent 記住某件事?告訴它「remember this」。
設計九:Skills over Features——以 Skill 檔案取代 Feature Branch
NanoClaw 最大膽的設計決策是:不接受新功能的 PR,只接受 Skill 的 PR。
.claude/skills/customize/SKILL.md — Customize skill,教 Claude Code 如何互動式地修改 NanoClaw 的行為
---
name: customize
description: Add new capabilities or modify NanoClaw behavior...
---
# NanoClaw Customization
## Key Files
| File | Purpose |
|------|---------|
| `src/config.ts` | Assistant name, trigger pattern, directories |
| `src/index.ts` | Message routing, WhatsApp connection, agent invocation |
## Common Customization Patterns
### Adding a New Input Channel (e.g., Telegram, Slack, Email)
Questions to ask:
- Which channel?
- Same trigger word or different?
- Same memory hierarchy or separate?
Implementation pattern:
1. Find/add MCP server for the channel
2. Add connection and message handling in `src/index.ts`
3. Store messages in the database
4. Ensure responses route back to correct channel
Code language: PHP (php)Skill 不是程式碼,而是教 Claude Code 如何修改程式碼的指引。使用者執行 /add-telegram,Claude Code 讀取 Skill 文件,然後直接修改使用者 fork 中的程式碼。最終每個使用者的 codebase 只包含他們真正需要的功能——沒有 Telegram 程式碼殘留在一個只用 WhatsApp 的系統中。
設計十:Credential Filtering 與最小權限暴露
容器需要 Claude API 認證才能執行,但 NanoClaw 不會把整個 .env 給容器:
src/container-runner.ts — 只過濾出 agent 需要的環境變數,以 read-only 方式掛載
const envContent = fs.readFileSync(envFile, 'utf-8');
const allowedVars = ['CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY'];
const filteredLines = envContent.split('\n').filter((line) => {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) return false;
return allowedVars.some((v) => trimmed.startsWith(`${v}=`));
});
if (filteredLines.length > 0) {
fs.writeFileSync(path.join(envDir, 'env'), filteredLines.join('\n') + '\n');
mounts.push({
hostPath: envDir,
containerPath: '/workspace/env-dir',
readonly: true,
});
}
Code language: JavaScript (javascript)注意是 readonly: true——容器不能修改認證資訊。而 Dockerfile 中的 entrypoint 負責從這個目錄讀取環境變數:
container/Dockerfile — 容器映像定義,entrypoint 從 mount 目錄載入環境變數
# Sources env from mounted /workspace/env-dir/env if it exists
# (workaround for Apple Container -i bug)
[ -f /workspace/env-dir/env ] && export $(cat /workspace/env-dir/env | xargs)
Code language: PHP (php)SECURITY.md 坦誠地指出目前的限制:agent 在容器內仍可透過 Bash 讀取這些認證。這種「承認限制並標記為待改進」的態度,比假裝問題不存在更負責任。
Prompt 設計解讀
NanoClaw 的 prompt 設計體現了「分層特權」的理念。全域 CLAUDE.md 定義基礎行為,主群組的 CLAUDE.md 則額外授予管理能力。
groups/main/CLAUDE.md — 主頻道的 prompt 設計,包含結構化的管理操作指引
幾個值得學習的 prompt 設計技巧:
- 明確的能力宣告:prompt 開頭就列出「What You Can Do」,讓 agent 清楚知道自己的能力邊界
- 操作流程寫成步驟:「Adding a Group」分成 6 個明確步驟,避免 agent 遺漏操作
- Fallback 策略:查詢群組時先用 IPC 檔案,如果找不到再查 SQLite——直接把 fallback 邏輯寫進 prompt
- 格式約束:「Do NOT use markdown headings (##) in WhatsApp messages」——避免 agent 使用 WhatsApp 不支援的格式
- 長任務處理:「先用 send_message 回覆確認,再做事,再回覆結果」——避免使用者等待無回應
MCP tool 的 description 同樣是精心設計的 prompt:
tool('schedule_task',
`...CONTEXT MODE - Choose based on task type:
• "group" (recommended for most tasks): Task runs in the group's conversation context...
• "isolated": Task runs in a fresh session...
If unsure which mode to use, ask the user. Examples:
- "Remind me about our discussion" → group (needs conversation context)
- "Check the weather every morning" → isolated (self-contained task)`,
...
)
Code language: JavaScript (javascript)透過具體的 examples 引導 Claude 在模糊場景中做出正確選擇。
設計理念萃取
- Container 隔離優於應用層權限 — 與其在程式碼中寫一堆
if (hasPermission)檢查,不如讓安全邊界在 OS 層面。Agent 在沙箱裡可以bypassPermissions,因為它的世界只有你允許它看到的部分。這個模式適用於任何需要執行不受信任程式碼的場景。 - Filesystem-based IPC 適合跨信任邊界通訊 — 當兩個 process 處於不同信任等級時,用 JSON 檔案作為 IPC 比 socket 更容易審計和控制。原子寫入(temp file + rename)保證了可靠性,而目錄路徑作為身份識別避免了身份偽造。
- Prompt 就是設定檔 — NanoClaw 沒有 YAML 設定、沒有 admin dashboard。行為變更直接寫在 CLAUDE.md 中,用自然語言描述。這在 AI-native 應用中是合理的——你的「使用者」是 LLM,自然語言就是最好的設定語言。
- Skills over Features 是 AI 時代的新擴展模式 — 不把所有功能塞進一個 codebase,而是用 Skill 文件教 AI 如何按需修改程式碼。每個使用者的 fork 只包含他們真正需要的功能,不存在功能膨脹問題。
- 極簡架構的可維護性紅利 — 8 個核心檔案、1500 行程式碼,任何人(或 AI)都能在 8 分鐘內理解整個系統。這種「小到可以理解」的設計哲學,讓 debug、customization 和安全審計都變得可行。
延伸思考
NanoClaw 的設計模式可以延伸到許多場景:
AI Agent 安全沙箱:如果你在構建任何需要執行 AI 生成程式碼的系統,Container 隔離 + mount allowlist 的模式比 application-level sandboxing 更可靠。關鍵是把安全設定放在 agent 不可觸及的地方。
Multi-tenant Agent 系統:per-group 隔離的模式——獨立的 filesystem、session、IPC namespace——可以直接應用到 SaaS 產品中的 multi-tenant AI agent 架構。信任等級不同的 tenant 就給不同的 mount 權限。
AI-native Configuration:如果你的系統主要由 AI 操作,考慮用自然語言文件(如 CLAUDE.md)取代傳統設定檔。這不只是「方便」——LLM 理解自然語言的能力遠超理解 YAML 語法,行為的可預測性反而更高。
Skills 模式:對於任何面向開發者的 CLI 工具或框架,可以考慮用「教 AI 如何修改程式碼」的 Skill 文件來取代 plugin system。使用者得到的是乾淨的、量身定制的程式碼,而不是一堆可能衝突的 plugin。
Vibe Coding:把觀念變成程式碼
以下是你可以直接給 AI 的 prompt 指令,將本文介紹的設計觀念應用到你的專案中:
Container 隔離取代應用層權限檢查
場景:你正在設計一個需要執行不受信任程式碼的系統(AI agent、使用者提交的程式碼、自動化腳本),目前用應用層的 if (hasPermission) 來控制存取權限。
給 AI 的指令:
我的系統需要執行不受信任的程式碼,目前用應用層權限檢查來控制安全。我想改用 NanoClaw 的「Container 隔離作為主要安全邊界」模式——把每次執行放進獨立的 Docker Container,用 volume mount 來控制可見範圍,而不是在程式碼中寫權限判斷。
請幫我設計一個 container-runner 模組,需要:
1. 根據使用者的信任等級組裝不同的 volume mounts(例如:管理員掛載整個專案目錄可讀寫、一般使用者只掛載自己的資料夾)
2. 敏感路徑(.ssh、.env、credentials)無論設定如何都不能被掛載——實作一個 blocked patterns 清單
3. 所有路徑都要做 symlink resolution(fs.realpathSync),防止 symlink traversal attack
4. 環境變數只傳遞白名單中的項目,且以 read-only 方式掛載
我的技術棧是 [你的語言/框架],容器技術用 [Docker/Podman]。
效果:AI 會產出一個完整的 container runner 模組,包含 volume mount 組裝邏輯、blocked patterns 安全檢查、symlink 解析驗證,以及環境變數過濾機制。你的安全邊界會從分散在各處的 if 判斷,變成集中在 OS 層級的隔離。
Filesystem-based IPC 跨信任邊界通訊
場景:你有兩個不同信任等級的 process 需要通訊(例如沙箱中的 agent 需要觸發 host 上的操作),正在考慮用 socket、HTTP API、或 message queue。
給 AI 的指令:
我的系統中有一個在 Container 沙箱內執行的 agent process,它需要請求 host process 執行某些操作(例如發送訊息、排程任務),但不能直接存取 host 的資源。
我想採用 NanoClaw 的「Filesystem-based IPC」模式:agent 將操作意圖序列化為 JSON 檔案寫入共享的 IPC 目錄,host process 定期掃描這個目錄並執行。請幫我實作:
1. IPC 寫入端:用 atomic write(先寫 temp file 再 rename)保證檔案完整性,檔名用 timestamp + random string 確保唯一
2. IPC 讀取端:host 的 watcher 定期掃描目錄,解析 JSON,根據目錄路徑識別來源身份(不信任 payload 中的身份宣告),處理完後刪除或歸檔檔案
3. 授權驗證:host 根據 IPC 檔案所在的目錄路徑(而非檔案內容)判斷請求者身份,確保無法偽造身份
我的技術棧是 [你的語言/框架]。
效果:AI 會產出 IPC 的寫入端和讀取端程式碼,包含原子寫入、目錄掃描、身份驗證邏輯。這種模式比 socket 更容易審計(檔案系統留下完整痕跡),比 HTTP API 更安全(不需要暴露 port)。
Sentinel Markers 解決混合輸出解析
場景:你的系統需要從子 process 的 stdout 中提取結構化輸出,但 stdout 裡混雜了各種 debug log、第三方庫的輸出,讓 JSON 解析經常失敗。
給 AI 的指令:
我的系統會 spawn 子 process 並需要從 stdout 中提取 JSON 結果,但 stdout 裡混合了 debug log 和第三方庫的輸出,無法直接 JSON.parse 整個 stdout。
請幫我實作 NanoClaw 的「Sentinel Markers」模式:
1. 定義一對唯一的標記字串(例如---MY_OUTPUT_START---和---MY_OUTPUT_END---),子 process 在輸出結果前後印出這對標記
2. 父 process 從 stdout 中用 indexOf 找到標記,提取中間的 JSON 內容
3. 加上 fallback 機制:如果找不到標記,嘗試解析最後一行非空行(向後相容)
4. 加上錯誤處理:標記找到但 JSON 解析失敗的情況
請同時給我子 process 端的輸出函式和父 process 端的解析函式。
效果:AI 會產出一對配合使用的函式——子 process 端的 emitResult() 和父 process 端的 parseContainerOutput(),包含 sentinel markers、fallback 邏輯和完整的錯誤處理。
Skills over Features 擴展模式
場景:你在維護一個開源專案或內部工具,想讓使用者能自訂功能,但不希望所有功能都塞進同一個 codebase(造成功能膨脹)。
給 AI 的指令:
我想為我的專案 [專案名稱] 採用 NanoClaw 的「Skills over Features」擴展模式——不直接加功能到 codebase,而是寫 SKILL.md 文件教 AI 如何按需修改使用者 fork 中的程式碼。
請幫我為以下功能寫一個 SKILL.md 檔案:[要新增的功能描述]
SKILL.md 的格式參考:
– YAML frontmatter 包含 name 和 description
– 列出相關的 Key Files 和它們的用途
– 列出互動式問題(AI 應該先問使用者什麼?)
– 寫出具體的 Implementation Pattern(步驟化的修改指引)
– 包含注意事項和常見陷阱
目標是讓使用者執行這個 Skill 後,AI 能根據指引直接修改程式碼,而不是安裝一個 plugin。
效果:AI 會產出一個結構化的 SKILL.md 檔案,包含完整的互動流程和實作步驟。使用者可以把這個 Skill 加入 .claude/skills/ 目錄,讓 Claude Code 根據指引自動化地修改程式碼。
Prompt 作為設定檔的 AI-native 設計
場景:你正在開發一個 AI agent 應用,需要讓不同的使用者/租戶有不同的行為設定,目前用 YAML 或 JSON 設定檔。
給 AI 的指令:
我正在開發一個多租戶的 AI agent 系統,目前每個租戶的行為設定用 JSON 設定檔管理。我想改用 NanoClaw 的「Prompt 就是設定檔」模式——每個租戶有自己的 CLAUDE.md(或類似的 system prompt 文件),用自然語言定義 agent 的行為、能力和限制。
請幫我設計這個 prompt-as-config 架構:
1. 設計 prompt 的分層結構:全域 prompt(所有租戶共享的基礎行為)+ 租戶專屬 prompt(個別客製)
2. 全域 prompt 範本:包含能力宣告、長任務處理流程(先確認再執行再回報)、格式約束、fallback 策略
3. 租戶 prompt 範本:包含該租戶特有的知識、偏好、可用工具清單
4. prompt 載入機制:agent 啟動時按優先順序合併這些 prompt
我的 agent 使用 [Claude API / OpenAI API / 其他]。
效果:AI 會產出一套 prompt 範本和載入機制,讓你用自然語言文件取代 JSON 設定檔。當需要調整 agent 行為時,直接修改 markdown 文件而非程式碼。
延伸閱讀
- NanoClaw GitHub Repository — 專案原始碼與完整文件,包含 SECURITY.md 中對安全模型的坦誠說明
- NanoClaw 官方網站 — 專案的快速入門指南與核心設計理念說明
- Making Claude Code More Secure and Autonomous (Anthropic Engineering Blog) — Anthropic 官方深度解說 Claude Code 的沙箱機制設計,包含 OS 層級隔離的技術細節,與 NanoClaw 的 Container 隔離理念一脈相承
- Extend Claude with Skills (Claude Code Docs) — Claude Code Skills 的官方文件,詳細說明 SKILL.md 的格式規範與進階用法,理解 NanoClaw 的 Skills over Features 模式必讀
- 500 Lines vs. 50 Modules: What NanoClaw Gets Right About AI Agent Architecture — 深度分析 NanoClaw 與 OpenClaw 的架構差異,探討極簡設計在 AI agent 領域的優勢
- How to Sandbox AI Agents in 2026: MicroVMs, gVisor & Isolation Strategies (Northflank) — 全面比較各種 AI agent 沙箱方案(Container、MicroVM、gVisor、OS primitives),幫助你選擇適合自己場景的隔離策略