2026-02-01 17:45:05 +02:00
< p align = "center" >
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
< h1 align = "center" > 🦞 Clawdie< / h1 >
2026-02-01 17:45:05 +02:00
< / p >
2026-01-31 18:54:24 +02:00
2026-02-01 17:45:05 +02:00
< p align = "center" >
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
< strong > Personal AI Assistant on FreeBSD< / strong >
2026-02-01 17:45:05 +02:00
< / p >
2026-02-01 12:47:40 +02:00
Adds Agent Swarms
* feat: streaming container mode, IPC messaging, agent teams support
Major architectural shift from single-shot container runs to long-lived
streaming containers with IPC-based message injection.
- Agent runner: query loop with AsyncIterable prompt to keep stdin open
for agent teams (fixes isSingleUserTurn premature shutdown)
- New standalone stdio MCP server (ipc-mcp-stdio.ts) inheritable by
subagents, with send_message and schedule_task tools
- Streaming output: parse OUTPUT_START/END markers in real-time, send
results to WhatsApp as they arrive
- IPC file-based messaging: host writes to ipc/{group}/input/, agent
polls for follow-up messages without respawning containers
- Per-group settings.json with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
- SDK bumped to 0.2.34 for TeamCreate tool support
- Container idle timeout (30min) with _close sentinel for shutdown
- Orphaned container cleanup on startup
- alwaysRespond flag for groups that skip trigger pattern check
- Uncaught exception/rejection handlers with timestamps in logger
- Combined SDK documentation into single deep dive reference
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove unused ipc-mcp.ts (replaced by ipc-mcp-stdio.ts)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: clarify agent communication model in docs and tool descriptions
- CLAUDE.md (main + global): split communication instructions into
"responding to messages" vs "scheduled tasks" sections
- send_message tool: note that scheduled task output is not sent to user
- Remove structured output (outputFormat) — not needed with current flow
- Regular output is sent to WhatsApp; scheduled task output is only logged
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: ignore dynamic group data while preserving base structure
Only track groups/main/CLAUDE.md and groups/global/CLAUDE.md. All other
group directories and files are ignored to prevent tracking user-specific
session data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve critical bugs in streaming container mode
Bug 1 (scheduled task hang): Task scheduler now passes onOutput callback
with idle timer that writes _close sentinel after IDLE_TIMEOUT, so
containers exit cleanly instead of blocking queue slots for 30 minutes.
Scheduled tasks stay alive for interactive follow-up via IPC.
Bug 2 (timeout disabled): Remove resetTimeout() from stderr handler.
SDK writes debug logs continuously, resetting the timer on every line.
Timeout now only resets on actual output markers in stdout.
Bug 3 (trigger bypass): Piped messages in startMessageLoop now check
trigger pattern for non-main groups. Non-trigger messages accumulate in
DB and are pulled as context via getMessagesSince when a trigger arrives.
Bug 7 (non-atomic IPC writes): GroupQueue.sendMessage uses temp file +
rename for atomic writes, matching ipc-mcp-stdio.ts pattern.
Also: flip isVerbose back to false (debug leftover), add isScheduledTask
to host-side ContainerInput interface.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer not starting + scheduled task groupFolder missing
Two bugs that prevented the scheduled task idle timeout fix from working:
1. onOutput was only called when parsed.result !== null, but session
update markers have result: null. The idle timer never started for
"silent" query completions, leaving containers parked at
waitForIpcMessage until hard timeout.
2. Scheduler's onProcess callback didn't pass groupFolder to
queue.registerProcess, so closeStdin no-oped (groupFolder was null).
The _close sentinel was never written even when the idle timer fired.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: duplicate messages and timestamp rollback in piping path
Two bugs introduced by the trigger context accumulation change:
1. processGroupMessages didn't advance lastAgentTimestamp until after
the container finished. The piping path's getMessagesSince(lastAgent
Timestamp) re-fetched messages already sent as the initial prompt,
causing duplicates.
2. processGroupMessages overwrote lastAgentTimestamp with the original
batch timestamp on completion, rolling back any advancement made by
the piping path while the container was running.
Fix: advance lastAgentTimestamp immediately after building the prompt,
before starting the container. This matches the piping path behavior
and eliminates both the overlap and the rollback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: container idles 30 extra minutes after _close during query
When _close was detected during pollIpcDuringQuery, it was consumed
(deleted) and stream.end() was called. But after runQuery returned,
main() still emitted a session-update marker (resetting the host's idle
timer) and called waitForIpcMessage (which polled forever since _close
was already gone). The container had to wait for a second _close.
Fix: runQuery now returns closedDuringQuery. When true, main() skips
the session-update marker and waitForIpcMessage, exiting immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resume branching, internal tags, and output forwarding
- Fix resume branching: pass resumeSessionAt with last assistant UUID
to anchor each query loop resume to the correct conversation tree
position. Prevents agent responses landing on invisible branches
when agent teams subagents create parallel JSONL entries.
- Add <internal> tag stripping: agent can wrap internal reasoning in
<internal> tags which are logged but not sent to WhatsApp. Prevents
duplicate messages and internal monologue reaching users.
- Forward scheduled task output: scheduled tasks now send result text
to WhatsApp (with <internal> stripping), matching regular message
behavior. No more special-case instructions.
- Update Communication guidance in CLAUDE.md: simplified to "your
output is sent to the user or group" with soft guidance on
<internal> tags and send_message usage.
- Add messaging behavior docs to schedule_task tool: prompts the
scheduling agent to include guidance on whether the task should
always/conditionally/never message the user.
- Mount security: containerPath now optional, defaults to basename
of hostPath.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: cursor rollback on error, flush guard, verbose logging
- Roll back lastAgentTimestamp on container error so retries can
re-process the messages instead of silently losing them.
- Add guard flag to flushOutgoingQueue to prevent duplicate sends
from concurrent flushes during rapid WA reconnects.
- Revert isVerbose from hardcoded false back to env-based check
(LOG_LEVEL=debug|trace).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: orphan container cleanup was silently failing
The startup cleanup used `container ls --format {{.Names}}` which is
Docker Go-template syntax. Apple Container only supports `--format json`
or `--format table`. The command errored with exit code 64, but the
catch block silently swallowed it — orphan containers were never cleaned
up on restart.
Fixed to use `--format json` and parse `configuration.id` from the
JSON output. Also filters by `status: running` and logs a warning on
failure instead of silently catching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Discord badge and community section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer reset on null results and flush queue message loss
- Only reset idle timer on actual results (non-null), not session-update
markers. Prevents containers staying alive 30 extra minutes after the
agent finishes work.
- flushOutgoingQueue now uses shift() instead of splice(0) so unattempted
messages stay in the queue if an unexpected error bails the loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Agent Swarms to README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update Telegram skill for current architecture
Rewrite integration instructions to match the per-group queue/SQLite
architecture: remove onMessage callback pattern (store to DB, let
message loop pick up), fix startSchedulerLoop signature, add
TELEGRAM_ONLY service startup, SQLite registration, data/env/env sync,
@mention-to-trigger translation, and BotFather group privacy docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Telegram skill message chunking, media placeholders, chat discovery
- Split long messages at Telegram's 4096 char limit to prevent silent
send failures
- Store placeholder text for non-text messages (photos, voice, stickers,
etc.) so the agent knows media was sent
- Update getAvailableGroups filter to include tg: chats so the agent can
discover and register Telegram chats via IPC
- Fix removal step numbering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update REQUIREMENTS.md and SPEC.md for SQLite architecture
- Replace all registered_groups.json / sessions.json / router_state.json
references with SQLite equivalents
- Fix CONTAINER_TIMEOUT default (300000 → 1800000)
- Add missing config exports (IDLE_TIMEOUT, MAX_CONCURRENT_CONTAINERS)
- Update folder structure: add missing src files (logger, group-queue,
mount-security), remove non-existent utils.ts, list all skills
- Fix agent-runner entry (ipc-mcp.ts → ipc-mcp-stdio.ts)
- Update startup sequence to reflect per-group queue architecture
- Fix env mounting description (data/env/env, not extracted vars)
- Update troubleshooting to use sqlite3 commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: fix README architecture description, revert SPEC.md env error
- README: update architecture blurb to mention per-group queue, add
group-queue.ts to key files, update file descriptions
- SPEC.md: restore correct credential filtering description (only auth
vars are extracted from .env, not the full file)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 02:50:43 +02:00
< p align = "center" >
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
A lean, secure AI assistant running on FreeBSD 15 with native jail isolation.
Adds Agent Swarms
* feat: streaming container mode, IPC messaging, agent teams support
Major architectural shift from single-shot container runs to long-lived
streaming containers with IPC-based message injection.
- Agent runner: query loop with AsyncIterable prompt to keep stdin open
for agent teams (fixes isSingleUserTurn premature shutdown)
- New standalone stdio MCP server (ipc-mcp-stdio.ts) inheritable by
subagents, with send_message and schedule_task tools
- Streaming output: parse OUTPUT_START/END markers in real-time, send
results to WhatsApp as they arrive
- IPC file-based messaging: host writes to ipc/{group}/input/, agent
polls for follow-up messages without respawning containers
- Per-group settings.json with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
- SDK bumped to 0.2.34 for TeamCreate tool support
- Container idle timeout (30min) with _close sentinel for shutdown
- Orphaned container cleanup on startup
- alwaysRespond flag for groups that skip trigger pattern check
- Uncaught exception/rejection handlers with timestamps in logger
- Combined SDK documentation into single deep dive reference
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove unused ipc-mcp.ts (replaced by ipc-mcp-stdio.ts)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: clarify agent communication model in docs and tool descriptions
- CLAUDE.md (main + global): split communication instructions into
"responding to messages" vs "scheduled tasks" sections
- send_message tool: note that scheduled task output is not sent to user
- Remove structured output (outputFormat) — not needed with current flow
- Regular output is sent to WhatsApp; scheduled task output is only logged
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: ignore dynamic group data while preserving base structure
Only track groups/main/CLAUDE.md and groups/global/CLAUDE.md. All other
group directories and files are ignored to prevent tracking user-specific
session data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve critical bugs in streaming container mode
Bug 1 (scheduled task hang): Task scheduler now passes onOutput callback
with idle timer that writes _close sentinel after IDLE_TIMEOUT, so
containers exit cleanly instead of blocking queue slots for 30 minutes.
Scheduled tasks stay alive for interactive follow-up via IPC.
Bug 2 (timeout disabled): Remove resetTimeout() from stderr handler.
SDK writes debug logs continuously, resetting the timer on every line.
Timeout now only resets on actual output markers in stdout.
Bug 3 (trigger bypass): Piped messages in startMessageLoop now check
trigger pattern for non-main groups. Non-trigger messages accumulate in
DB and are pulled as context via getMessagesSince when a trigger arrives.
Bug 7 (non-atomic IPC writes): GroupQueue.sendMessage uses temp file +
rename for atomic writes, matching ipc-mcp-stdio.ts pattern.
Also: flip isVerbose back to false (debug leftover), add isScheduledTask
to host-side ContainerInput interface.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer not starting + scheduled task groupFolder missing
Two bugs that prevented the scheduled task idle timeout fix from working:
1. onOutput was only called when parsed.result !== null, but session
update markers have result: null. The idle timer never started for
"silent" query completions, leaving containers parked at
waitForIpcMessage until hard timeout.
2. Scheduler's onProcess callback didn't pass groupFolder to
queue.registerProcess, so closeStdin no-oped (groupFolder was null).
The _close sentinel was never written even when the idle timer fired.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: duplicate messages and timestamp rollback in piping path
Two bugs introduced by the trigger context accumulation change:
1. processGroupMessages didn't advance lastAgentTimestamp until after
the container finished. The piping path's getMessagesSince(lastAgent
Timestamp) re-fetched messages already sent as the initial prompt,
causing duplicates.
2. processGroupMessages overwrote lastAgentTimestamp with the original
batch timestamp on completion, rolling back any advancement made by
the piping path while the container was running.
Fix: advance lastAgentTimestamp immediately after building the prompt,
before starting the container. This matches the piping path behavior
and eliminates both the overlap and the rollback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: container idles 30 extra minutes after _close during query
When _close was detected during pollIpcDuringQuery, it was consumed
(deleted) and stream.end() was called. But after runQuery returned,
main() still emitted a session-update marker (resetting the host's idle
timer) and called waitForIpcMessage (which polled forever since _close
was already gone). The container had to wait for a second _close.
Fix: runQuery now returns closedDuringQuery. When true, main() skips
the session-update marker and waitForIpcMessage, exiting immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resume branching, internal tags, and output forwarding
- Fix resume branching: pass resumeSessionAt with last assistant UUID
to anchor each query loop resume to the correct conversation tree
position. Prevents agent responses landing on invisible branches
when agent teams subagents create parallel JSONL entries.
- Add <internal> tag stripping: agent can wrap internal reasoning in
<internal> tags which are logged but not sent to WhatsApp. Prevents
duplicate messages and internal monologue reaching users.
- Forward scheduled task output: scheduled tasks now send result text
to WhatsApp (with <internal> stripping), matching regular message
behavior. No more special-case instructions.
- Update Communication guidance in CLAUDE.md: simplified to "your
output is sent to the user or group" with soft guidance on
<internal> tags and send_message usage.
- Add messaging behavior docs to schedule_task tool: prompts the
scheduling agent to include guidance on whether the task should
always/conditionally/never message the user.
- Mount security: containerPath now optional, defaults to basename
of hostPath.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: cursor rollback on error, flush guard, verbose logging
- Roll back lastAgentTimestamp on container error so retries can
re-process the messages instead of silently losing them.
- Add guard flag to flushOutgoingQueue to prevent duplicate sends
from concurrent flushes during rapid WA reconnects.
- Revert isVerbose from hardcoded false back to env-based check
(LOG_LEVEL=debug|trace).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: orphan container cleanup was silently failing
The startup cleanup used `container ls --format {{.Names}}` which is
Docker Go-template syntax. Apple Container only supports `--format json`
or `--format table`. The command errored with exit code 64, but the
catch block silently swallowed it — orphan containers were never cleaned
up on restart.
Fixed to use `--format json` and parse `configuration.id` from the
JSON output. Also filters by `status: running` and logs a warning on
failure instead of silently catching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Discord badge and community section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer reset on null results and flush queue message loss
- Only reset idle timer on actual results (non-null), not session-update
markers. Prevents containers staying alive 30 extra minutes after the
agent finishes work.
- flushOutgoingQueue now uses shift() instead of splice(0) so unattempted
messages stay in the queue if an unexpected error bails the loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Agent Swarms to README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update Telegram skill for current architecture
Rewrite integration instructions to match the per-group queue/SQLite
architecture: remove onMessage callback pattern (store to DB, let
message loop pick up), fix startSchedulerLoop signature, add
TELEGRAM_ONLY service startup, SQLite registration, data/env/env sync,
@mention-to-trigger translation, and BotFather group privacy docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Telegram skill message chunking, media placeholders, chat discovery
- Split long messages at Telegram's 4096 char limit to prevent silent
send failures
- Store placeholder text for non-text messages (photos, voice, stickers,
etc.) so the agent knows media was sent
- Update getAvailableGroups filter to include tg: chats so the agent can
discover and register Telegram chats via IPC
- Fix removal step numbering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update REQUIREMENTS.md and SPEC.md for SQLite architecture
- Replace all registered_groups.json / sessions.json / router_state.json
references with SQLite equivalents
- Fix CONTAINER_TIMEOUT default (300000 → 1800000)
- Add missing config exports (IDLE_TIMEOUT, MAX_CONCURRENT_CONTAINERS)
- Update folder structure: add missing src files (logger, group-queue,
mount-security), remove non-existent utils.ts, list all skills
- Fix agent-runner entry (ipc-mcp.ts → ipc-mcp-stdio.ts)
- Update startup sequence to reflect per-group queue architecture
- Fix env mounting description (data/env/env, not extracted vars)
- Update troubleshooting to use sqlite3 commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: fix README architecture description, revert SPEC.md env error
- README: update architecture blurb to mention per-group queue, add
group-queue.ts to key files, update file descriptions
- SPEC.md: restore correct credential filtering description (only auth
vars are extracted from .env, not the full file)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 02:50:43 +02:00
< / p >
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
< p align = "center" >
2026-03-10 21:08:08 +00:00
< a href = "https://docs.clawdie.si" > Documentation< / a > •
< a href = "https://clawdie.si" > Website< / a > •
2026-03-16 09:57:30 +00:00
< a href = "https://codeberg.org/Clawdie/Clawdie-AI" > Codeberg< / a >
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
< / p >
2026-02-23 23:37:25 +02:00
2026-03-09 01:02:59 +01:00
< p align = "center" >
< a href = "repo-tokens" > < img src = "repo-tokens/badge.svg" alt = "38.4k tokens, 19% of context window" valign = "middle" > < / a >
2026-03-13 21:33:30 +01:00
< a href = "https://docs.clawdie.si/docs/split-brain.html" > < img src = "https://img.shields.io/badge/built--in%20knowledge-preloaded-2ab7ca" alt = "built-in knowledge preloaded" valign = "middle" > < / a >
2026-03-09 01:02:59 +01:00
< / p >
< p align = "center" >
<!-- token - count --> 38.4k tokens · 19% of context window<!-- /token - count -->
2026-03-13 21:33:30 +01:00
•
built-in knowledge · preloaded
2026-03-09 01:02:59 +01:00
< / p >
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
---
Adds Agent Swarms
* feat: streaming container mode, IPC messaging, agent teams support
Major architectural shift from single-shot container runs to long-lived
streaming containers with IPC-based message injection.
- Agent runner: query loop with AsyncIterable prompt to keep stdin open
for agent teams (fixes isSingleUserTurn premature shutdown)
- New standalone stdio MCP server (ipc-mcp-stdio.ts) inheritable by
subagents, with send_message and schedule_task tools
- Streaming output: parse OUTPUT_START/END markers in real-time, send
results to WhatsApp as they arrive
- IPC file-based messaging: host writes to ipc/{group}/input/, agent
polls for follow-up messages without respawning containers
- Per-group settings.json with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
- SDK bumped to 0.2.34 for TeamCreate tool support
- Container idle timeout (30min) with _close sentinel for shutdown
- Orphaned container cleanup on startup
- alwaysRespond flag for groups that skip trigger pattern check
- Uncaught exception/rejection handlers with timestamps in logger
- Combined SDK documentation into single deep dive reference
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove unused ipc-mcp.ts (replaced by ipc-mcp-stdio.ts)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: clarify agent communication model in docs and tool descriptions
- CLAUDE.md (main + global): split communication instructions into
"responding to messages" vs "scheduled tasks" sections
- send_message tool: note that scheduled task output is not sent to user
- Remove structured output (outputFormat) — not needed with current flow
- Regular output is sent to WhatsApp; scheduled task output is only logged
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: ignore dynamic group data while preserving base structure
Only track groups/main/CLAUDE.md and groups/global/CLAUDE.md. All other
group directories and files are ignored to prevent tracking user-specific
session data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve critical bugs in streaming container mode
Bug 1 (scheduled task hang): Task scheduler now passes onOutput callback
with idle timer that writes _close sentinel after IDLE_TIMEOUT, so
containers exit cleanly instead of blocking queue slots for 30 minutes.
Scheduled tasks stay alive for interactive follow-up via IPC.
Bug 2 (timeout disabled): Remove resetTimeout() from stderr handler.
SDK writes debug logs continuously, resetting the timer on every line.
Timeout now only resets on actual output markers in stdout.
Bug 3 (trigger bypass): Piped messages in startMessageLoop now check
trigger pattern for non-main groups. Non-trigger messages accumulate in
DB and are pulled as context via getMessagesSince when a trigger arrives.
Bug 7 (non-atomic IPC writes): GroupQueue.sendMessage uses temp file +
rename for atomic writes, matching ipc-mcp-stdio.ts pattern.
Also: flip isVerbose back to false (debug leftover), add isScheduledTask
to host-side ContainerInput interface.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer not starting + scheduled task groupFolder missing
Two bugs that prevented the scheduled task idle timeout fix from working:
1. onOutput was only called when parsed.result !== null, but session
update markers have result: null. The idle timer never started for
"silent" query completions, leaving containers parked at
waitForIpcMessage until hard timeout.
2. Scheduler's onProcess callback didn't pass groupFolder to
queue.registerProcess, so closeStdin no-oped (groupFolder was null).
The _close sentinel was never written even when the idle timer fired.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: duplicate messages and timestamp rollback in piping path
Two bugs introduced by the trigger context accumulation change:
1. processGroupMessages didn't advance lastAgentTimestamp until after
the container finished. The piping path's getMessagesSince(lastAgent
Timestamp) re-fetched messages already sent as the initial prompt,
causing duplicates.
2. processGroupMessages overwrote lastAgentTimestamp with the original
batch timestamp on completion, rolling back any advancement made by
the piping path while the container was running.
Fix: advance lastAgentTimestamp immediately after building the prompt,
before starting the container. This matches the piping path behavior
and eliminates both the overlap and the rollback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: container idles 30 extra minutes after _close during query
When _close was detected during pollIpcDuringQuery, it was consumed
(deleted) and stream.end() was called. But after runQuery returned,
main() still emitted a session-update marker (resetting the host's idle
timer) and called waitForIpcMessage (which polled forever since _close
was already gone). The container had to wait for a second _close.
Fix: runQuery now returns closedDuringQuery. When true, main() skips
the session-update marker and waitForIpcMessage, exiting immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resume branching, internal tags, and output forwarding
- Fix resume branching: pass resumeSessionAt with last assistant UUID
to anchor each query loop resume to the correct conversation tree
position. Prevents agent responses landing on invisible branches
when agent teams subagents create parallel JSONL entries.
- Add <internal> tag stripping: agent can wrap internal reasoning in
<internal> tags which are logged but not sent to WhatsApp. Prevents
duplicate messages and internal monologue reaching users.
- Forward scheduled task output: scheduled tasks now send result text
to WhatsApp (with <internal> stripping), matching regular message
behavior. No more special-case instructions.
- Update Communication guidance in CLAUDE.md: simplified to "your
output is sent to the user or group" with soft guidance on
<internal> tags and send_message usage.
- Add messaging behavior docs to schedule_task tool: prompts the
scheduling agent to include guidance on whether the task should
always/conditionally/never message the user.
- Mount security: containerPath now optional, defaults to basename
of hostPath.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: cursor rollback on error, flush guard, verbose logging
- Roll back lastAgentTimestamp on container error so retries can
re-process the messages instead of silently losing them.
- Add guard flag to flushOutgoingQueue to prevent duplicate sends
from concurrent flushes during rapid WA reconnects.
- Revert isVerbose from hardcoded false back to env-based check
(LOG_LEVEL=debug|trace).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: orphan container cleanup was silently failing
The startup cleanup used `container ls --format {{.Names}}` which is
Docker Go-template syntax. Apple Container only supports `--format json`
or `--format table`. The command errored with exit code 64, but the
catch block silently swallowed it — orphan containers were never cleaned
up on restart.
Fixed to use `--format json` and parse `configuration.id` from the
JSON output. Also filters by `status: running` and logs a warning on
failure instead of silently catching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Discord badge and community section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer reset on null results and flush queue message loss
- Only reset idle timer on actual results (non-null), not session-update
markers. Prevents containers staying alive 30 extra minutes after the
agent finishes work.
- flushOutgoingQueue now uses shift() instead of splice(0) so unattempted
messages stay in the queue if an unexpected error bails the loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Agent Swarms to README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update Telegram skill for current architecture
Rewrite integration instructions to match the per-group queue/SQLite
architecture: remove onMessage callback pattern (store to DB, let
message loop pick up), fix startSchedulerLoop signature, add
TELEGRAM_ONLY service startup, SQLite registration, data/env/env sync,
@mention-to-trigger translation, and BotFather group privacy docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Telegram skill message chunking, media placeholders, chat discovery
- Split long messages at Telegram's 4096 char limit to prevent silent
send failures
- Store placeholder text for non-text messages (photos, voice, stickers,
etc.) so the agent knows media was sent
- Update getAvailableGroups filter to include tg: chats so the agent can
discover and register Telegram chats via IPC
- Fix removal step numbering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update REQUIREMENTS.md and SPEC.md for SQLite architecture
- Replace all registered_groups.json / sessions.json / router_state.json
references with SQLite equivalents
- Fix CONTAINER_TIMEOUT default (300000 → 1800000)
- Add missing config exports (IDLE_TIMEOUT, MAX_CONCURRENT_CONTAINERS)
- Update folder structure: add missing src files (logger, group-queue,
mount-security), remove non-existent utils.ts, list all skills
- Fix agent-runner entry (ipc-mcp.ts → ipc-mcp-stdio.ts)
- Update startup sequence to reflect per-group queue architecture
- Fix env mounting description (data/env/env, not extracted vars)
- Update troubleshooting to use sqlite3 commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: fix README architecture description, revert SPEC.md env error
- README: update architecture blurb to mention per-group queue, add
group-queue.ts to key files, update file descriptions
- SPEC.md: restore correct credential filtering description (only auth
vars are extracted from .env, not the full file)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 02:50:43 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Overview
2026-02-01 12:47:40 +02:00
2026-03-14 00:07:42 +01:00
Clawdie is a FreeBSD-first personal AI assistant with a host-side Node.js orchestrator and jailed agent execution. The core repo stays small, Telegram is built in, and additional channels or integrations are added through skills instead of being hard-wired into core.
2026-02-01 12:47:40 +02:00
2026-04-23 00:00:49 +02:00
## V2 Track
The `main` branch stays focused on the current working system. The
`multitenant` branch is the internal V2 track where Clawdie is refactored into
2026-05-07 11:16:40 +02:00
a host platform that can run tenant assistants such as `atlas` or `bob` .
2026-04-23 00:00:49 +02:00
That branch is for architecture work, not a feature race. The goal is to make
ownership, recovery, degraded mode, and FreeBSD-native multitenancy explicit
before any wider public launch.
2026-03-14 14:55:47 +01:00
## Current Release
2026-04-24 22:32:26 +02:00
`v0.10.0` (04.apr.2026)
2026-04-04 12:13:31 +00:00
Domain Defaults Fix
2026-03-14 14:55:47 +01:00
2026-03-16 08:04:54 +00:00
See [Changelog ](html/docs-clawdie-si/changelog.html ) for full release notes.
2026-03-14 14:55:47 +01:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
**Key Features:**
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
- 🏠 **Native FreeBSD** - No Linux emulation, native jail isolation
- 🔒 **Jail Isolation** - Secure OS-level containers with ZFS snapshots
- ⚡ **Better Performance** - Single layer: FreeBSD → Jail → Node.js
2026-03-24 10:10:06 +00:00
- 💾 **ZFS Integration** - Snapshots, quotas, compression, RAIDZ1 support
- 🌐 **Multi-Language Docs** - English, German, French, Spanish (Crowdin-managed)
- 📚 **Zero-Downtime Deployments** - Symlink-based versioning with instant rollback
- 🔄 **Automated Sync** - Daily documentation compilation & deployment @ 05:00 UTC
- 🔧 **Cloud & Baremetal** - ISO variants for VPS (headless) and physical hardware (GUI)
- 🔐 **SSH Keys & Passwords** - Pre-configured or interactive setup options
feat(cnc): rename robot→cnc everywhere, add cnc pi-profile, fix ipc-mcp-stdio
- clawdie-robot → clawdie-cnc (README, html/clawdie/, freebsd-setup.html)
- "Robot OS" → "CNC" throughout (titles, taglines, ecosystem table, section headers)
- src/pi-profile.ts: add 'cnc' as 10th profile — CNC machine operation,
G-code, machine procedures; tools: read-only by default; thinking: high;
safety rules around position confirmation before movement
- PiTuiProfileName union now has 10 members — clean 5×2 grid for installer UI
- jail/agent-runner/src/ipc-mcp-stdio.ts: fix register_group tool —
WhatsApp JID example → Telegram tg:<chat_id> format,
"@Andy" trigger → "@Clawdie",
available_groups.json hint → SQLite messages.db
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:14:05 +00:00
- 🔧 **CNC Ready** - clawdie-cnc for CNC machine control (in development)
2026-02-01 17:53:54 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Why Clawdie?
2026-02-01 17:53:54 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
### Why Jails Instead of Docker?
2026-02-01 17:53:54 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
| Aspect | Docker on FreeBSD | FreeBSD Jails |
| --------------- | ------------------------- | ---------------------- |
| Performance | Good (emulation overhead) | **Excellent (native)** |
| Layers | FreeBSD → Linux → Docker | **FreeBSD → Jail** |
| Security | Good | **Excellent** |
| Networking | Docker bridge | **Native IP** |
| Complexity | High | **Low** |
| ZFS Integration | Manual | **Native** |
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
**Result:** Simpler, faster, more secure.
2026-02-01 12:47:40 +02:00
2026-03-07 21:15:16 +01:00
### Why Clawdie?
2026-02-01 12:47:40 +02:00
2026-03-16 09:57:30 +00:00
[NanoClaw ](https://github.com/qwibitai/nanoclaw ) by Gavriel is the upstream line
2026-03-14 14:55:47 +01:00
we still track, and NanoClaw itself follows the broader
[OpenClaw ](https://github.com/openclaw/openclaw ) direction opened by
[Peter Steinberger ](https://github.com/steipete ). Clawdie takes that line onto
FreeBSD for operators who want:
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
- Native performance without Linux emulation
- ZFS integration for snapshots and quotas
- Simpler architecture (fewer layers)
feat(cnc): rename robot→cnc everywhere, add cnc pi-profile, fix ipc-mcp-stdio
- clawdie-robot → clawdie-cnc (README, html/clawdie/, freebsd-setup.html)
- "Robot OS" → "CNC" throughout (titles, taglines, ecosystem table, section headers)
- src/pi-profile.ts: add 'cnc' as 10th profile — CNC machine operation,
G-code, machine procedures; tools: read-only by default; thinking: high;
safety rules around position confirmation before movement
- PiTuiProfileName union now has 10 members — clean 5×2 grid for installer UI
- jail/agent-runner/src/ipc-mcp-stdio.ts: fix register_group tool —
WhatsApp JID example → Telegram tg:<chat_id> format,
"@Andy" trigger → "@Clawdie",
available_groups.json hint → SQLite messages.db
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:14:05 +00:00
- CNC machine integration for manufacturing
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Architecture
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
```
2026-03-14 00:07:42 +01:00
Telegram + scheduled tasks + IPC
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
↓
docs: update SQLite references to PostgreSQL ops database (Sam & Claude)
Split-brain architecture now spans three PostgreSQL databases:
skills (read-only), memory (dynamic), and ops (operational state).
SQLite is fully removed from the runtime.
Updated: README, public docs site, install guide, internal docs,
agent memory, skill files, backup/restore procedure, debug checklist,
and 6 marketing page translations.
---
Build: pass | Tests: not run (Linux)
2026-04-11 14:56:24 +02:00
PostgreSQL ops database (messages, groups, tasks, sessions)
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
↓
2026-03-14 00:07:42 +01:00
Host orchestrator (Node.js)
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
↓
2026-03-14 00:07:42 +01:00
FreeBSD worker jail(s)
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
↓
2026-03-14 00:07:42 +01:00
Agent response
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
```
2026-02-01 12:47:40 +02:00
2026-05-09 16:48:36 +02:00
**Single Node.js process.** Agents execute in isolated FreeBSD worker jails with filesystem isolation via nullfs mounts. Only mounted directories are accessible. Per-group message queue with concurrency control. PostgreSQL defaults to host runtime (`DB_RUNTIME=host` ) with platform-owned `system_*` databases: built-in skills/reference knowledge, user/agent memory, and operational state. A dedicated db jail remains available when explicitly selected. Ops + memory are required; the built-in skills artifact is committed and can be refreshed with `just refresh-skills-artifact` when docs or skills change.
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
### Key Files
release: v0.7.1 — Control Plane Refactoring
0.7.0 — Privileged Host Daemon + PF Web Edge:
- clawdie-hostd: root daemon on /var/run/clawdie-hostd.sock with whitelisted
Zod-validated op handlers (bastille, zfs, pf, service, pkg, sysrc, sanoid)
- setup/pf.ts: writes /etc/pf.conf with NAT egress + rdr pass 80/443 → cms jail
- src/controlplane.ts: self-healing checks hostd, service jails, PF; repairs via
hostd; process.exit(1) if db jail still down after fix
- setup/hostd.ts: installs rc.d script, sets clawdie_hostd_enable=YES
- setup/service.ts: tmux session with setup window when PI_PROFILE=setup
- Preflight: 15 steps (pf at position 3, hostd at position 12)
- Removed infra/ansible/playbooks/host-nginx.yaml
0.7.1 — Control Plane Refactoring:
- src/infra.ts → src/controlplane.ts (runControlPlaneChecks,
CONTROLPLANE_CHECK_INTERVAL_MS, ControlPlaneReport, ControlPlaneCheckResult)
- Watchdog stores lastControlPlaneReport; exposed as controlplane in IPC status
- doctor now queries watchdog IPC: prints WATCHDOG_* and CONTROLPLANE_* lines
- Docs: README simplified, MONITORING rewritten with watchdog/controlplane
layers, SECURITY updated with hostd in architecture diagram,
HOST-OPERATOR-MODEL gets privilege delegation section, CMS-DEPLOYMENT-PLAN
updated with implementation status
- Skills: nginx fully rewritten to cms-jail model; setup + freebsd-admin updated
- All stale src/infra.ts references eliminated
---
Build: pass | Tests: pass — 414 passed (45 files)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
2026-03-15 08:50:08 +00:00
- `src/index.ts` — orchestrator: state, message loop, agent invocation
- `src/hostd/` — privileged host daemon (types, ops, daemon, client)
- `src/controlplane.ts` — self-healing: checks hostd, service jails, PF; repairs via hostd
- `src/watchdog.ts` — memory throttle, run mode, control plane timer
- `src/channels/telegram.ts` — built-in Telegram channel
- `src/group-queue.ts` — per-group queue with global concurrency limit
2026-04-03 09:36:40 +00:00
- `src/agent-runner.ts` — spawns jailed agent processes
- `src/mount-security.ts` — mount allowlist enforcement
release: v0.7.1 — Control Plane Refactoring
0.7.0 — Privileged Host Daemon + PF Web Edge:
- clawdie-hostd: root daemon on /var/run/clawdie-hostd.sock with whitelisted
Zod-validated op handlers (bastille, zfs, pf, service, pkg, sysrc, sanoid)
- setup/pf.ts: writes /etc/pf.conf with NAT egress + rdr pass 80/443 → cms jail
- src/controlplane.ts: self-healing checks hostd, service jails, PF; repairs via
hostd; process.exit(1) if db jail still down after fix
- setup/hostd.ts: installs rc.d script, sets clawdie_hostd_enable=YES
- setup/service.ts: tmux session with setup window when PI_PROFILE=setup
- Preflight: 15 steps (pf at position 3, hostd at position 12)
- Removed infra/ansible/playbooks/host-nginx.yaml
0.7.1 — Control Plane Refactoring:
- src/infra.ts → src/controlplane.ts (runControlPlaneChecks,
CONTROLPLANE_CHECK_INTERVAL_MS, ControlPlaneReport, ControlPlaneCheckResult)
- Watchdog stores lastControlPlaneReport; exposed as controlplane in IPC status
- doctor now queries watchdog IPC: prints WATCHDOG_* and CONTROLPLANE_* lines
- Docs: README simplified, MONITORING rewritten with watchdog/controlplane
layers, SECURITY updated with hostd in architecture diagram,
HOST-OPERATOR-MODEL gets privilege delegation section, CMS-DEPLOYMENT-PLAN
updated with implementation status
- Skills: nginx fully rewritten to cms-jail model; setup + freebsd-admin updated
- All stale src/infra.ts references eliminated
---
Build: pass | Tests: pass — 414 passed (45 files)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
2026-03-15 08:50:08 +00:00
- `src/task-scheduler.ts` — scheduled tasks
docs: update SQLite references to PostgreSQL ops database (Sam & Claude)
Split-brain architecture now spans three PostgreSQL databases:
skills (read-only), memory (dynamic), and ops (operational state).
SQLite is fully removed from the runtime.
Updated: README, public docs site, install guide, internal docs,
agent memory, skill files, backup/restore procedure, debug checklist,
and 6 marketing page translations.
---
Build: pass | Tests: not run (Linux)
2026-04-11 14:56:24 +02:00
- `src/db.ts` — PostgreSQL ops (messages, groups, sessions, state, routing)
release: v0.7.1 — Control Plane Refactoring
0.7.0 — Privileged Host Daemon + PF Web Edge:
- clawdie-hostd: root daemon on /var/run/clawdie-hostd.sock with whitelisted
Zod-validated op handlers (bastille, zfs, pf, service, pkg, sysrc, sanoid)
- setup/pf.ts: writes /etc/pf.conf with NAT egress + rdr pass 80/443 → cms jail
- src/controlplane.ts: self-healing checks hostd, service jails, PF; repairs via
hostd; process.exit(1) if db jail still down after fix
- setup/hostd.ts: installs rc.d script, sets clawdie_hostd_enable=YES
- setup/service.ts: tmux session with setup window when PI_PROFILE=setup
- Preflight: 15 steps (pf at position 3, hostd at position 12)
- Removed infra/ansible/playbooks/host-nginx.yaml
0.7.1 — Control Plane Refactoring:
- src/infra.ts → src/controlplane.ts (runControlPlaneChecks,
CONTROLPLANE_CHECK_INTERVAL_MS, ControlPlaneReport, ControlPlaneCheckResult)
- Watchdog stores lastControlPlaneReport; exposed as controlplane in IPC status
- doctor now queries watchdog IPC: prints WATCHDOG_* and CONTROLPLANE_* lines
- Docs: README simplified, MONITORING rewritten with watchdog/controlplane
layers, SECURITY updated with hostd in architecture diagram,
HOST-OPERATOR-MODEL gets privilege delegation section, CMS-DEPLOYMENT-PLAN
updated with implementation status
- Skills: nginx fully rewritten to cms-jail model; setup + freebsd-admin updated
- All stale src/infra.ts references eliminated
---
Build: pass | Tests: pass — 414 passed (45 files)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
2026-03-15 08:50:08 +00:00
- `setup/*.ts` — modular setup entrypoints
docs: comprehensive doc audit — update 16 files for consistency with codebase
Systematic review of all doc/, docs/internal/, docs/public/, ARCHITECTURE.md,
and README.md against recent codebase changes. 16 files updated:
Cross-cutting fixes (multiple files):
- Model references: anthropic/claude-3-5-sonnet → zai/glm-5-turbo (4 files)
- Port references: hardcoded 3100 → CONTROLPLANE_API_PORT (3 files)
- Skills mechanism: --no-skills + --append-system-prompt + skills_search (6 files)
- CONTROLPLANE_SHARED_SECRET: documented in security, architecture, install (5 files)
- Prompt guardrails: AGENT_MAX_INBOUND_CHARS etc. added to 3 files
- controlplane is NOT a jail — runs on host (3 files corrected)
- git jail added to layouts and IP tables (3 files)
- npm run → just (2 files)
Specific fixes:
- .env.example: AGENT_SESSION_MAX_BYTES session rollover hint
- README.md: fix IP layout (git=.6 not .4), add run-*.sh generation note
- ARCHITECTURE.md: add config vars, recipe count update, --no-skills
- doc/CONTROLPLANE-AGENT-ROLES.md: fix model, remove deleted file ref
- doc/CONTROLPLANE-ARCHITECTURE.md: port params, security, guardrails section
- doc/CONTROLPLANE-MESSAGE-CONTRACT.md: auth header, skills catalog rewrite
- doc/SESSION-HANDOFF-2026-04-18.md: fix Telegram (plain text not Markdown)
- doc/THREE-BIRD-ARCHITECTURE.md: fix 5 broken STRAPI-FREEBSD-GOTCHA refs
- doc/HANDOFF-PHASE7.md: mark sysprompt cleanup as done
- docs/internal/DOCUMENTATION.md: just CLI, tracked hooks, parameterized paths
- docs/internal/HEARTBEAT.md: add controlplane heartbeat reference, fix setup step
- docs/public/architecture/controlplane.md: phases 2-7 all ✅ DONE
- docs/public/architecture/freebsd-jail-implementation.md: git jail, Forgejo
- docs/public/architecture/warden.md: controlplane=host, git jail added
- docs/public/operate/monitoring.md: just doctor, all guardrail vars
- docs/public/operate/security.md: API auth, shell injection, guardrails
Build: pass | Tests: not run (Linux) (Sam & Claude)
2026-04-18 22:15:50 +02:00
- `setup/service.ts` — generates `run-*.sh` wrappers at install time (not tracked in git)
release: v0.7.1 — Control Plane Refactoring
0.7.0 — Privileged Host Daemon + PF Web Edge:
- clawdie-hostd: root daemon on /var/run/clawdie-hostd.sock with whitelisted
Zod-validated op handlers (bastille, zfs, pf, service, pkg, sysrc, sanoid)
- setup/pf.ts: writes /etc/pf.conf with NAT egress + rdr pass 80/443 → cms jail
- src/controlplane.ts: self-healing checks hostd, service jails, PF; repairs via
hostd; process.exit(1) if db jail still down after fix
- setup/hostd.ts: installs rc.d script, sets clawdie_hostd_enable=YES
- setup/service.ts: tmux session with setup window when PI_PROFILE=setup
- Preflight: 15 steps (pf at position 3, hostd at position 12)
- Removed infra/ansible/playbooks/host-nginx.yaml
0.7.1 — Control Plane Refactoring:
- src/infra.ts → src/controlplane.ts (runControlPlaneChecks,
CONTROLPLANE_CHECK_INTERVAL_MS, ControlPlaneReport, ControlPlaneCheckResult)
- Watchdog stores lastControlPlaneReport; exposed as controlplane in IPC status
- doctor now queries watchdog IPC: prints WATCHDOG_* and CONTROLPLANE_* lines
- Docs: README simplified, MONITORING rewritten with watchdog/controlplane
layers, SECURITY updated with hostd in architecture diagram,
HOST-OPERATOR-MODEL gets privilege delegation section, CMS-DEPLOYMENT-PLAN
updated with implementation status
- Skills: nginx fully rewritten to cms-jail model; setup + freebsd-admin updated
- All stale src/infra.ts references eliminated
---
Build: pass | Tests: pass — 414 passed (45 files)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
2026-03-15 08:50:08 +00:00
- `groups/*/AGENTS.md` — per-group memory
2026-02-01 12:47:40 +02:00
2026-05-12 21:16:17 +02:00
A `justfile` provides discoverable command shortcuts. Run `just` (or `just --list` ) to see all recipes. Prefer `just` for interactive work; `npm run <name>` remains for CI and scripting. The full installer is intentionally exposed as `just install` / `npm run install:clawdie` instead of the npm lifecycle name `install` .
2026-04-12 16:38:52 +00:00
Common mappings:
```
2026-05-12 21:16:17 +02:00
just install # npm run install:clawdie
just install-from-db # npm run install:clawdie -- --from db
2026-04-12 16:38:52 +00:00
just setup-db # npm run setup -- --step db
just setup-cms # npm run setup -- --step cms
```
2026-04-12 10:09:20 +02:00
2026-02-02 01:39:37 +02:00
## What It Supports
2026-02-01 12:47:40 +02:00
2026-03-14 00:07:42 +01:00
- **Telegram-first core** - Built-in Telegram channel plus headless/background operation.
2026-03-07 22:25:03 +01:00
- **Isolated group context** - Each group has its own `AGENTS.md` memory, isolated filesystem, and runs in its own jail sandbox with only that filesystem mounted.
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
- **Main channel** - Your private channel (self-chat) for admin control; every group is completely isolated.
- **Scheduled tasks** - Recurring jobs that run the AI agent and can message you back.
- **Jail isolation** - Agents are sandboxed in FreeBSD jails with ZFS snapshots.
2026-06-13 14:01:50 +02:00
- **Layered Memory Fabric** - PostgreSQL stores three platform-owned planes by default: `system_skills` for reviewed skills/reference knowledge, `system_brain` for user/agent memory, and `system_ops` for messages, tasks, sessions, routing, and runtime state. See [`docs/public/architecture/layered-memory-fabric.md` ](docs/public/architecture/layered-memory-fabric.md ).
2026-03-14 14:55:47 +01:00
- **Built-in payments, optional extras** - Stripe ships in core and is ready when configured; other channels and integrations can still be layered through skills.
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Installation
### Prerequisites
2026-05-10 16:31:40 +02:00
- FreeBSD 15.x
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
- ZFS root installation
- Root access or sudo
2026-03-14 14:55:47 +01:00
- Internet access for `pkg` and `npm`
- `bash` and `git` available before first run
2026-04-16 18:42:50 +02:00
- **`just` ** — command runner (`pkg install just` on FreeBSD; preinstalled on Clawdie ISO)
2026-04-12 08:26:20 +02:00
- **At least one agent CLI on `PATH` **: one of `pi` , `aider` , `claude` , `codex` , or `gemini` . The controlplane harness uses Aider+Pi as the primary driver. Onboarding fails fast if none are present (see [`doc/AGENT-CLI-VALIDATION.md` ](doc/AGENT-CLI-VALIDATION.md ) for the validated install paths). The Clawdie ISO ships claude/gemini/pi via the npm-globals bundle, aider via `py311-aider_chat` pkg, and codex via `pkg install codex` .
2026-03-14 14:55:47 +01:00
Recommended explicit host baseline before first run:
```sh
2026-05-05 16:57:14 +02:00
sudo pkg install -y bash git bastille node24 npm tmux btop python311 uv ripgrep fd-find rsync postgresql18-client py311-pillow dejavu py311-aider_chat edk2-bhyve just
2026-03-14 14:55:47 +01:00
```
2026-03-17 12:30:27 +00:00
The `edk2-bhyve` package provides UEFI firmware required for optional browser-vm support
(FEATURE_BHYVE_GUI=YES in .env).
2026-05-10 19:16:09 +02:00
On FreeBSD, use `fd-find` . It provides the `fd` command that `pi` expects and
avoids colliding with the unrelated `fd` file manager package.
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
2026-03-14 15:26:46 +01:00
The host baseline also includes `py311-pillow` and `dejavu` so tmux screenshot
capture works without a separate `uv pip install Pillow` step.
2026-03-14 15:57:06 +01:00
If the host still has both Python 3.11 and 3.12 installed, pin `uv` to 3.11
explicitly until the generic `python3` path is cleaned up:
```sh
uv venv --python 3.11
uv run --python 3.11 < command >
```
2026-05-05 16:02:29 +02:00
### Operator Glasspane
The local operator cockpit lives in [`scripts/glass.sh` ](scripts/glass.sh ).
On a root/platform install it uses the tmux session name `glasspane` . On a
tenant install it uses `<tenant>-glasspane` .
```sh
# create and attach
sh scripts/glass.sh
# create without attaching (safe smoke test)
GLASS_ATTACH=0 sh scripts/glass.sh
# remove the glasspane session
sh scripts/glass.sh kill
```
On FreeBSD, keep `fd-find` installed. It provides the `fd` command that `pi`
expects inside the glasspane session.
2026-05-05 18:24:19 +02:00
First use:
- Start it with `sh scripts/glass.sh` .
- Window `0` (`glass` ) contains `pi` on the left and `aider` on the right.
- Window `1` contains `btop` .
- Switch windows with `Ctrl-b 0` and `Ctrl-b 1` .
- Move between panes with `Ctrl-b` then an arrow key.
- Detach without killing the session with `Ctrl-b d` .
- Reattach later with `tmux attach -t glasspane` .
- Stop the session with `sh scripts/glass.sh kill` .
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
### Quick Start
```bash
2026-03-14 14:55:47 +01:00
# 1. Install the recommended FreeBSD host baseline
2026-05-05 16:57:14 +02:00
sudo pkg install -y bash git bastille node24 npm tmux btop python311 uv ripgrep fd-find rsync postgresql18-client py311-pillow dejavu py311-aider_chat just
2026-03-14 14:55:47 +01:00
# 2. Clone the repository
2026-03-08 20:11:24 +01:00
git clone https://codeberg.org/Clawdie/Clawdie-AI.git /home/clawdie/clawdie-ai
cd /home/clawdie/clawdie-ai
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
2026-05-07 12:20:01 +02:00
# 3. Bootstrap repo dependencies and hooks
2026-03-14 00:07:42 +01:00
./setup.sh
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
2026-04-08 09:38:23 +00:00
# 4. Ensure at least one agent CLI is on PATH (onboarding gates on this).
2026-05-07 12:20:01 +02:00
# Pick whichever you use; the ISO bundle installs all supported CLIs offline.
2026-05-09 12:35:22 +02:00
pi --version >/dev/null 2>& 1 || npm install -g @earendil -works/pi-coding-agent
2026-04-08 09:38:23 +00:00
# Optional alternates:
# npm install -g @anthropic-ai/claude-code # claude
# npm install -g @google/gemini-cli # gemini
# sudo pkg install -y codex # codex (FreeBSD pkg)
2026-03-14 14:55:47 +01:00
2026-05-07 12:20:01 +02:00
# 5. Run the canonical install orchestrator
just install
2026-03-07 21:15:16 +01:00
2026-05-07 12:20:01 +02:00
# 6. If a step fails, fix the cause and resume from that step
just install-from-db
2026-03-14 00:07:42 +01:00
2026-05-07 12:20:01 +02:00
# 7. Validate the result
just doctor
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
```
2026-05-05 15:34:45 +02:00
If the host still has the old `fd` file manager package installed, `pkg` will
replace it with `fd-find` . That replacement is the intended FreeBSD baseline.
2026-03-14 14:55:47 +01:00
2026-05-07 12:20:01 +02:00
`just install` is the supported full path. The lower-level `setup/index.ts` steps remain available for debugging and targeted recovery, but new installs should prefer the orchestrator so checkpoints and resume behavior stay consistent.
2026-01-31 18:54:24 +02:00
2026-03-14 20:50:05 +01:00
### PI Profiles
2026-05-10 19:16:09 +02:00
`pi-tui` uses a single `PI_TUI_PROFILE` selector for common runtime scenarios:
2026-03-14 20:50:05 +01:00
- `setup` — onboarding and exact setup actions
- `operator` — normal daily runtime
- `status` — read-only health/status summaries
- `payments` — Stripe-safe support flow
- `docs` — docs and release copy
- `cms` — Astro/Strapi publishing work
- `git` — local git mirror and upstream sync
2026-06-13 14:01:50 +02:00
- `memory` — Layered Memory Fabric and PostgreSQL memory work
2026-03-14 20:50:05 +01:00
- `local` — Ollama/offline fallback
2026-03-14 20:27:42 +00:00
- `cnc` — CNC machine operation and G-code work
2026-03-14 20:50:05 +01:00
Check the resolved profile state with:
```sh
2026-04-12 16:38:52 +00:00
just setup -- --step pi-config
2026-03-14 20:50:05 +01:00
```
2026-05-07 16:58:37 +02:00
`pi-config` validates the active provider through Pi auth in
`~/.pi/agent/auth.json` , provider env vars in `.env` , or `OLLAMA_HOST`
for local Ollama.
2026-03-14 20:50:05 +01:00
List all built-in profiles with:
```sh
2026-04-12 16:38:52 +00:00
just setup -- --step pi-config --list-profiles
2026-03-14 20:50:05 +01:00
```
2026-06-13 14:01:50 +02:00
The Layered Memory Fabric database path is mandatory. Setup generates or preserves the
2026-05-10 19:16:09 +02:00
PostgreSQL and Strapi secrets in `.env` , then keeps `SKILLS_DB_URL` ,
`MEMORY_DB_URL` , and `OPS_DB_URL` aligned with `AGENT_NAME` , subnet, and
passwords. The `db` step applies three distinct schema tracks:
2026-03-14 17:59:20 +01:00
- built-in knowledge tables in the skills DB
- dynamic hybrid-memory tables in the user/agent memory DB
docs: update SQLite references to PostgreSQL ops database (Sam & Claude)
Split-brain architecture now spans three PostgreSQL databases:
skills (read-only), memory (dynamic), and ops (operational state).
SQLite is fully removed from the runtime.
Updated: README, public docs site, install guide, internal docs,
agent memory, skill files, backup/restore procedure, debug checklist,
and 6 marketing page translations.
---
Build: pass | Tests: not run (Linux)
2026-04-11 14:56:24 +02:00
- operational state tables in the ops DB (messages, tasks, sessions, routing)
2026-03-14 17:59:20 +01:00
The `db` step also imports the shipped built-in knowledge artifact by default.
2026-05-09 16:48:36 +02:00
`skills-memory --import` remains available as a manual re-import path. Maintainers refresh the committed artifact with `just refresh-skills-artifact` ; the wrapper detects docs/skills/identity changes and checks OpenRouter budget before regenerating embeddings.
2026-05-10 19:16:09 +02:00
At runtime, the host queries the local skills DB before each jail run and
2026-03-14 18:03:37 +01:00
prepends the top built-in references to the prompt when relevant.
2026-03-14 17:59:20 +01:00
The active mandatory pieces are:
2026-03-14 14:55:47 +01:00
- `POSTGRES_ADMIN_PASSWORD`
- `SKILLS_DB_PASSWORD`
- `MEMORY_DB_PASSWORD`
docs: update SQLite references to PostgreSQL ops database (Sam & Claude)
Split-brain architecture now spans three PostgreSQL databases:
skills (read-only), memory (dynamic), and ops (operational state).
SQLite is fully removed from the runtime.
Updated: README, public docs site, install guide, internal docs,
agent memory, skill files, backup/restore procedure, debug checklist,
and 6 marketing page translations.
---
Build: pass | Tests: not run (Linux)
2026-04-11 14:56:24 +02:00
- `OPS_DB_PASSWORD`
docs: comprehensive doc audit — update 16 files for consistency with codebase
Systematic review of all doc/, docs/internal/, docs/public/, ARCHITECTURE.md,
and README.md against recent codebase changes. 16 files updated:
Cross-cutting fixes (multiple files):
- Model references: anthropic/claude-3-5-sonnet → zai/glm-5-turbo (4 files)
- Port references: hardcoded 3100 → CONTROLPLANE_API_PORT (3 files)
- Skills mechanism: --no-skills + --append-system-prompt + skills_search (6 files)
- CONTROLPLANE_SHARED_SECRET: documented in security, architecture, install (5 files)
- Prompt guardrails: AGENT_MAX_INBOUND_CHARS etc. added to 3 files
- controlplane is NOT a jail — runs on host (3 files corrected)
- git jail added to layouts and IP tables (3 files)
- npm run → just (2 files)
Specific fixes:
- .env.example: AGENT_SESSION_MAX_BYTES session rollover hint
- README.md: fix IP layout (git=.6 not .4), add run-*.sh generation note
- ARCHITECTURE.md: add config vars, recipe count update, --no-skills
- doc/CONTROLPLANE-AGENT-ROLES.md: fix model, remove deleted file ref
- doc/CONTROLPLANE-ARCHITECTURE.md: port params, security, guardrails section
- doc/CONTROLPLANE-MESSAGE-CONTRACT.md: auth header, skills catalog rewrite
- doc/SESSION-HANDOFF-2026-04-18.md: fix Telegram (plain text not Markdown)
- doc/THREE-BIRD-ARCHITECTURE.md: fix 5 broken STRAPI-FREEBSD-GOTCHA refs
- doc/HANDOFF-PHASE7.md: mark sysprompt cleanup as done
- docs/internal/DOCUMENTATION.md: just CLI, tracked hooks, parameterized paths
- docs/internal/HEARTBEAT.md: add controlplane heartbeat reference, fix setup step
- docs/public/architecture/controlplane.md: phases 2-7 all ✅ DONE
- docs/public/architecture/freebsd-jail-implementation.md: git jail, Forgejo
- docs/public/architecture/warden.md: controlplane=host, git jail added
- docs/public/operate/monitoring.md: just doctor, all guardrail vars
- docs/public/operate/security.md: API auth, shell injection, guardrails
Build: pass | Tests: not run (Linux) (Sam & Claude)
2026-04-18 22:15:50 +02:00
- `CONTROLPLANE_SHARED_SECRET`
2026-03-14 14:55:47 +01:00
2026-05-07 12:20:01 +02:00
For PostgreSQL identifiers, the root install uses the shared platform namespace
`system` , independent of `ASSISTANT_NAME` or `AGENT_NAME` . Platform databases
use `system_skills` , `system_brain` , `system_ops` , `system_git` , and
`system_web` . Later additive tenants get their own `<tenant>_*` databases.
2026-03-14 14:55:47 +01:00
2026-05-10 19:16:09 +02:00
`STRAPI_DB_PASSWORD` and the `STRAPI_*` app secrets feed the default internal
Strapi bootstrap inside the `cms` jail. They are generated
2026-03-14 18:39:50 +01:00
automatically if missing and should stay private to the CMS layer.
2026-03-14 14:55:47 +01:00
2026-05-02 18:04:09 +02:00
`npm run preflight-check` writes a full host validation bundle into
`tmp/preflight/<stamp>/` , including `summary.json` and `summary.env` for
2026-05-10 19:16:09 +02:00
the on-host agent. It includes `telegram-auth` in the default sequence;
`groups` and `register` remain post-deployment follow-up work
2026-03-14 23:04:03 +01:00
and no longer block base install verification on a fresh host.
2026-03-14 22:51:55 +01:00
2026-05-10 19:16:09 +02:00
Clawdie provisions local code hosting by default through the dedicated `git`
jail. The default mode is:
2026-03-14 17:41:41 +01:00
- `CODE_HOSTING_MODE=git`
- `FEATURE_GIT=YES`
2026-05-07 15:47:25 +02:00
- `WARDEN_GIT_IP=<subnet>.2`
2026-03-14 17:41:41 +01:00
2026-05-07 15:47:25 +02:00
The `git` step creates the shared `git` jail by default (`GIT_JAIL_NAME` can
override it), installs the git jail baseline, creates `/srv/git` , and mirrors
the current repository into a bare repository.
2026-03-14 17:41:41 +01:00
2026-03-14 19:45:15 +01:00
### Default IP Layout
2026-05-07 15:47:25 +02:00
The repo registry/default examples use `10.0.1.x` ; live installs can override
this through `.env` with another private `/24` such as `192.168.72.x` . For a
running system, live jail state and `.env` are authoritative; this table is the
provisioning/default slot map from `infra/jails.yaml` :
2026-03-14 19:45:15 +01:00
- `.1` gateway on `warden0`
2026-05-07 15:47:25 +02:00
- `.2` `git` / Git Service
- `.3` `cms` / Web Service
- `.4` Local AI Models (`ollama` or `llama.cpp` , if enabled)
- `.5` optional `db` / Data Service when `DB_RUNTIME=jail`
2026-05-11 14:53:12 +02:00
- `.6` `browser` / Browser Execution Template
2026-03-14 19:45:15 +01:00
- `.101+` workers
2026-05-07 15:47:25 +02:00
- `.211` DB admin worker
- `.212` Git admin worker
- `.213` coordinator worker
2026-05-11 14:53:12 +02:00
- `.150+` ephemeral browser task clones
2026-03-14 19:45:15 +01:00
This keeps foundational services low in the range while leaving room for
multiple workers and avoiding overlap with host-facing web services. The CMS
stack stays on the private jail network instead of assuming control of host
nginx, which is the main reason the low fixed service slots matter.
2026-03-14 14:55:47 +01:00
### Naming and Local DNS
Current `main` separates public and internal naming:
- `AGENT_DOMAIN` is the public-facing site/API domain
- `AGENT_INTERNAL_DOMAIN` is the internal jail/service zone written into `/etc/hosts`
2026-05-10 18:49:08 +02:00
Fresh installs should keep public and internal names separate:
2026-03-14 14:55:47 +01:00
2026-05-10 18:49:08 +02:00
- `AGENT_DOMAIN=` until you have a real public DNS name configured
- `AGENT_INTERNAL_DOMAIN=<agent>.home.arpa` for local jail/service names
2026-03-14 14:55:47 +01:00
Why this changed:
- `.local` is reserved for mDNS and is a bad default for private service naming
- `home.arpa` is the safer standards-based internal namespace
- keeping public and internal names separate avoids accidentally treating a
non-public jail hostname as if it were externally routable
2026-03-08 20:11:24 +01:00
## FreeBSD Milestone
2026-03-08 21:15:44 +00:00
< p align = "center" >
2026-04-05 06:29:19 +00:00
< img src = "docs/internal/tmux-screenshot-sample.png" alt = "tmux diagnostic screenshot captured by Clawdie" width = "720" >
2026-03-08 21:15:44 +00:00
< br >
2026-05-10 07:58:27 +02:00
< em > Example tmux screenshot generated by Clawdie and sent as a Telegram photo< / em >
2026-03-08 21:15:44 +00:00
< / p >
2026-05-07 12:20:01 +02:00
Current runtime centers on:
2026-03-08 20:11:24 +01:00
2026-03-14 00:07:42 +01:00
- host-side orchestration in `src/index.ts`
2026-05-07 12:20:01 +02:00
- service-owned shared infrastructure (`clawdie` service, `system_*` platform resources)
- Bastille worker jails from `src/jail-config.ts`
- `just install` as the canonical install orchestrator
- mandatory DB bootstrap with built-in knowledge import when the artifact is present
2026-03-14 14:55:47 +01:00
2026-05-07 12:20:01 +02:00
### Simple Install Flow
2026-03-14 14:55:47 +01:00
```text
./setup.sh
2026-05-07 12:20:01 +02:00
-> bootstrap repo dependencies and hooks
just install
-> read first-boot setup seed or run onboarding fallback
-> configure environment, pi, PF, jails, services, hostd
-> provision Data Service, Git Service, Web Service when enabled
-> verify install and report warnings
2026-03-14 14:55:47 +01:00
```
2026-05-07 12:20:01 +02:00
`ASSISTANT_NAME` is display-only. The root install remains the shared platform:
service name `clawdie` , platform namespace `system` , and no root `TENANT_ID` .
2026-03-14 19:45:15 +01:00
`groups` and `register` remain explicit follow-up steps after auth/state are
present; they are not part of the minimal first-boot path.
2026-03-14 14:55:47 +01:00
### Stripe Flow
```text
onboarding
-> configure Stripe now? (or skip)
-> write STRIPE_SECRET_KEY into .env
2026-04-03 09:36:40 +00:00
host agent-runner
2026-03-14 14:55:47 +01:00
-> reads STRIPE_SECRET_KEY from .env
-> passes it to jailed runtime in stdin JSON secrets payload
jailed agent runner
-> merges secret into SDK env only
-> registers Stripe MCP tools
agent chat
-> can use payment, customer, invoice, and subscription tools
```
release: v0.7.1 — Control Plane Refactoring
0.7.0 — Privileged Host Daemon + PF Web Edge:
- clawdie-hostd: root daemon on /var/run/clawdie-hostd.sock with whitelisted
Zod-validated op handlers (bastille, zfs, pf, service, pkg, sysrc, sanoid)
- setup/pf.ts: writes /etc/pf.conf with NAT egress + rdr pass 80/443 → cms jail
- src/controlplane.ts: self-healing checks hostd, service jails, PF; repairs via
hostd; process.exit(1) if db jail still down after fix
- setup/hostd.ts: installs rc.d script, sets clawdie_hostd_enable=YES
- setup/service.ts: tmux session with setup window when PI_PROFILE=setup
- Preflight: 15 steps (pf at position 3, hostd at position 12)
- Removed infra/ansible/playbooks/host-nginx.yaml
0.7.1 — Control Plane Refactoring:
- src/infra.ts → src/controlplane.ts (runControlPlaneChecks,
CONTROLPLANE_CHECK_INTERVAL_MS, ControlPlaneReport, ControlPlaneCheckResult)
- Watchdog stores lastControlPlaneReport; exposed as controlplane in IPC status
- doctor now queries watchdog IPC: prints WATCHDOG_* and CONTROLPLANE_* lines
- Docs: README simplified, MONITORING rewritten with watchdog/controlplane
layers, SECURITY updated with hostd in architecture diagram,
HOST-OPERATOR-MODEL gets privilege delegation section, CMS-DEPLOYMENT-PLAN
updated with implementation status
- Skills: nginx fully rewritten to cms-jail model; setup + freebsd-admin updated
- All stale src/infra.ts references eliminated
---
Build: pass | Tests: pass — 414 passed (45 files)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
2026-03-15 08:50:08 +00:00
### Web Serving
2026-03-14 14:55:47 +01:00
2026-05-07 12:20:01 +02:00
nginx runs inside the Web Service (cms jail). By default, `setup/pf.ts` configures Warden egress (NAT) only; public ingress (PF `rdr` ) is intentionally opt-in so Clawdie does not take over host ports 80/443 unexpectedly. Strapi (when used) is internal-only by default.
2026-03-08 20:11:24 +01:00
Operational docs for this milestone:
2026-04-06 01:37:26 +00:00
- [Bastille on FreeBSD 15 ](docs/public/architecture/bastille.md )
- [Jail Networking Strategy ](docs/public/architecture/jail-networking.md )
2026-04-05 06:29:19 +00:00
- [PostgreSQL Memory Plan ](docs/internal/POSTGRES-MEMORY.md )
2026-04-06 01:37:26 +00:00
- [Monitoring Model ](docs/public/operate/monitoring.md )
2026-04-05 06:29:19 +00:00
- [Manual Reset and pi-tui Rebootstrap ](docs/internal/CLEAN-RESET-PI-TUI.md )
2026-03-08 20:11:24 +01:00
2026-01-31 18:54:24 +02:00
## Usage
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
Talk to your assistant with the trigger word (default: `@Clawdie` ):
2026-02-01 12:47:40 +02:00
```
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
@Clawdie send an overview of the sales pipeline every weekday morning at 9am
@Clawdie review the git history for the past week each Friday and update the README
@Clawdie every Monday at 8am, compile news on AI developments and message me a briefing
2026-02-01 12:47:40 +02:00
```
2026-06-13 14:01:50 +02:00
Run `just doctor` to check system health (runtime, jails, networking, services, DNS resolver probes, TLS certificate expiry, ACME renewal cron, morning-report schedule, and Layered Memory Fabric DB/artifact status). Exit codes: 0 = ok or warnings, 1 = error.
2026-03-08 19:30:52 +00:00
2026-05-10 12:21:55 +02:00
### TLS Certificate Lifecycle
Public edge certificates are managed by acme.sh on the FreeBSD host and installed under `/usr/local/etc/nginx/ssl/<label>/` . The TLS setup step is safe by default:
```sh
# Non-mutating local validation: acme binary, cron, nginx -t, webroots, challenge routes, cert parsing
sudo npx tsx setup/index.ts --step tls --smoke-test
# Repair/install lifecycle without forcing issuance: install acme.sh, install cert hooks, write /etc/cron.d/clawdie-acme
sudo npx tsx setup/index.ts --step tls --apply
# Force-renew one cert only when deliberately validating or recovering before expiry
sudo npx tsx setup/index.ts --step tls --apply --cert clawdie --force-renew
```
`just doctor` reports `TLS_<LABEL>` days remaining and `ACME_RENEWAL_CRON` status. Do not force-renew repeatedly; Let’ s Encrypt rate-limits duplicate certificates.
2026-02-01 12:47:40 +02:00
From the main channel (your self-chat), you can manage groups and tasks:
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
2026-01-31 18:54:24 +02:00
```
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
@Clawdie list all scheduled tasks across groups
@Clawdie pause the Monday briefing task
@Clawdie join the Family Chat group
2026-01-31 18:54:24 +02:00
```
docs: update env example, README features, AGENTS.md with all new modules
- .env.example: add TELEGRAM_OPS_CHAT_ID, remove legacy TTS block,
update output format to native MP3
- README.md: remove broken DOCUMENTATION-SYNC-RUNBOOK references,
add Telegram commands table, session compaction, budget-aware
chat policy, and TTS sections
- AGENTS.md: add sections for budget-aware chat policy, TTS,
inbound sanitization, HTML message splitting, startup report
---
Build: pass | Tests: n/a — docs only (Sam & Claude)
2026-04-20 16:10:43 +02:00
## Telegram Commands
docs: integrate operator observability + provider fallback work
Brings the public docs in line with what shipped on multitenant over the
last few days. Three new operator-facing pages, three updates to existing
ones, and a CHANGELOG batch.
New pages (docs/public/operate/):
- operator-commands.md — single reference for all Telegram slash commands,
grouped by purpose (status, structured reports, runtime, sessions, admin
actions) with auth gating per command. Previously only in-bot /help text.
- provider-fallback.md — operator guide for the cooldown layer: env vars,
how cooldowns are detected and tracked, /policy surfacing, /clearcooldown
for manual release, the configured/effective/actual observability triple.
Includes a "path convention note" flagging that the cooldown file still
uses the legacy $CLAWDIE_VAR_DIR resolution while test/build status
files have moved to repo tmp/ — divergence to harmonize later in code.
- structured-reports.md — explains the Observed/Interpretation/Operator
Notes pattern, lists the six structured reports, documents the
test/build pipeline contract (status JSON schema + new $AGENT_STATUS_DIR
→ $CLAWDIE_VAR_DIR → tmp/status precedence Codex landed in 1389e17),
and covers free-text routing (classifyReportIntent + isOpsFlavored).
Updates:
- monitoring.md: appended "Operator-Facing Reports" section pointing at
the new structured-reports page, and "Provider Fallback Health" pointing
at the fallback page.
- operate/index.md: added the three new pages to the runbook list.
- architecture/controlplane.md: added "Runtime Observability" section
documenting the configured/effective/actual triple and linking to the
new operate pages.
- README.md: expanded the Telegram Commands table (was 10 rows, missing
every structured report, /policy, /clearcooldown, /budgetreset) and
added a pointer to operator-commands.md as the full reference. Also
noted free-text routing.
- CHANGELOG.md: appended an "operator observability + provider fallback,
apr.2026" batch under [Unreleased] covering provider fallback, the
reports family, the test/build wrapper pipeline, free-text routing,
/clearcooldown, the observability triple, the Telegram setMyCommands
menu, and the new "Verify Before Claiming Remote State" rule in
AGENTS.md.
No code changes. Slovenian sl/ mirror left untouched (out of localization
scope).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---
Build: pass | Tests: FAIL — Tests 8 failed | 1940 passed (1948)
---
Build: pass | Tests: FAIL — Tests 2 failed | 1949 passed (1951)
2026-04-26 12:58:44 +02:00
A short selection — for the full reference (status, structured reports,
runtime, sessions, admin actions, free-text routing) see
[Operator Commands ](docs/public/operate/operator-commands.md ).
2026-06-13 14:01:50 +02:00
| Command | Description | Auth |
| ---------------- | ------------------------------------------------------------------------------ | -------- |
| `/status` | System summary: jails, ZFS, PF, budget, model | anyone |
| `/report` | Structured system + auth report | admin |
| `/disk` | Structured ZFS pool + snapshot report | admin |
| `/tasks` | Structured controlplane task report | admin |
| `/budgetreport` | Structured budget + token analytics | admin |
| `/publishreport` | Structured tenant publish/content report | admin |
| `/testreport` | Structured build + test status (from wrapper-written JSON) | admin |
| `/policy` | Default runtime, per-chat overrides, fallback cooldowns | anyone |
| `/usage` | Per-agent token budget breakdown | anyone |
docs: integrate operator observability + provider fallback work
Brings the public docs in line with what shipped on multitenant over the
last few days. Three new operator-facing pages, three updates to existing
ones, and a CHANGELOG batch.
New pages (docs/public/operate/):
- operator-commands.md — single reference for all Telegram slash commands,
grouped by purpose (status, structured reports, runtime, sessions, admin
actions) with auth gating per command. Previously only in-bot /help text.
- provider-fallback.md — operator guide for the cooldown layer: env vars,
how cooldowns are detected and tracked, /policy surfacing, /clearcooldown
for manual release, the configured/effective/actual observability triple.
Includes a "path convention note" flagging that the cooldown file still
uses the legacy $CLAWDIE_VAR_DIR resolution while test/build status
files have moved to repo tmp/ — divergence to harmonize later in code.
- structured-reports.md — explains the Observed/Interpretation/Operator
Notes pattern, lists the six structured reports, documents the
test/build pipeline contract (status JSON schema + new $AGENT_STATUS_DIR
→ $CLAWDIE_VAR_DIR → tmp/status precedence Codex landed in 1389e17),
and covers free-text routing (classifyReportIntent + isOpsFlavored).
Updates:
- monitoring.md: appended "Operator-Facing Reports" section pointing at
the new structured-reports page, and "Provider Fallback Health" pointing
at the fallback page.
- operate/index.md: added the three new pages to the runbook list.
- architecture/controlplane.md: added "Runtime Observability" section
documenting the configured/effective/actual triple and linking to the
new operate pages.
- README.md: expanded the Telegram Commands table (was 10 rows, missing
every structured report, /policy, /clearcooldown, /budgetreset) and
added a pointer to operator-commands.md as the full reference. Also
noted free-text routing.
- CHANGELOG.md: appended an "operator observability + provider fallback,
apr.2026" batch under [Unreleased] covering provider fallback, the
reports family, the test/build wrapper pipeline, free-text routing,
/clearcooldown, the observability triple, the Telegram setMyCommands
menu, and the new "Verify Before Claiming Remote State" rule in
AGENTS.md.
No code changes. Slovenian sl/ mirror left untouched (out of localization
scope).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---
Build: pass | Tests: FAIL — Tests 8 failed | 1940 passed (1948)
---
Build: pass | Tests: FAIL — Tests 2 failed | 1949 passed (1951)
2026-04-26 12:58:44 +02:00
| `/clearcooldown` | Clear a [provider fallback ](docs/public/operate/provider-fallback.md ) cooldown | ops chat |
2026-06-13 14:01:50 +02:00
| `/compact` | Compact session (summarize old, keep recent turns) | admin |
| `/new` | Hard reset session, start fresh | admin |
| `/stop` | Kill running agent mid-response | admin |
| `/tts` | Toggle voice replies (on/off/status/default) | admin |
| `/activation` | Set trigger mode (always/mention) | admin |
| `/whoami` | Show your Telegram identity | anyone |
| `/help` | List available commands | anyone |
docs: integrate operator observability + provider fallback work
Brings the public docs in line with what shipped on multitenant over the
last few days. Three new operator-facing pages, three updates to existing
ones, and a CHANGELOG batch.
New pages (docs/public/operate/):
- operator-commands.md — single reference for all Telegram slash commands,
grouped by purpose (status, structured reports, runtime, sessions, admin
actions) with auth gating per command. Previously only in-bot /help text.
- provider-fallback.md — operator guide for the cooldown layer: env vars,
how cooldowns are detected and tracked, /policy surfacing, /clearcooldown
for manual release, the configured/effective/actual observability triple.
Includes a "path convention note" flagging that the cooldown file still
uses the legacy $CLAWDIE_VAR_DIR resolution while test/build status
files have moved to repo tmp/ — divergence to harmonize later in code.
- structured-reports.md — explains the Observed/Interpretation/Operator
Notes pattern, lists the six structured reports, documents the
test/build pipeline contract (status JSON schema + new $AGENT_STATUS_DIR
→ $CLAWDIE_VAR_DIR → tmp/status precedence Codex landed in 1389e17),
and covers free-text routing (classifyReportIntent + isOpsFlavored).
Updates:
- monitoring.md: appended "Operator-Facing Reports" section pointing at
the new structured-reports page, and "Provider Fallback Health" pointing
at the fallback page.
- operate/index.md: added the three new pages to the runbook list.
- architecture/controlplane.md: added "Runtime Observability" section
documenting the configured/effective/actual triple and linking to the
new operate pages.
- README.md: expanded the Telegram Commands table (was 10 rows, missing
every structured report, /policy, /clearcooldown, /budgetreset) and
added a pointer to operator-commands.md as the full reference. Also
noted free-text routing.
- CHANGELOG.md: appended an "operator observability + provider fallback,
apr.2026" batch under [Unreleased] covering provider fallback, the
reports family, the test/build wrapper pipeline, free-text routing,
/clearcooldown, the observability triple, the Telegram setMyCommands
menu, and the new "Verify Before Claiming Remote State" rule in
AGENTS.md.
No code changes. Slovenian sl/ mirror left untouched (out of localization
scope).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---
Build: pass | Tests: FAIL — Tests 8 failed | 1940 passed (1948)
---
Build: pass | Tests: FAIL — Tests 2 failed | 1949 passed (1951)
2026-04-26 12:58:44 +02:00
The bot also routes **free-text ops phrasings** ("disk usage", "are the
tests passing", "task report", etc.) to the matching structured report
instead of the LLM path — see
[Structured Reports → Free-Text Routing ](docs/public/operate/structured-reports.md#free-text-routing ).
docs: update env example, README features, AGENTS.md with all new modules
- .env.example: add TELEGRAM_OPS_CHAT_ID, remove legacy TTS block,
update output format to native MP3
- README.md: remove broken DOCUMENTATION-SYNC-RUNBOOK references,
add Telegram commands table, session compaction, budget-aware
chat policy, and TTS sections
- AGENTS.md: add sections for budget-aware chat policy, TTS,
inbound sanitization, HTML message splitting, startup report
---
Build: pass | Tests: n/a — docs only (Sam & Claude)
2026-04-20 16:10:43 +02:00
### Session Compaction
When a conversation grows past the byte limit (`AGENT_SESSION_MAX_BYTES` ), old turns are automatically summarized via the LLM and stored in the memory database. The session file is rewritten with a compaction header + last N turns at full fidelity. Manual compaction is available via `/compact` .
Remove budget enforcement + retire gated TS (Sam & Hermes)
Budget enforcement removed: DeepSeek prefix caching at ~98% hit rate
makes per-chat token budgets unnecessary.
DELETED (8 files):
- chat-policy.ts (+ test) — state machine (normal/low_budget/paused)
- controlplane-budget.ts (+ test) — budget tracking
- reports/budget-report.ts (+ test) — report generation
- controlplane-aider-runner.ts (+ test) — gated behind CONTROLPLANE_RUNNER=aider
- controlplane-heartbeat-codex.ts — gated behind CONTROLPLANE_RUNNER=codex
- tmux-screenshot-command.ts (+ test) — replaced by Herdr
REMOVED FROM PRODUCTION PATHS:
- chat_spend table + recordChatSpend/getChatSpend from controlplane-db.ts
- Budget check block in controlplane-heartbeat-dispatch.ts
- recordTokenSpend tracking in heartbeat
- /resume, /budget, /budgetreport, /budgetreset commands
- Budget state injection into system prompt
- ALL AGENT_BUDGET_* + AGENT_CHAT_DAILY_TOKEN_LIMIT config vars
- Budget routes, pages, response types, test fixtures
MARKED FOR COLIBRI MIGRATION (deprecation comments only):
- agent-runner.ts, agent-session.ts, session-compaction.ts
- jail-exec-runner.ts, controlplane-runner.ts, group-queue.ts
DOCS: AGENTS.md + README.md updated (Cost Model replacing Budget Policy).
Claude: please review executor/config imports before merge.
CONTROLPLANE_RUNNER=pi confirmed as production default.
2026-05-27 00:57:57 +02:00
### Cost Model
docs: update env example, README features, AGENTS.md with all new modules
- .env.example: add TELEGRAM_OPS_CHAT_ID, remove legacy TTS block,
update output format to native MP3
- README.md: remove broken DOCUMENTATION-SYNC-RUNBOOK references,
add Telegram commands table, session compaction, budget-aware
chat policy, and TTS sections
- AGENTS.md: add sections for budget-aware chat policy, TTS,
inbound sanitization, HTML message splitting, startup report
---
Build: pass | Tests: n/a — docs only (Sam & Claude)
2026-04-20 16:10:43 +02:00
Remove budget enforcement + retire gated TS (Sam & Hermes)
Budget enforcement removed: DeepSeek prefix caching at ~98% hit rate
makes per-chat token budgets unnecessary.
DELETED (8 files):
- chat-policy.ts (+ test) — state machine (normal/low_budget/paused)
- controlplane-budget.ts (+ test) — budget tracking
- reports/budget-report.ts (+ test) — report generation
- controlplane-aider-runner.ts (+ test) — gated behind CONTROLPLANE_RUNNER=aider
- controlplane-heartbeat-codex.ts — gated behind CONTROLPLANE_RUNNER=codex
- tmux-screenshot-command.ts (+ test) — replaced by Herdr
REMOVED FROM PRODUCTION PATHS:
- chat_spend table + recordChatSpend/getChatSpend from controlplane-db.ts
- Budget check block in controlplane-heartbeat-dispatch.ts
- recordTokenSpend tracking in heartbeat
- /resume, /budget, /budgetreport, /budgetreset commands
- Budget state injection into system prompt
- ALL AGENT_BUDGET_* + AGENT_CHAT_DAILY_TOKEN_LIMIT config vars
- Budget routes, pages, response types, test fixtures
MARKED FOR COLIBRI MIGRATION (deprecation comments only):
- agent-runner.ts, agent-session.ts, session-compaction.ts
- jail-exec-runner.ts, controlplane-runner.ts, group-queue.ts
DOCS: AGENTS.md + README.md updated (Cost Model replacing Budget Policy).
Claude: please review executor/config imports before merge.
CONTROLPLANE_RUNNER=pi confirmed as production default.
2026-05-27 00:57:57 +02:00
Budget enforcement has been removed (26.maj.2026). DeepSeek prefix caching at ~98%
hit rate makes per-chat token budgets unnecessary.
docs: update env example, README features, AGENTS.md with all new modules
- .env.example: add TELEGRAM_OPS_CHAT_ID, remove legacy TTS block,
update output format to native MP3
- README.md: remove broken DOCUMENTATION-SYNC-RUNBOOK references,
add Telegram commands table, session compaction, budget-aware
chat policy, and TTS sections
- AGENTS.md: add sections for budget-aware chat policy, TTS,
inbound sanitization, HTML message splitting, startup report
---
Build: pass | Tests: n/a — docs only (Sam & Claude)
2026-04-20 16:10:43 +02:00
### Text-to-Speech
Clawdie uses Microsoft Edge TTS (free, no API key) to generate voice replies. Configured via `TTS_AUTO_MODE` :
- `always` — every reply gets a voice message
- `inbound` — reply with voice when user sends a voice note
- `tagged` — only when agent output contains `[[tts]]` marker
- `off` — no voice messages
Per-chat override via `/tts` command.
2026-02-02 01:39:37 +02:00
## Customizing
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
Clawdie doesn't use configuration files. To make changes, just tell the AI agent what you want:
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
- "Change the trigger word to @Assistant "
2026-02-01 13:43:11 +02:00
- "Remember in the future to make responses shorter and more direct"
2026-02-01 12:47:40 +02:00
- "Add a custom greeting when I say good morning"
- "Store conversation summaries weekly"
Or run `/customize` for guided changes.
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
The codebase is small enough that the AI agent can safely modify it.
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Philosophy
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
**Small enough to understand.** One process, a few source files, no microservices. If you want to understand the full Clawdie codebase, ask the AI agent to walk you through it.
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
**Secure by isolation.** Agents run in FreeBSD jails with filesystem isolation via nullfs mounts. They can only access explicitly mounted directories. Bash access is safe because commands run inside the jail, not on your host.
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
**Built for the individual user.** Clawdie isn't a monolithic framework; it's software that fits each user's exact needs. You make your own fork and have the AI agent modify it to match your requirements.
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
**Customization = code changes.** No configuration sprawl. Want different behavior? Modify the code. The codebase is small enough that it's safe to make changes.
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
**AI-native.**
2026-02-01 12:47:40 +02:00
2026-04-12 06:27:29 +00:00
- FreeBSD installs can start with `npm run wizard` for optional interactive locale, timezone, and assistant-first onboarding. `bsddialog` is used when present; plain TTY prompts are the fallback. The selector uses FreeBSD's locale inventory, so you can choose any installed locale (for example `en_US.UTF-8` or `zh_CN.UTF-8` ) and it is applied the same way as the default.
2026-04-12 16:38:52 +00:00
- The rest of setup remains modular and scriptable through `just setup -- --step ...` (or `npm run setup -- --step ...` ).
2026-04-11 09:21:55 +00:00
- No monitoring dashboard; the harness shows status and the AI fills in the details.
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
- No debugging tools; describe the problem and the AI fixes it.
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
**Skills over features.** Instead of adding features (e.g., support for Telegram) to the codebase, contributors submit skills like `/add-telegram` that transform your fork. You end up with clean code that does exactly what you need.
2026-02-01 15:36:57 +02:00
2026-03-24 10:10:06 +00:00
## Documentation System (Phase 3.0+)
**v0.9.0 includes a complete multi-language documentation deployment system:**
### Architecture
```
Markdown Source (git) → Crowdin (translate) → Daily Sync (05:00 UTC)
↓ ↓ ↓
2026-04-05 06:29:19 +00:00
docs/public/*.md (English) → docs/public/{de,fr,es}/* → docs-v0.9.0_24.mar.2026/
2026-03-24 10:10:06 +00:00
├─ en/
├─ de/
├─ fr/
└─ es/
Symlink Swap (atomic, zero-downtime)
↓
https://docs.clawdie.si/{en,de,fr,es}/
```
### Features
2026-04-05 06:29:19 +00:00
- **Markdown Source of Truth** — English docs in `docs/public/*.md` , auto-synced to Crowdin
2026-03-24 10:10:06 +00:00
- **Crowdin Integration** — Translators work on [crowdin.com/project/clawdie-ai ](https://crowdin.com/project/clawdie-ai )
- **Automated Sync** — Daily cron @ 05:00 UTC compiles markdown → HTML for all languages
- **Zero-Downtime Deployment** — Symlink-based versioning with atomic swaps
- **30-Day Retention** — Old versions auto-cleaned, instant rollback available
- **No External Dependencies** — Pure shell compilation (no pandoc, no external tools)
### Quick Links
- **[docs-deployment skill ](.agent/skills/docs-deployment/SKILL.md )** — Complete operations guide
- **[CROWDIN.md ](CROWDIN.md )** — Translation workflow
- **[Integration Guide ](.agent/skills/docs-deployment/INTEGRATION.md )** — How build (clawdie-shell) and deployment (clawdie-ai) work together
### Supported Languages
- 🇬🇧 English (source, always current)
- 🇩🇪 Deutsch (German)
- 🇫🇷 Français (French)
- 🇪🇸 Español (Spanish)
Want to add more languages? Update `scripts/docs-sync.cron.sh` and add to Crowdin.
---
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Clawdie Ecosystem
2026-01-31 18:54:24 +02:00
docs: update SQLite references to PostgreSQL ops database (Sam & Claude)
Split-brain architecture now spans three PostgreSQL databases:
skills (read-only), memory (dynamic), and ops (operational state).
SQLite is fully removed from the runtime.
Updated: README, public docs site, install guide, internal docs,
agent memory, skill files, backup/restore procedure, debug checklist,
and 6 marketing page translations.
---
Build: pass | Tests: not run (Linux)
2026-04-11 14:56:24 +02:00
| Component | Description | Status |
| --------------------------- | -------------------------------------------------- | ----------- |
| ** `{AGENT_NAME}-worker` ** | Default Bastille worker jail profile | Current |
| **skills-memory bootstrap** | Precomputed pgvector import for the skills DB | Current |
| **docs-deployment** | Multi-language docs with Crowdin sync (Phase 3.0+) | Live |
| **clawdie-cnc** | CNC machine control | Development |
| **browser-vm** | Browser automation profile in jail config | Planned |
| **docs.clawdie.si** | Documentation site (4 languages) | Live |
2026-01-31 18:54:24 +02:00
feat(cnc): rename robot→cnc everywhere, add cnc pi-profile, fix ipc-mcp-stdio
- clawdie-robot → clawdie-cnc (README, html/clawdie/, freebsd-setup.html)
- "Robot OS" → "CNC" throughout (titles, taglines, ecosystem table, section headers)
- src/pi-profile.ts: add 'cnc' as 10th profile — CNC machine operation,
G-code, machine procedures; tools: read-only by default; thinking: high;
safety rules around position confirmation before movement
- PiTuiProfileName union now has 10 members — clean 5×2 grid for installer UI
- jail/agent-runner/src/ipc-mcp-stdio.ts: fix register_group tool —
WhatsApp JID example → Telegram tg:<chat_id> format,
"@Andy" trigger → "@Clawdie",
available_groups.json hint → SQLite messages.db
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:14:05 +00:00
### CNC (clawdie-cnc)
2026-01-31 18:54:24 +02:00
feat(cnc): rename robot→cnc everywhere, add cnc pi-profile, fix ipc-mcp-stdio
- clawdie-robot → clawdie-cnc (README, html/clawdie/, freebsd-setup.html)
- "Robot OS" → "CNC" throughout (titles, taglines, ecosystem table, section headers)
- src/pi-profile.ts: add 'cnc' as 10th profile — CNC machine operation,
G-code, machine procedures; tools: read-only by default; thinking: high;
safety rules around position confirmation before movement
- PiTuiProfileName union now has 10 members — clean 5×2 grid for installer UI
- jail/agent-runner/src/ipc-mcp-stdio.ts: fix register_group tool —
WhatsApp JID example → Telegram tg:<chat_id> format,
"@Andy" trigger → "@Clawdie",
available_groups.json hint → SQLite messages.db
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:14:05 +00:00
Clawdie-cnc is the **control system for the CNC machine** — an open source machine designed to manufacture geodesic dome components. It translates dome designs from [OSA ](https://osa.smilepowered.org ) into G-code, manages the build sequence, and logs everything to persistent memory.
2026-01-31 18:54:24 +02:00
feat(cnc): rename robot→cnc everywhere, add cnc pi-profile, fix ipc-mcp-stdio
- clawdie-robot → clawdie-cnc (README, html/clawdie/, freebsd-setup.html)
- "Robot OS" → "CNC" throughout (titles, taglines, ecosystem table, section headers)
- src/pi-profile.ts: add 'cnc' as 10th profile — CNC machine operation,
G-code, machine procedures; tools: read-only by default; thinking: high;
safety rules around position confirmation before movement
- PiTuiProfileName union now has 10 members — clean 5×2 grid for installer UI
- jail/agent-runner/src/ipc-mcp-stdio.ts: fix register_group tool —
WhatsApp JID example → Telegram tg:<chat_id> format,
"@Andy" trigger → "@Clawdie",
available_groups.json hint → SQLite messages.db
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:14:05 +00:00
See `clawdie-cnc/README.md` for details.
2026-01-31 18:54:24 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Contributing
2026-01-31 18:54:24 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
**Don't add features. Add skills.**
2026-01-31 18:54:24 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
If you want to add Slack support, don't create a PR that adds Slack alongside Telegram. Instead, contribute a skill file (`.agent/skills/add-slack/SKILL.md` ) that teaches the AI agent how to transform a Clawdie installation to use Slack.
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
Users then run `/add-slack` on their fork and get clean code that does exactly what they need, not a bloated system trying to support every use case.
2026-02-01 12:47:40 +02:00
2026-05-11 00:58:54 +02:00
### Available Skills (35+)
2026-03-08 19:30:52 +00:00
**Channels:** add-telegram, add-discord, add-gmail, add-slack, add-voice-transcription, x-integration
**Jail & Infrastructure:** warden-bootstrap, warden-pf, warden-zfs, warden-health, bastille-network, browser-vm, freebsd-admin, sanoid
2026-03-24 10:10:06 +00:00
**Operations:**
docs: update SQLite references to PostgreSQL ops database (Sam & Claude)
Split-brain architecture now spans three PostgreSQL databases:
skills (read-only), memory (dynamic), and ops (operational state).
SQLite is fully removed from the runtime.
Updated: README, public docs site, install guide, internal docs,
agent memory, skill files, backup/restore procedure, debug checklist,
and 6 marketing page translations.
---
Build: pass | Tests: not run (Linux)
2026-04-11 14:56:24 +02:00
2026-03-24 10:10:06 +00:00
- **nginx** — CMS jail vhost management
- **nginx-glasspane** — Nginx security features
- **docs-deployment** — Multi-language documentation sync (NEW v0.9.0)
- telegram-admin, tmux-screenshot, postgres-memory
2026-03-08 19:30:52 +00:00
2026-03-08 20:49:16 +00:00
**Frontend & CMS:** astro, strapi
2026-03-08 19:30:52 +00:00
**Agent:** coding-agent, add-telegram-swarm, add-parallel
2026-05-11 00:58:54 +02:00
**Utility:** setup, update, customize, debug
2026-03-08 19:30:52 +00:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
### Skills Structure
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
```
.agent/skills/add-telegram/
├── SKILL.md # Skill documentation and instructions
├── manifest.yaml # Skill metadata
├── add/ # Files to add
│ └── src/channels/telegram.ts
├── modify/ # Files to modify
│ └── src/config.ts
└── tests/ # Skill tests
└── telegram.test.ts
```
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Requirements
2026-02-01 12:47:40 +02:00
2026-05-10 16:31:40 +02:00
- FreeBSD 15.x
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
- Node.js 24+
2026-03-14 15:26:46 +01:00
- Python 3.11+ (for voice transcription, screenshots, and other features)
2026-05-10 18:49:08 +02:00
- ZFS (required for Bastille jails)
2026-03-14 00:07:42 +01:00
- Optional: Telegram bot token, provider API key, PostgreSQL URLs for memory/skills DB
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Security
2026-02-01 12:47:40 +02:00
2026-04-06 01:37:26 +00:00
Agents run in FreeBSD jails with filesystem isolation, not behind application-level permission checks. They can only access explicitly mounted directories. The codebase is small enough that you can review it. See [docs/public/operate/security.md ](docs/public/operate/security.md ) for the full security model.
2026-02-01 12:47:40 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Documentation
2026-01-31 18:54:24 +02:00
2026-03-24 10:10:06 +00:00
- **[docs.clawdie.si ](https://docs.clawdie.si )** - Complete documentation (English, Deutsch, Français, Español)
2026-04-06 01:37:26 +00:00
- **[docs/public/architecture/host-operator-model.md ](docs/public/architecture/host-operator-model.md )** - Host-first operator model and service-jail layout
2026-03-24 10:10:06 +00:00
- **[.agent/skills/docs-deployment/SKILL.md ](.agent/skills/docs-deployment/SKILL.md )** - Documentation deployment system (Phase 3.0+)
- **[.agent/skills/docs-deployment/INTEGRATION.md ](.agent/skills/docs-deployment/INTEGRATION.md )** - Cross-repo integration guide (clawdie-ai ↔ clawdie-shell)
- **[CROWDIN.md ](CROWDIN.md )** - How to translate and contribute translations
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
- **[AGENTS.md ](AGENTS.md )** - Agent development guidelines
2026-01-31 18:54:24 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Community
2026-02-01 13:43:11 +02:00
2026-03-16 09:57:30 +00:00
Questions or ideas? Open an issue on [Codeberg ](https://codeberg.org/Clawdie/Clawdie-AI ) or reach out at [hello@clawdie.si ](mailto:hello@clawdie.si ).
2026-02-01 13:43:11 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## Acknowledgments
2026-02-01 13:43:11 +02:00
2026-03-14 14:55:47 +01:00
Clawdie is built on giants' shoulders. [Peter Steinberger ](https://github.com/steipete )
created [OpenClaw ](https://github.com/openclaw/openclaw ), which set the broader
2026-03-16 09:57:30 +00:00
project line. [NanoClaw ](https://github.com/qwibitai/nanoclaw ) by
2026-03-14 14:55:47 +01:00
[Gavriel ](https://github.com/openclaw ) distilled that line into a minimal
personal-assistant upstream. Clawdie is the FreeBSD-first fork in that lineage.
2026-02-01 13:43:11 +02:00
2026-03-14 14:55:47 +01:00
We keep NanoClaw as an upstream reference where it helps, then carry the design
into native jails, ZFS, PF, and the wider
[OSA ](https://osa.smilepowered.org ) mission.
2026-02-01 13:43:11 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
## License
2026-02-01 13:43:11 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
BSD 3-Clause License
Adds Agent Swarms
* feat: streaming container mode, IPC messaging, agent teams support
Major architectural shift from single-shot container runs to long-lived
streaming containers with IPC-based message injection.
- Agent runner: query loop with AsyncIterable prompt to keep stdin open
for agent teams (fixes isSingleUserTurn premature shutdown)
- New standalone stdio MCP server (ipc-mcp-stdio.ts) inheritable by
subagents, with send_message and schedule_task tools
- Streaming output: parse OUTPUT_START/END markers in real-time, send
results to WhatsApp as they arrive
- IPC file-based messaging: host writes to ipc/{group}/input/, agent
polls for follow-up messages without respawning containers
- Per-group settings.json with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
- SDK bumped to 0.2.34 for TeamCreate tool support
- Container idle timeout (30min) with _close sentinel for shutdown
- Orphaned container cleanup on startup
- alwaysRespond flag for groups that skip trigger pattern check
- Uncaught exception/rejection handlers with timestamps in logger
- Combined SDK documentation into single deep dive reference
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove unused ipc-mcp.ts (replaced by ipc-mcp-stdio.ts)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: clarify agent communication model in docs and tool descriptions
- CLAUDE.md (main + global): split communication instructions into
"responding to messages" vs "scheduled tasks" sections
- send_message tool: note that scheduled task output is not sent to user
- Remove structured output (outputFormat) — not needed with current flow
- Regular output is sent to WhatsApp; scheduled task output is only logged
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: ignore dynamic group data while preserving base structure
Only track groups/main/CLAUDE.md and groups/global/CLAUDE.md. All other
group directories and files are ignored to prevent tracking user-specific
session data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve critical bugs in streaming container mode
Bug 1 (scheduled task hang): Task scheduler now passes onOutput callback
with idle timer that writes _close sentinel after IDLE_TIMEOUT, so
containers exit cleanly instead of blocking queue slots for 30 minutes.
Scheduled tasks stay alive for interactive follow-up via IPC.
Bug 2 (timeout disabled): Remove resetTimeout() from stderr handler.
SDK writes debug logs continuously, resetting the timer on every line.
Timeout now only resets on actual output markers in stdout.
Bug 3 (trigger bypass): Piped messages in startMessageLoop now check
trigger pattern for non-main groups. Non-trigger messages accumulate in
DB and are pulled as context via getMessagesSince when a trigger arrives.
Bug 7 (non-atomic IPC writes): GroupQueue.sendMessage uses temp file +
rename for atomic writes, matching ipc-mcp-stdio.ts pattern.
Also: flip isVerbose back to false (debug leftover), add isScheduledTask
to host-side ContainerInput interface.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer not starting + scheduled task groupFolder missing
Two bugs that prevented the scheduled task idle timeout fix from working:
1. onOutput was only called when parsed.result !== null, but session
update markers have result: null. The idle timer never started for
"silent" query completions, leaving containers parked at
waitForIpcMessage until hard timeout.
2. Scheduler's onProcess callback didn't pass groupFolder to
queue.registerProcess, so closeStdin no-oped (groupFolder was null).
The _close sentinel was never written even when the idle timer fired.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: duplicate messages and timestamp rollback in piping path
Two bugs introduced by the trigger context accumulation change:
1. processGroupMessages didn't advance lastAgentTimestamp until after
the container finished. The piping path's getMessagesSince(lastAgent
Timestamp) re-fetched messages already sent as the initial prompt,
causing duplicates.
2. processGroupMessages overwrote lastAgentTimestamp with the original
batch timestamp on completion, rolling back any advancement made by
the piping path while the container was running.
Fix: advance lastAgentTimestamp immediately after building the prompt,
before starting the container. This matches the piping path behavior
and eliminates both the overlap and the rollback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: container idles 30 extra minutes after _close during query
When _close was detected during pollIpcDuringQuery, it was consumed
(deleted) and stream.end() was called. But after runQuery returned,
main() still emitted a session-update marker (resetting the host's idle
timer) and called waitForIpcMessage (which polled forever since _close
was already gone). The container had to wait for a second _close.
Fix: runQuery now returns closedDuringQuery. When true, main() skips
the session-update marker and waitForIpcMessage, exiting immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resume branching, internal tags, and output forwarding
- Fix resume branching: pass resumeSessionAt with last assistant UUID
to anchor each query loop resume to the correct conversation tree
position. Prevents agent responses landing on invisible branches
when agent teams subagents create parallel JSONL entries.
- Add <internal> tag stripping: agent can wrap internal reasoning in
<internal> tags which are logged but not sent to WhatsApp. Prevents
duplicate messages and internal monologue reaching users.
- Forward scheduled task output: scheduled tasks now send result text
to WhatsApp (with <internal> stripping), matching regular message
behavior. No more special-case instructions.
- Update Communication guidance in CLAUDE.md: simplified to "your
output is sent to the user or group" with soft guidance on
<internal> tags and send_message usage.
- Add messaging behavior docs to schedule_task tool: prompts the
scheduling agent to include guidance on whether the task should
always/conditionally/never message the user.
- Mount security: containerPath now optional, defaults to basename
of hostPath.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: cursor rollback on error, flush guard, verbose logging
- Roll back lastAgentTimestamp on container error so retries can
re-process the messages instead of silently losing them.
- Add guard flag to flushOutgoingQueue to prevent duplicate sends
from concurrent flushes during rapid WA reconnects.
- Revert isVerbose from hardcoded false back to env-based check
(LOG_LEVEL=debug|trace).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: orphan container cleanup was silently failing
The startup cleanup used `container ls --format {{.Names}}` which is
Docker Go-template syntax. Apple Container only supports `--format json`
or `--format table`. The command errored with exit code 64, but the
catch block silently swallowed it — orphan containers were never cleaned
up on restart.
Fixed to use `--format json` and parse `configuration.id` from the
JSON output. Also filters by `status: running` and logs a warning on
failure instead of silently catching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Discord badge and community section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer reset on null results and flush queue message loss
- Only reset idle timer on actual results (non-null), not session-update
markers. Prevents containers staying alive 30 extra minutes after the
agent finishes work.
- flushOutgoingQueue now uses shift() instead of splice(0) so unattempted
messages stay in the queue if an unexpected error bails the loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Agent Swarms to README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update Telegram skill for current architecture
Rewrite integration instructions to match the per-group queue/SQLite
architecture: remove onMessage callback pattern (store to DB, let
message loop pick up), fix startSchedulerLoop signature, add
TELEGRAM_ONLY service startup, SQLite registration, data/env/env sync,
@mention-to-trigger translation, and BotFather group privacy docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Telegram skill message chunking, media placeholders, chat discovery
- Split long messages at Telegram's 4096 char limit to prevent silent
send failures
- Store placeholder text for non-text messages (photos, voice, stickers,
etc.) so the agent knows media was sent
- Update getAvailableGroups filter to include tg: chats so the agent can
discover and register Telegram chats via IPC
- Fix removal step numbering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update REQUIREMENTS.md and SPEC.md for SQLite architecture
- Replace all registered_groups.json / sessions.json / router_state.json
references with SQLite equivalents
- Fix CONTAINER_TIMEOUT default (300000 → 1800000)
- Add missing config exports (IDLE_TIMEOUT, MAX_CONCURRENT_CONTAINERS)
- Update folder structure: add missing src files (logger, group-queue,
mount-security), remove non-existent utils.ts, list all skills
- Fix agent-runner entry (ipc-mcp.ts → ipc-mcp-stdio.ts)
- Update startup sequence to reflect per-group queue architecture
- Fix env mounting description (data/env/env, not extracted vars)
- Update troubleshooting to use sqlite3 commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: fix README architecture description, revert SPEC.md env error
- README: update architecture blurb to mention per-group queue, add
group-queue.ts to key files, update file descriptions
- SPEC.md: restore correct credential filtering description (only auth
vars are extracted from .env, not the full file)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 02:50:43 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
Copyright (c) 2026, Sam (Samo Blatnik)
Adds Agent Swarms
* feat: streaming container mode, IPC messaging, agent teams support
Major architectural shift from single-shot container runs to long-lived
streaming containers with IPC-based message injection.
- Agent runner: query loop with AsyncIterable prompt to keep stdin open
for agent teams (fixes isSingleUserTurn premature shutdown)
- New standalone stdio MCP server (ipc-mcp-stdio.ts) inheritable by
subagents, with send_message and schedule_task tools
- Streaming output: parse OUTPUT_START/END markers in real-time, send
results to WhatsApp as they arrive
- IPC file-based messaging: host writes to ipc/{group}/input/, agent
polls for follow-up messages without respawning containers
- Per-group settings.json with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
- SDK bumped to 0.2.34 for TeamCreate tool support
- Container idle timeout (30min) with _close sentinel for shutdown
- Orphaned container cleanup on startup
- alwaysRespond flag for groups that skip trigger pattern check
- Uncaught exception/rejection handlers with timestamps in logger
- Combined SDK documentation into single deep dive reference
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove unused ipc-mcp.ts (replaced by ipc-mcp-stdio.ts)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: clarify agent communication model in docs and tool descriptions
- CLAUDE.md (main + global): split communication instructions into
"responding to messages" vs "scheduled tasks" sections
- send_message tool: note that scheduled task output is not sent to user
- Remove structured output (outputFormat) — not needed with current flow
- Regular output is sent to WhatsApp; scheduled task output is only logged
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: ignore dynamic group data while preserving base structure
Only track groups/main/CLAUDE.md and groups/global/CLAUDE.md. All other
group directories and files are ignored to prevent tracking user-specific
session data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve critical bugs in streaming container mode
Bug 1 (scheduled task hang): Task scheduler now passes onOutput callback
with idle timer that writes _close sentinel after IDLE_TIMEOUT, so
containers exit cleanly instead of blocking queue slots for 30 minutes.
Scheduled tasks stay alive for interactive follow-up via IPC.
Bug 2 (timeout disabled): Remove resetTimeout() from stderr handler.
SDK writes debug logs continuously, resetting the timer on every line.
Timeout now only resets on actual output markers in stdout.
Bug 3 (trigger bypass): Piped messages in startMessageLoop now check
trigger pattern for non-main groups. Non-trigger messages accumulate in
DB and are pulled as context via getMessagesSince when a trigger arrives.
Bug 7 (non-atomic IPC writes): GroupQueue.sendMessage uses temp file +
rename for atomic writes, matching ipc-mcp-stdio.ts pattern.
Also: flip isVerbose back to false (debug leftover), add isScheduledTask
to host-side ContainerInput interface.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer not starting + scheduled task groupFolder missing
Two bugs that prevented the scheduled task idle timeout fix from working:
1. onOutput was only called when parsed.result !== null, but session
update markers have result: null. The idle timer never started for
"silent" query completions, leaving containers parked at
waitForIpcMessage until hard timeout.
2. Scheduler's onProcess callback didn't pass groupFolder to
queue.registerProcess, so closeStdin no-oped (groupFolder was null).
The _close sentinel was never written even when the idle timer fired.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: duplicate messages and timestamp rollback in piping path
Two bugs introduced by the trigger context accumulation change:
1. processGroupMessages didn't advance lastAgentTimestamp until after
the container finished. The piping path's getMessagesSince(lastAgent
Timestamp) re-fetched messages already sent as the initial prompt,
causing duplicates.
2. processGroupMessages overwrote lastAgentTimestamp with the original
batch timestamp on completion, rolling back any advancement made by
the piping path while the container was running.
Fix: advance lastAgentTimestamp immediately after building the prompt,
before starting the container. This matches the piping path behavior
and eliminates both the overlap and the rollback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: container idles 30 extra minutes after _close during query
When _close was detected during pollIpcDuringQuery, it was consumed
(deleted) and stream.end() was called. But after runQuery returned,
main() still emitted a session-update marker (resetting the host's idle
timer) and called waitForIpcMessage (which polled forever since _close
was already gone). The container had to wait for a second _close.
Fix: runQuery now returns closedDuringQuery. When true, main() skips
the session-update marker and waitForIpcMessage, exiting immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resume branching, internal tags, and output forwarding
- Fix resume branching: pass resumeSessionAt with last assistant UUID
to anchor each query loop resume to the correct conversation tree
position. Prevents agent responses landing on invisible branches
when agent teams subagents create parallel JSONL entries.
- Add <internal> tag stripping: agent can wrap internal reasoning in
<internal> tags which are logged but not sent to WhatsApp. Prevents
duplicate messages and internal monologue reaching users.
- Forward scheduled task output: scheduled tasks now send result text
to WhatsApp (with <internal> stripping), matching regular message
behavior. No more special-case instructions.
- Update Communication guidance in CLAUDE.md: simplified to "your
output is sent to the user or group" with soft guidance on
<internal> tags and send_message usage.
- Add messaging behavior docs to schedule_task tool: prompts the
scheduling agent to include guidance on whether the task should
always/conditionally/never message the user.
- Mount security: containerPath now optional, defaults to basename
of hostPath.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: cursor rollback on error, flush guard, verbose logging
- Roll back lastAgentTimestamp on container error so retries can
re-process the messages instead of silently losing them.
- Add guard flag to flushOutgoingQueue to prevent duplicate sends
from concurrent flushes during rapid WA reconnects.
- Revert isVerbose from hardcoded false back to env-based check
(LOG_LEVEL=debug|trace).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: orphan container cleanup was silently failing
The startup cleanup used `container ls --format {{.Names}}` which is
Docker Go-template syntax. Apple Container only supports `--format json`
or `--format table`. The command errored with exit code 64, but the
catch block silently swallowed it — orphan containers were never cleaned
up on restart.
Fixed to use `--format json` and parse `configuration.id` from the
JSON output. Also filters by `status: running` and logs a warning on
failure instead of silently catching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Discord badge and community section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: idle timer reset on null results and flush queue message loss
- Only reset idle timer on actual results (non-null), not session-update
markers. Prevents containers staying alive 30 extra minutes after the
agent finishes work.
- flushOutgoingQueue now uses shift() instead of splice(0) so unattempted
messages stay in the queue if an unexpected error bails the loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Agent Swarms to README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update Telegram skill for current architecture
Rewrite integration instructions to match the per-group queue/SQLite
architecture: remove onMessage callback pattern (store to DB, let
message loop pick up), fix startSchedulerLoop signature, add
TELEGRAM_ONLY service startup, SQLite registration, data/env/env sync,
@mention-to-trigger translation, and BotFather group privacy docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Telegram skill message chunking, media placeholders, chat discovery
- Split long messages at Telegram's 4096 char limit to prevent silent
send failures
- Store placeholder text for non-text messages (photos, voice, stickers,
etc.) so the agent knows media was sent
- Update getAvailableGroups filter to include tg: chats so the agent can
discover and register Telegram chats via IPC
- Fix removal step numbering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update REQUIREMENTS.md and SPEC.md for SQLite architecture
- Replace all registered_groups.json / sessions.json / router_state.json
references with SQLite equivalents
- Fix CONTAINER_TIMEOUT default (300000 → 1800000)
- Add missing config exports (IDLE_TIMEOUT, MAX_CONCURRENT_CONTAINERS)
- Update folder structure: add missing src files (logger, group-queue,
mount-security), remove non-existent utils.ts, list all skills
- Fix agent-runner entry (ipc-mcp.ts → ipc-mcp-stdio.ts)
- Update startup sequence to reflect per-group queue architecture
- Fix env mounting description (data/env/env, not extracted vars)
- Update troubleshooting to use sqlite3 commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: fix README architecture description, revert SPEC.md env error
- README: update architecture blurb to mention per-group queue, add
group-queue.ts to key files, update file descriptions
- SPEC.md: restore correct credential filtering description (only auth
vars are extracted from .env, not the full file)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 02:50:43 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
See [LICENSE ](LICENSE ) for full text.
2026-01-31 18:54:24 +02:00
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
---
< p align = "center" >
< strong > Clawdie< / strong > · Personal AI Assistant on FreeBSD< br >
2026-03-10 21:08:08 +00:00
< a href = "https://clawdie.si" > clawdie.si< / a > · < a href = "https://docs.clawdie.si" > docs.clawdie.si< / a > < br >
2026-03-14 14:55:47 +01:00
< em > Built on giants' shoulders · FreeBSD-first< / em >
refactor: replace WhatsApp with Telegram, rename container→jail, migrate skills to .agent/
- Replace WhatsApp channel (@whiskeysockets/baileys) with Telegram (grammy)
- Add src/channels/telegram.ts, remove src/channels/whatsapp.ts + whatsapp-auth.ts
- TELEGRAM_BOT_TOKEN required; fatal exit if not set
- Remove @whiskeysockets/baileys, qrcode, qrcode-terminal packages
- Update routing tests to use tg: JID format
- Rename container→jail throughout src/
- container-runner.ts → jail-runner.ts (jexec-based spawn)
- container-runtime.ts → jail-ops.ts (stopJail, ensureJailRunning, cleanupStaleJails)
- Add jail-config.ts, jail-runtime.ts for FreeBSD jail provisioning
- Rename config exports: CONTAINER_TIMEOUT→JAIL_TIMEOUT, MAX_CONCURRENT_CONTAINERS→MAX_CONCURRENT_JAILS
- Update group-queue.ts: isTaskContainer→isTaskJail, activeContainers→activeJails
- Migrate skills from .claude/skills/ to .agent/skills/
- Add tmux-screenshot skill (ANSI color PNG renderer, wide-char fix, 24-bit truecolor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 18:36:27 +01:00
< / p >