---
name: treehouse-ops
description: Treehouse platform operations — NixOS rebuilds, nanoclaw and Mission Control service management, DB operations, SIGHUP hot-reload, scheduled tasks, skills system, audio/TTS, and agent workspace contract details.
allowed-tools: Bash(ssh:*), Bash(sudo:*), Read, Write, Edit
---

# Treehouse Platform Operations

SSH: `ssh treehouse-host '<command>'`

## NixOS Config & Rebuild

All server, service, and tenant config is declarative. **Never configure imperatively.**

- `/etc/nixos/configuration.nix` — system, firewall, Caddy, packages
- `/etc/nixos/nanoclaw-tenants.nix` — tenant provisioning, sandboxing, services
- `/etc/nixos/borgmatic.nix` — backup config

```bash
sudo nixos-rebuild switch
```

## Nanoclaw Service

- **Source:** `/home/admin/treehouse/nanoclaw` (symlinked to `/opt/nanoclaw/base/`)
- **Service:** `nanoclaw.service`
- **NEVER restart** without user confirmation — kills containers, disconnects bots, interrupts sessions
- **NEVER** run `systemctl kill` on a tenant user slice (`user-<uid>.slice`) without user confirmation — kills ALL tenant containers, containerd, buildkitd, and active sessions for that tenant

### SIGHUP (hot-reload) — preferred

Re-reads all tenants and groups from DB without restarting. No containers killed, no disconnections.

Use for: adding/modifying tenants, registering groups, any DB-only change.

```bash
treehouse nanoclaw hup
# or: sudo systemctl kill -s HUP nanoclaw.service
```

### Full restart — only when necessary

Use for: nanoclaw code changes, tenant deletion (user/volume removed).

NanoClaw restart now performs a bounded graceful stop first: it writes resume markers for active chats, asks idle agent containers to exit, and signals detached tenant runtime helpers before the service exits.

```bash
# Always ask user first
treehouse nanoclaw status
treehouse nanoclaw logs --lines 100
sudo systemctl restart nanoclaw.service
```

## Mission Control (MC)

- **Backend:** `/home/admin/treehouse/mc/server.mjs` — `mission-control.service`
- **Frontend:** `/home/admin/treehouse/mc-ui/` — static production build

```bash
# UI change? Rebuild first (no service restart needed after)
cd /home/admin/treehouse/mc-ui && npm run build

# Backend change? Restart service
sudo systemctl restart mission-control

# CLI shortcuts
treehouse mc restart --yes
treehouse mc restart --build-ui --yes
```

## MC Tasks (Mission Control)

Use `treehouse mctasks` for all MC task operations — never query the DB directly for this.

```bash
treehouse mctasks list                          # list all tasks
treehouse mctasks list --status open            # filter by status (open/in_progress/done/cancelled)
treehouse mctasks show --id <taskId>            # full task detail
treehouse mctasks create --title "Fix X" --description "..." --status open --priority high
treehouse mctasks update --id <taskId> --status in_progress
treehouse mctasks comment --id <taskId> --text "Done, deployed to prod"
treehouse mctasks delete --id <taskId> --yes
```

## Database Operations

Use `sqlite3` only for data the CLI does not expose (usage logs, raw session state, etc). For tenants, tasks, groups, and apps — use the CLI commands instead.


Central SQLite DB at `/var/lib/nanoclaw/store/messages.db`.

> ⚠️ `/home/admin/treehouse/nanoclaw/store/messages.db` is a dev/test DB — NOT the live DB. Always use `/var/lib/nanoclaw/store/messages.db`.

```bash
# Query tenants
sqlite3 /var/lib/nanoclaw/store/messages.db "SELECT id, name, status FROM tenants"

# Daily usage
sqlite3 /var/lib/nanoclaw/store/messages.db \
  "SELECT tenant_id, COUNT(*) as runs FROM usage_log WHERE date(timestamp) = date('now') GROUP BY tenant_id"
```

## Scheduled Tasks

Agents schedule tasks via `schedule_task` IPC. The platform polls every 60 seconds.

Schedule types: `cron` (cron expression), `interval` (milliseconds), `once` (ISO-8601 timestamp, auto-completes).

- Usage limits are checked before each task run (same as interactive messages)
- Every run is logged to `usage_log`
- Cross-tenant scheduling is blocked

```bash
treehouse tasks list
treehouse tasks list --tenant <id>
treehouse tasks show --id <taskId>
treehouse tasks logs --id <taskId>
treehouse tasks watch
treehouse tasks pause  --id <taskId> [--yes]
treehouse tasks resume --id <taskId> [--yes]
treehouse tasks cancel --id <taskId> [--yes]
```

Key source files: `src/task-scheduler.ts`, `src/ipc.ts:1120`, `src/db.ts:785`

## Skills System

Skills are directories with a `SKILL.md` (YAML frontmatter + markdown body) in `.claude/skills/`. Only the `description` frontmatter field is loaded into the system prompt — full body loads only on invocation.

Skill layers (later overrides earlier):
1. Base skills — `treehouse/nanoclaw/container/skills/<skill>/`
2. Tenant skills — `/home/<tenant>/nanoclaw/skills/<skill>/`
3. Platform skills — `container/skills-platform/<skill>/` (available to all tenants, hidden from dashboard — lazy-loaded like other skills)
4. Admin skills — `container/skills-admin/<skill>/` (admin tenants only)

