?

The convention

Rousseau does not have a first-class "workspace" concept. It has one state.path in internal/config/config.go (StateConfig) and by default points every process at ~/.local/share/rousseau/sessions.db. All sessions, cron jobs, JID mappings, and the FTS5 recall index live in that single file.

For most operators that's exactly right. When you want isolation — per project, per machine, per client — you point rousseau at a different SQLite file. That file is the workspace.

Switch workspace per invocation

Two knobs, either works:

# 1. flag on any rousseau command
rousseau --config ~/.config/rousseau/acme.yaml chat

# 2. env var (Viper picks it up via ROUSSEAU_STATE_PATH)
ROUSSEAU_STATE_PATH=~/.local/share/rousseau/acme.db rousseau chat

Neither approach requires a rousseau restart when you jump between workspaces — each process opens its own file.

Per-project workspace layout

~/.config/rousseau/
├── acme.yaml         # provider = anthropic, state.path = …/acme.db
├── personal.yaml     # provider = claudecli, state.path = …/personal.db
└── work.yaml         # provider = bedrock,    state.path = …/work.db

Each config file overrides state.path:

state:
  path: /home/seb/.local/share/rousseau/acme.db

Then launch each session with the right config. The TUI (internal/tui/model.go) surfaces the session id + provider in its status bar — visual confirmation you're in the right workspace.

Sharing history across machines

The session store is a single SQLite file. WAL journaling is enabled by Open() in internal/state/sqlite/store.go, so live snapshots are safe:

# Snapshot laptop-to-desktop (both idle)
rsync -avz --partial \
  ~/.local/share/rousseau/sessions.db \
  desktop:~/.local/share/rousseau/sessions.db

Only one writer at a time. Do not run rousseau whatsapp on two machines against the same SQLite file over NFS — that is undefined. Sync when nothing is writing, or run a single writer with read replicas.

A safer alternative is the .backup snapshot:

sqlite3 ~/.local/share/rousseau/sessions.db ".backup '/tmp/sessions.snap.db'"
scp /tmp/sessions.snap.db desktop:~/.local/share/rousseau/sessions.db

.backup uses SQLite's online backup API and produces a consistent point-in-time file.

Migrating a workspace

Move the whole directory; that's the workspace:

rsync -avz ~/.local/share/rousseau/ new-host:~/.local/share/rousseau/

whatsapp.db (device credentials) is separate — you either bring it too (device stays paired) or leave it behind and re-scan the QR on the new host.

Dropping a workspace's history

rousseau session list                 # confirm what you're about to lose
rm ~/.local/share/rousseau/acme.db*   # includes -wal and -shm sidecars

The next process to open the path will re-create it with the schema in internal/state/sqlite/schema.sql.

If you only want to drop a subset of sessions, use the CLI:

rousseau session delete <id> --yes

rousseau session delete (internal/cli/session.go) calls Store.Delete, which cascades through the FTS5 triggers to keep the recall index consistent. The --yes flag is required — the command refuses to run without it.

Partial deletion via SQL

For bulk cleanup — every session older than 90 days:

sqlite3 ~/.local/share/rousseau/sessions.db <<'SQL'
DELETE FROM sessions WHERE updated_at < datetime('now', '-90 days');
SQL

The FTS5 triggers (sessions_fts_ad in internal/state/sqlite/search.go) fire on the DELETE and keep the index in sync automatically.

Per-workspace approvers

Because config file and state file are both per-workspace, so is the approver:

# work.yaml — strict pattern approver
agent:
  approver:
    mode: pattern
    default: deny
    allow:
      - {tool: read, match: ".*"}
      - {tool: grep, match: ".*"}

state:
  path: /home/seb/.local/share/rousseau/work.db

A separate personal.yaml might keep mode: allow_all for interactive work. See Tutorial: Harden the approver.

Related

Type to search 150+ pages. Ranking: BM25 with title/description boost.