Skills take effect on the next agent run — no restart or SIGHUP needed.

```bash
# Tenant skill API (tenant-scoped)
GET/PUT/DELETE /td/api/skills/:id
```

## Audio Processing

Discord audio → host temp file → staged to `/workspace/attachments/` spool → container normalizes with `ffmpeg` + transcribes with `whisper-cli` → transcript prepended to user message.

- Whisper model provided by NixOS via `NANOCLAW_WHISPER_MODEL_FILE` (mounted read-only at `/models/whisper/ggml-base.en.bin`)
- Audio temp files should be written to `/var/lib/nanoclaw/store/attachments/` (not `/tmp` — service uses `PrivateTmp=true`)
- Low-capacity tenants may fail transcription if RAM/CPU limits are too small — intentional

## Text To Speech

Agent runs `tc send voice <text>` → tc calls edge-tts locally to synthesize to `/workspace/group/.nanoclaw-outbound/tts/` → IPC `file` message → host delivers via channel → host cleans up generated file.

- Current provider: `edge-tts` (swappable adapter registry in container)
- Host does not synthesize audio — only delivers the generated file

## Agent Workspace Contract

| File | Purpose | Writable by |
|------|---------|-------------|
| `AGENTS.md` | Operating instructions, injected each run | Read-only |
| `SOUL.md` | Assistant voice/persona | Tenant |
| `IDENTITY.md` | Agent identity/persona | Tenant |
| `USER.md` | User facts/preferences | Tenant |
| `MEMORY.md` | Canonical durable memory | Agent (nanoclaw) |
| `memory/` | Extended memory notes | Agent (nanoclaw) |
| `BOOTSTRAP.md` | Optional first-run onboarding | Deleted after use |

- `CLAUDE.md` is a compatibility symlink → `MEMORY.md` (keeps Claude Code features working)
- Non-main groups inherit shared profile files from the tenant's main group
- File edits inside the container at `/home/node/.claude/projects/-workspace-group/memory/MEMORY.md` reflect the group workspace mount — same file as the host-side group `MEMORY.md`

## Maintenance

- **After modifying nanoclaw IPC handlers, platform behaviour, or any agent-facing feature, update the relevant skills** (, , , etc.) so documentation stays accurate.
- After modifying the tc — Treehouse CLI

Commands:
  tc whoami                               Show current tenant ID

  tc app deploy <app>                     Deploy an app
  tc app remove <app>                     Remove an app
  tc app stop <app>                       Stop an app
  tc app restart <app> [--service <svc>]  Restart an app
  tc app logs <app> <svc> [--tail N]      Fetch app logs
  tc app exec <app> <svc> -- <cmd...>     Exec in app container
  tc app volumes <app>                    List app volumes
  tc app volumes remove <app> <vol>       Remove a named volume
  tc app wait <app> [--timeout N]         Wait for deploy to complete
  tc app status [<app>]                   Show app deploy status
  tc app errors [--limit N]              Show recent deploy errors

  tc proxy                                Show residential proxy URL (if available)

  tc hosting info                         Show hosting info

  tc send <text>                          Send a message to the current group
  tc send --group <jid> <text>            Send a message to a specific group by JID
  tc send file <path> [--caption <t>]     Send a file
  tc send voice <text>                    Send a voice message

  tc tasks                                List scheduled tasks
  tc tasks schedule --type T --value V P  Schedule a task
  tc tasks pause <id>                     Pause a task
  tc tasks resume <id>                    Resume a task
  tc tasks cancel <id>                    Cancel a task
  tc tasks update <id> [opts]             Update a task

  tc groups list                                               List registered groups and their JIDs
  tc groups register --jid J --name N --folder F --trigger T  Register group
  tc groups settings                                           Show current group settings
  tc groups settings --requires-trigger true|false            Update requires-trigger setting

  tc runtime prune <scope>                Prune runtime (builder|images|volumes|all) — images-all blocked for agents
  tc runtime disk                         Show disk usage
  tc runtime reset-buildkit               Reset buildkit

  tc hooks [status]                       Show hooks token and enabled state
  tc hooks enable                         Enable hooks (auto-generates token)
  tc hooks disable                        Disable hooks
  tc hooks rotate                         Rotate the hooks bearer token

  tc report <text>                        Send a bug report to the platform admin

  tc creds [list]                         List credentials
  tc creds get <name>                     Get credential value
  tc creds set <name> <value>             Set or update a credential

## Maintenance

- **After modifying nanoclaw IPC handlers, platform behaviour, or any agent-facing feature, update the relevant skills** (`treehouse-tc`, `treehouse-app-hosting`, `treehouse-troubleshooting`, etc.) so documentation stays accurate.
- After modifying the `tc` CLI or `@treehouse/sdk`, update `treehouse-tc/SKILL.md`.
- After changing platform-level IPC message types, update all skills that describe those behaviours. Note: tasks/groups/hosting/group-settings are now served on-demand via IPC (get_tasks, get_groups, get_hosting, get_group_settings) — there are no longer pre-baked snapshot files written before each agent run.
