# Open Claudia

Your always-on, provider-agnostic coding-agent harness — Claude Code and OpenAI Codex via Telegram or Kazee Chat.

Send text, voice notes, screenshots, and files from your phone. Open Claudia runs the selected coding-agent provider on your projects, remembers what it learned, and reports back.

## Features

### Channels & providers
- **Multi-channel** — run the same bot on Telegram, Kazee Chat, or both at once (`CHANNELS=telegram,kazee`). Each channel renders keyboards, files, voice notes, and edits natively
- **Multi-provider** — switch between Claude Code and OpenAI Codex on the fly (`/backend claude|codex`, or pick a model in `/model`); each keeps its own project-scoped session state
- **Multi-user / team mode** — one bot serves multiple authorized users in parallel, each with their own conversations, settings, model, provider, and usage counters
- **Multi-project sessions** — switch between workspace projects; per-project conversation history auto-resumes

### Memory & long-term context
- **Context packs** — living per-topic documents (one per project, system, or recurring task) holding Stance, Procedure, State, and Journal. Packs matching your message are auto-injected into the agent's context, and a background reviewer updates them after every substantial turn — the assistant keeps its train of thought across sessions and projects
- **Entity memory** — short notes on the people, places, projects, orgs, and systems you mention, extracted automatically and injected when they come up again
- **Pluggable recall** — switch per chat with `/engine`: the **discoverer** graph engine (default), which walks a typed-edge graph over your packs/entities and surfaces hits with one-line why-bullets, or the simpler **classic** keyword engine as an explicit opt-out
- **Dream consolidation** — a nightly pass on a stronger model that merges duplicate packs, builds umbrella/parent pack trees, tightens descriptions, dedupes entities, tends the recall graph, and reports what it tidied — with everything backed up first
- **Personality** — a persona file gives the assistant a consistent voice on top of your soul file, and the dream pass evolves it gently as you work together
- **Transcript search** — redacted project transcripts indexed in SQLite FTS5; `open-claudia transcript-search` gives the agent ~50ms ranked recall over months of history
- **Smart compaction** — long conversations are summarized proactively before they get slow; full briefs are archived to disk so nothing is truly lost (`/compact`, `/compactwindow`)
- **No silent learning** — every pack, entity, or skill the bot creates or changes is announced in chat with one line

### Background work
- **Wakeups & crons** — the agent can schedule one-shot wake-ups ("check the deploy in 20 minutes") and recurring jobs that survive restarts
- **Persistent tasks** — a per-channel todo tree with plans and subtasks that survives compaction and restarts
- **Sub-agents** — throwaway research agents for side questions that shouldn't pollute the main conversation
- **Agent mode** — non-blocking side conversations while heavy tasks run in the background

### Working from your phone
- **Voice notes** — speak instructions, transcribed locally via Whisper; voice questions get voice replies (macOS)
- **Screenshots & images** — send UI mockups, errors, or code screenshots
- **File sharing** — send PDFs, code files, documents; the agent can send files, photos, and voice clips back
- **Reply context** — reply to any message (including files) for follow-up
- **Streaming output** — see the agent working in real time

### Team
- **People roster** — the bot knows your team members, their channels, and notes about them
- **Intros** — unknown chats go through an owner-approved introduction flow
- **Cross-channel relay** — the agent can message teammates on their own channels (with provenance and an audit trail)
- **Identity links** — link chats across channels to one canonical user so history follows you

### Operations
- **Encrypted vault** — store API keys and credentials securely
- **Customizable soul** — define your assistant's personality and knowledge
- **Capability-driven settings** — model, effort, read-only mode, budget, and worktree controls appear only when the selected provider supports them
- **Token economy** — byte-stable system prompt for maximum Anthropic prompt-cache hits; dynamic state rides each message instead
- **Web UI** — optional browser UI for setup and config (`open-claudia start --web`)
- **Auto-updates** — checks npm every 5 minutes, upgrade with `/upgrade`
- **Cluster self-management** — when running as an AgentSpace pod, the bot can inspect and manage its own deployment (`/cluster`, or `open-claudia cluster …` for the agent) through the broker, which authenticates, capability-checks, and audits every operation
- **Requirements doctor** — `/doctor` checks CLI installs, auth, voice tools, and writable paths
- **Cross-platform** — macOS, Linux, and Windows

## Prerequisites

- [Node.js](https://nodejs.org/) **24+** (required — its built-in SQLite powers pack/entity/transcript search and the recall graph). On older Node the bot boots into **safe mode** (diagnostic commands only) instead of running with degraded memory; set `MEMORY_ALLOW_DEGRADED=1` or send `/safemode continue` to explicitly run with keyword-only memory.
- A Telegram bot token (from [@BotFather](https://t.me/BotFather)) and/or a Kazee Chat bot
- At least one authenticated coding-agent provider on the host machine for model turns (setup, doctor, status, and web configuration also work with none installed)
- (Optional) [whisper.cpp](https://github.com/ggerganov/whisper.cpp) + ffmpeg for voice notes

## Quick Start

### 1. Install and authenticate coding-agent providers

For model-bearing turns, authenticate **at least one** of these on the machine where Open Claudia will run.

**Claude Code** (optional — at least one provider is required for model turns):

```bash
npm install -g @anthropic-ai/claude-code
claude                    # Opens browser to log in
claude --version          # Verify it works
```

**OpenAI Codex** (optional — at least one provider is required for model turns):

```bash
npm install -g @openai/codex
codex login               # Opens browser to authenticate
# Or from chat after Open Claudia is running: /codex_login
# If browser/device login cannot complete remotely: /codex_setup_token
codex --version           # Verify it works
```

Docker images include the Codex CLI. Direct npm installs still need optional provider CLIs installed on the host.

> **Important**: Claude Code can use macOS Keychain when you log in interactively, but a launchd/background bot may not be able to read that Keychain session. Open Claudia supports `CLAUDE_CODE_OAUTH_TOKEN` for non-interactive Claude runs. Prefer `/setup_token` then `/use_oauth_token` if chat shows Claude auth/keychain errors.

### 2. Install Open Claudia

```bash
npm install -g @inetafrica/open-claudia
```

### 3. Run setup

```bash
open-claudia setup
```

The setup wizard will:

1. Detect the Claude and Codex CLIs, plus ffmpeg and whisper, on your system
2. Report provider authentication status
3. Ask for your Telegram bot token and verify it
4. Generate a verification code — send it to your bot to prove your identity
5. Set your workspace path (default: `~/.open-claudia/Workspace`)
6. Create an encrypted vault for credentials
7. Optionally install as a background service (macOS launchd / Linux systemd)

If setup is interrupted, running it again resumes from the last completed step.

All configuration is stored in `~/.open-claudia/` — survives npm upgrades.

### 4. (Optional) Add Kazee Chat

Set `CHANNELS=telegram,kazee` plus `KAZEE_URL`, `KAZEE_BOT_TOKEN`, `KAZEE_BOT_USER_ID`, and `KAZEE_OWNER_USER_ID` in `~/.open-claudia/.env`, or run `/channel add kazee` from an existing chat and follow the wizard.

## Run

```bash
open-claudia start            # Start the bot (--web adds the web UI, --quick skips slow health checks)
open-claudia web              # Start with web UI for setup/config
open-claudia stop             # Stop the bot
open-claudia status           # Check if running (shows PID)
open-claudia health           # Run environment health checks (-v for detail)
open-claudia logs             # View recent logs
open-claudia auth             # Manage chat authorizations
```

If installed as a background service, the bot starts automatically on login and restarts on crash.

## Chat Commands

### Provider switching

| Command | Description |
|---------|-------------|
| `/backend` | Show the current provider with picker |

Each provider keeps its own persistent project session. Switching doesn't lose your place — you can go back and forth freely.

### Session management

The bot runs at the top-level workspace; there is no per-folder project selection.

| Command | Description |
|---------|-------------|
| `/new` | Start a fresh conversation |
| `/sessions` | List past conversations |
| `/continue` | Resume last conversation explicitly |
| `/compact` | Summarize conversation context now |
| `/compactwindow [<tokens> \| off \| default]` | Set the auto-compact token threshold |
| `/end` | End the current conversation |

When you select a project, the last conversation is automatically resumed. Tap "New conversation" to start fresh.

### Settings

| Command | Description |
|---------|-------------|
| `/model [<model>]` | Switch model for the selected provider |
| `/effort [<value>]` | Set a provider-supported effort level |
| `/budget [$N]` | Set max spend for the next task when supported (Claude Code) |
| `/plan` | Toggle read-only planning — Claude permission mode / Codex read-only sandbox |
| `/ask` | Toggle read-only Q&A through the selected provider's read-only mode |
| `/worktree` | Toggle a provider-managed isolated git branch when supported (Claude Code) |
| `/mode` | Switch between direct and agent bot modes |
| `/status` | Show current session, provider, capabilities, recall engine, and settings |
| `/usage` | Token usage and cost for this session |
| `/doctor` / `/requirements` | Check Node, CLI binaries/versions/auth, voice stack, and writable paths |

### Memory & skills

| Command | Description |
|---------|-------------|
| `/learn [<hint>]` | Capture the last piece of work into the matching context pack |
| `/skills [show\|remove <name>]` | List, show, or remove legacy learned skills |
| `/engine [classic\|discoverer]` | Switch the per-chat memory recall engine (default `discoverer`) |
| `/recall [on\|off]` | Toggle a per-turn "🧠 Recall this turn" debug line showing which packs/entities surfaced (and why, on discoverer) |
| `/soul` | View/edit assistant identity and personality |
| `/dreamsummary [on\|off]` | Toggle the post-dream memory summary in chat |

### Automation

| Command | Description |
|---------|-------------|
| `/cron [add\|remove ...]` | Manage scheduled tasks |
| `/vault [create\|get\|set\|remove\|lock]` | Manage encrypted credentials (password required) |

### Team & access

| Command | Description |
|---------|-------------|
| `/auth [list \| revoke <chatId>]` | Request access; owner lists/revokes |
| `/people [show\|note\|link\|unlink\|add\|remove ...]` | Manage the team roster |
| `/intros [approve\|reject <id>]` | Approve/reject introductions from unknown chats |
| `/link [<chat-id>] <email-or-id>` | Link a chat to a canonical user id |
| `/links` | List identity links (owner) |
| `/whoami` | Show your canonical user id |
| `/channel [add kazee \| remove <id>]` | Add or remove channels |

### Claude Code auth

| Command | Description |
|---------|-------------|
| `/auth_status` | Reports redacted Claude auth status and whether an OAuth token is configured |
| `/login` | Starts a Claude login flow, sends the URL/code, accepts paste-back codes (`/auth_code <code>`, `/cancel_auth`). Connected providers show a **🔁 Switch account** button that signs out and starts a fresh login |
| `/logout [claude\|codex]` | Full sign-out: clears the CLI credential store **and** (for Claude) the bot-held OAuth token, then offers a sign-in button. Without an argument, shows provider buttons |
| `/setup_token` | Runs `claude setup-token`; the resulting OAuth token is stored without echoing it |
| `/use_oauth_token [<token>]` | Stores `CLAUDE_CODE_OAUTH_TOKEN` for non-interactive runs; the message is deleted when possible. Without an argument, send the token as the next message |
| `/clear_oauth_token` | Removes the stored OAuth token only (`/logout claude` for a full sign-out) |

Tokens are redacted from chat output and logs.

### Codex auth

| Command | Description |
|---------|-------------|
| `/codex_auth_status` | Reports redacted Codex auth status/version |
| `/codex_login` | Starts `codex login --device-auth` and relays the URL/device code |
| `/codex_setup_token [<key>]` | Secure paste mode for an OpenAI API key (message deleted, never echoed) |
| `/cancel_codex_auth` | Cancels a pending Codex auth flow |

### System

| Command | Description |
|---------|-------------|
| `/version` | Show current running version |
| `/upgrade` | Upgrade to latest version and restart (includes a post-upgrade doctor summary) |
| `/downgrade [version]` | Roll back to the previously-running version (or a specific one) |
| `/safemode` | Show safe-mode status and ways out; `/safemode continue` boots normally despite a missing memory substrate |
| `/restart` | Restart the bot |
| `/dashboard` | Get a one-time login link to the web dashboard |
| `/stop` | Cancel a running task |
| `/help` | Show all commands |

### Cluster control

Available only when the bot runs as an AgentSpace-provisioned pod (the broker credentials `AGENTSPACE_API_URL` and `AGENTSPACE_POD_TOKEN` are present). Off this network the command replies that it isn't available and does nothing. Owner-gated; every operation is authenticated, capability-checked, and audited by the broker, and confined to the bot's own deployment.

| Command | Description |
|---------|-------------|
| `/cluster status` | Deployment readiness/phase |
| `/cluster logs [n]` | Tail the last n container log lines |
| `/cluster restart` | Rollout restart (pulls latest image) |
| `/cluster start` / `/cluster stop` | Scale to 1 / 0 replicas |
| `/cluster scale <0\|1>` | Stop (0) or start (1) |
| `/cluster sync` | Re-apply the deployment manifest |

## Memory & Long-Term Context

Open Claudia layers three memory systems on top of provider-native sessions:

**Context packs** (`~/.open-claudia/packs/<dir>/PACK.md`) are living per-topic documents with four sections: *Stance* (how to think about the topic — your preferences and hard rules), *Procedure* (verified how-to steps), *State* (where work stands now), and *Journal* (a dated one-line log of past sessions). Incoming messages are matched against packs (FTS5, field-weighted so a stray word can't drag a pack in) and hits are injected into the agent's context — mention a project anywhere and the assistant picks up its train of thought, decisions, and history without you re-explaining. After every substantial turn, a background reviewer on a cheap model updates the relevant pack (or creates one for a genuinely new topic). Every change is announced in chat.

**Entity memory** (`~/.open-claudia/entities/<slug>.md`) works the same way for the people, places, projects, orgs, and systems you mention — who they are, current truth, and a dated observation log. Mentioning a name injects its note.

**Recall engines** — how packs and entities get matched and surfaced is pluggable per chat via `/engine` (or the `RECALL_ENGINE` env default). **discoverer** (the default) runs a typed-edge graph over the corpus (`parent`/`governed-by`/`related` edges with weights in `recall-graph.db`): a pre-gate that skips recall on trivial turns → FTS seeding → spreading activation across the graph (1–2 hops — auto-pulls cross-cutting concerns the query never named) → a walker that reads each candidate and returns the genuinely-relevant set with one-line why-bullets (fail-open to keyword seeds, so it never recalls worse than classic). The walker is one small utility-model call per non-trivial turn (typically fractions of a cent; pin the model with `RECALL_DISCOVERER_MODEL`, and trivial/short turns skip it entirely via the pre-gate). Edges form structurally from pack `parent` frontmatter and `[[links]]`, and strengthen via Hebbian co-use when the agent opens packs together (📖); weights decay over time. **classic** is the explicit opt-out: keyword FTS plus a relevance judge with headline injection, no graph and no walker. Inspect with `open-claudia recall-stats` and `open-claudia recall graph [--sync]`, or flip on `/recall` to watch — per turn — which packs/entities surfaced and why, right in the chat. Switch any time with `/engine classic`.

**Dream consolidation** — while the per-turn reviewer takes quick notes, *dream* is the slow overnight pass (default 4am, through the configured provider's high model tier): it merges packs that drifted into the same topic, builds parent/sub pack trees with umbrella summaries, tightens descriptions and tags so the router matches with less noise, dedupes entities, cross-links notes, and tends the recall graph (structural sync, weight decay, orphan prune). The pass is *evidence-grounded*: per-turn recall telemetry (what surfaced, what got kept, what the agent actually opened) feeds the prompt, so archive/merge calls rest on usage numbers rather than vibes. Most nights run as cheap *deltas* — full pack bodies only for what changed since the last dream plus graph neighbours and pre-computed merge candidates; a full-corpus sweep runs every `DREAM_FULL_SWEEP_DAYS` (30). Deterministic phases run even if the model call fails: journal backfill dedupe, weakening of graph nodes that keep arriving but never get kept, co-rescue edge reinforcement, episodic index tending, and a memory-health report (rescue rate, noise, latency, spend) in the morning chat summary. Dream may also tune one bounded recall knob per night (`recall-tuning.json`) — every change is checked against the next window's health and auto-rolled-back if rescue drops or noise rises; env pins always win. Anything merged away is backed up under `~/.open-claudia/backup/dream-<stamp>/` first, and each report and morning summary records the provider/model used. Configure with `DREAM_CRON`, `DREAM_TIER`, `DREAM_PROVIDER`, or a provider-specific `DREAM_MODEL_CLAUDE` / `DREAM_MODEL_CODEX`; disable with `DREAM=off`.

**Personality** — your `soul.md` holds identity and hard rules; `~/.open-claudia/persona.md` holds the voice on top — tone, quirks, emoji habits. It feeds into the system prompt and the dream pass may evolve it gently (bounded, backed up, announced). Edit it directly any time.

**Transcript index** — every project conversation is logged (redacted) to JSONL outside the repo and indexed in SQLite FTS5, giving the agent ranked search over your full history.

```bash
open-claudia pack list|show <dir>|match "<text>"|migrate|remove <dir>|reindex
open-claudia entity list|show <slug>|match "<text>"|note <name> "<text>"|remove <slug>|reindex
open-claudia dream [--dry-run]               # run the consolidation pass now
open-claudia recall-stats                    # discoverer-engine metrics summary
open-claudia recall graph [--sync]           # recall-graph node/edge stats; --sync rebuilds structural edges
open-claudia kpi [--json|--html|--knobs]     # harness KPIs by version+model; --html writes a chart report, --knobs shows dream-tuned knob state
open-claudia transcript-search "<query>"     # alias: ts; --all for every project
open-claudia transcript-window "<pattern>"   # alias: tw; hits with surrounding turns
```

`pack migrate` folds legacy `~/.claude/skills` into packs (originals backed up, never deleted) — run it once after upgrading from a pre-2.5 version.

When a conversation grows past the auto-compact threshold, the bot summarizes it proactively: the full brief is archived to `~/.open-claudia/briefs/` and a condensed version seeds the fresh session, so long-running work never hits a context wall.

## Background Work

The agent can schedule its own future work — these survive bot restarts:

```bash
open-claudia schedule-wakeup <30s|5m|2h|1d|ISO-date> "<prompt>"   # one-shot; resumes the session
open-claudia cron-add "<5-field cron>" "<prompt>"                 # recurring
open-claudia cron-list / cron-remove <id>
```

A persistent per-channel task tree tracks multi-turn work (plans with subtasks; completed items are removed automatically):

```bash
open-claudia task plan "<title>" "<step 1>" "<step 2>" [--description "..."]
open-claudia task add|list|start <id>|done <id>|remove <id>
```

And for side research that shouldn't pollute the main conversation:

```bash
open-claudia agent "<prompt>" [--role "<role>"]   # throwaway sub-agent, output on stdout
```

## Team & Cross-Channel

The setup owner is automatically authorized. To add more users:

- **From chat**: unknown users who message the bot go through an intro flow — the owner gets an approve/reject prompt (`/intros`). Or they send `/auth` for a direct request.
- **From the terminal**: `open-claudia auth` shows authorized chats and pending requests.

Each chat defaults to `telegram:<chatId>` as its user id. Link chats to a canonical id to share sessions and history across channels:

```text
/link sumeet@example.com
/whoami
```

The bot keeps a people roster (`/people`, or `open-claudia people list|show|note|link`) and can relay messages between team members with provenance and an audit trail:

```bash
open-claudia send-to --person "<name>" "<message>"
open-claudia recent --person "<name>" [--limit 20]   # read recent activity from another chat
```

Replies and write/destructive actions for external people pass through an independent, read-only relationship guard. The guard can use Claude or Codex (`ENFORCER_PROVIDER`) and fails closed: malformed output, timeout, or total provider failure holds the action for owner approval. A fallback is used only when explicitly listed in `PROVIDER_FALLBACKS`; audit records identify the provider/model that judged the action without storing the mandate or proposed content.

## Provider Comparison

| | Claude Code | OpenAI Codex |
|---|---|---|
| Binary | `claude` | `codex` |
| Session flag | `--resume <id>` | `exec resume <id>` |
| Auth | `claude auth` | `codex login` |
| Plan mode | Yes (`--permission-mode plan`) | Yes (read-only sandbox) |
| Budget control | Yes (`--max-budget-usd`) | No |
| Effort levels | Native (`low` through `max`) | Native (`minimal` through `xhigh`) |
| Worktree | Yes (`--worktree`) | No |
| Model switching | Yes | Yes (`--model`) |
| Partial text streaming | Yes | No; normalized progress and final events only |

Both providers output structured events which Open Claudia normalizes for progress, usage, tools, sessions, and terminal results.

Unsupported optional controls return a provider-specific explanation and do not change saved settings. Mandatory safety controls are different: Open Claudia configures each provider's native pre-tool hook, and refuses unrestricted execution if that policy cannot initialize.

## Utility provider policy

Background intelligence—sub-agents, recall, memory review, dream/introspection, and the external-person enforcer—uses one provider-selection policy. A per-purpose override is checked first, then `UTILITY_PROVIDER` (default `active`), the active foreground provider when a chat exists, and `DEFAULT_PROVIDER` for global jobs. Providers translate the neutral `low`, `medium`, and `high` tiers to their own models; exact per-provider model overrides remain available.

Foreground turns never silently fall back to a different provider. Utility work uses `PROVIDER_FALLBACKS` only when the operator explicitly supplies an ordered list, starts a fresh provider session, and records the provider/model used. The relationship enforcer may try that configured list, but total failure always fails closed and asks the owner to decide.

## Provider session semantics

Conversation identity is the tuple of canonical user, project, provider, and native session ID. Claude Code and Codex histories and active pointers stay separate: switching providers restores only that provider's project session and never passes one provider's native session ID to another. Session-history entries are provider-tagged; ambiguous legacy records remain visible but non-selectable.

Model, effort, budget, permission mode, and worktree settings are stored per provider. `/new` clears only the active provider's conversation pointer, while `/end` ends the current conversation (resetting to the top-level workspace) without deleting history. Compaction and scheduled jobs capture an immutable provider/session tuple; an explicitly configured scheduled fallback starts fresh from a provider-neutral archived brief.

## Provider migration and rollback

Upgrades from a release with the removed third provider snapshot `state.json`, `sessions.json`, `jobs.json`, legacy cron sources, and their relevant backups before activating provider-aware schemas. Removed-provider selections, histories, and jobs become non-selectable or disabled archives; they are never reassigned to Claude Code or Codex. See [Provider migration snapshots and rollback](docs/PROVIDER_MIGRATION.md) before upgrading or restoring an older runtime.

## Sending Files

Send any file to the bot — PDFs, code files, documents, images. Files are saved to `~/.open-claudia/files/` with their original names. The agent reads the file and responds based on content.

Add a caption to give the agent specific instructions:
- Send a PDF with caption "summarize the key findings"
- Send a code file with caption "find bugs in this"
- Send a screenshot with caption "implement this design"

The agent can also send files back — documents, photos with inline previews, and voice clips — directly from within a task.

## Voice Notes

Requires [whisper.cpp](https://github.com/ggerganov/whisper.cpp) and ffmpeg:

```bash
# macOS
brew install whisper-cpp ffmpeg

# Linux (Ubuntu/Debian)
sudo apt install ffmpeg
# Build whisper.cpp from source: https://github.com/ggerganov/whisper.cpp
```

Voice notes are transcribed locally — nothing sent to external services. On macOS, replies to voice messages come back as voice notes too.

## How It Works

```
Phone (Telegram / Kazee) --> Bot (Node.js) --> Claude Code CLI    --> Your codebase
                                           --> OpenAI Codex CLI  -->
                         <--               <--                   <--
```

The bot spawns the selected provider CLI in headless mode for each message, normalizing its JSONL output back to the chat. It maintains provider-native context through the provider adapter and passes the same Open Claudia prompt/context contract to either CLI.

The appended system prompt is byte-stable within a session to maximize Anthropic prompt-cache hits; per-turn state (vault status, pending tasks, matched packs/entities) rides the user message instead, where it is always uncached anyway.

Open Claudia does not summarize one provider's native session into another during switches; instead it records a redacted project transcript outside the repo and injects a small pointer telling fresh/switched sessions to search it only if needed.

### Provider credential boundary

Native Claude and Codex child processes receive allowlisted process variables plus explicitly configured `AGENT_ENV_PASSTHROUGH` entries. Open Claudia removes control-plane, keyring, and all provider credential keys before adding back only the selected provider's credentials and auth/config root. This is environment isolation, not OS containment: a native same-UID process retains whatever filesystem access that operating-system user has, including access to readable CLI auth stores and configuration files.

## Configuration Files

All stored in `~/.open-claudia/`:

| File | Purpose |
|------|---------|
| `.env` | Tokens, workspace path, binary paths, channel config |
| `auth.json` | Authorized users and pending requests |
| `identities.json` | Channel-to-canonical-user mappings |
| `people.json` / `intros.json` | Team roster and pending introductions |
| `vault.enc` | Encrypted credential store |
| `soul.md` | Assistant identity and hard rules (editable via `/soul`) |
| `persona.md` | Assistant voice and quirks (feeds the system prompt; evolved gently by dream) |
| `crons.json` / `jobs.json` | Recurring crons and one-shot wakeups |
| `tasks/` | Persistent per-channel task trees |
| `packs/` | Context packs (living topic documents) + FTS index |
| `entities/` | Entity notes (people/places/projects) + FTS index |
| `sessions.json` | Per-project conversation history |
| `state.json` | Current provider/project state and provider-scoped settings (survives restarts) |
| `transcripts/` | Redacted project-scoped JSONL transcripts + FTS index |
| `briefs/` | Archived full compaction briefs |
| `audit.log` | Relay/intro/auth audit trail |
| `bot.log` | Bot logs |
| `files/` | Files received from chat |
| `media/` | Temporary media (voice notes, photos) |
| `backup/` | Backups (skills folded by `pack migrate`; packs/entities merged away by dream) |

### Environment Variables (.env)

| Variable | Required | Description |
|----------|----------|-------------|
| `TELEGRAM_BOT_TOKEN` | Yes* | Bot token from BotFather |
| `TELEGRAM_CHAT_ID` | Yes* | Comma-separated authorized chat IDs |
| `CHANNELS` | No | Channels to start: `telegram`, `kazee`, or `telegram,kazee` (default `telegram`) |
| `KAZEE_URL` / `KAZEE_BOT_TOKEN` / `KAZEE_BOT_USER_ID` / `KAZEE_OWNER_USER_ID` | Kazee only | Kazee Chat connection |
| `WORKSPACE` | Yes | Path to your projects directory |
| `CLAUDE_PATH` / `CODEX_PATH` | No | Optional paths to provider CLIs (auto-detected if in PATH) |
| `DEFAULT_PROVIDER` | No | Foreground default (`claude` or `codex`); blank deterministically chooses the first compatible provider |
| `UTILITY_PROVIDER` | No | Utility default (`active`, `claude`, or `codex`); defaults to the active foreground provider |
| `MEMORY_PROVIDER` / `RECALL_PROVIDER` / `SUBAGENT_PROVIDER` | No | Optional per-purpose utility-provider overrides |
| `CLAUDE_CODE_OAUTH_TOKEN` | No | OAuth token for non-interactive Claude runs (set via `/use_oauth_token`) |
| `AGENT_ENV_PASSTHROUGH` | No | Comma-separated project environment keys to pass to provider children; reserved provider/control/keyring keys are always filtered and re-added only by the selected provider |
| `CLAUDE_MODEL` / `CODEX_MODEL` | No | Optional default model for the matching provider |
| `AUTO_COMPACT_TOKENS` | No | Auto-compact threshold in tokens (also settable via `/compactwindow`) |
| `USAGE_ALERT_CONTEXT_TOKENS` | No | Alert when one completed turn's context tokens exceed this ceiling (default `120000`, `off` disables) |
| `USAGE_ALERT_RATE_MULTIPLIER` | No | Alert when the latest context-token rate exceeds the recent baseline by this multiple (default `1.75`, `off` disables) |
| `USAGE_ALERT_BASELINE_TURNS` / `USAGE_ALERT_MIN_BASELINE_TURNS` / `USAGE_ALERT_COOLDOWN_MS` | No | Tune token-rate baseline size, minimum sample size, and alert cooldown |
| `MEMORY_RECALL_MAX_CHARS` | No | Hard cap for auto-injected pack/entity memory per turn (default `9000`, `off` disables auto recall injection) |
| `RECALL_ENGINE` | No | Default recall engine when a chat hasn't set one via `/engine` (`classic` or `discoverer`, default `discoverer`) |
| `RECALL_GRAPH_DB` / `RECALL_METRICS` | No | Override the discoverer graph DB path; `off` on metrics disables per-turn recall logging |
| `RECALL_WALKER_MAX_CANDIDATES` | No | Cap on candidates sent to the discoverer's walker judge per turn (default `14`; dream-tunable 8–20, env pins it) |
| `RECALL_EPISODES` / `RECALL_EPISODE_LIMIT` | No | `off` disables episodic transcript candidates in recall; limit caps transcript hits per turn (default `3`; dream-tunable 1–5) |
| `RECALL_SEEDS_TIER_MAX_WORDS` | No | Turns at or under this word count take the fast seeds-only recall path (default `4`; dream-tunable 2–6) |
| `RECALL_DECAY_HALF_LIFE_DAYS` | No | Half-life for recall-graph edge decay during dream tending (default `60`; dream-tunable 10–90) |
| `RECALL_CASCADE` / `RECALL_CASCADE_SHADOW_RATE` | No | `off` disables the deterministic keep/drop cascade before the walker judge; shadow rate is the fraction of cascade verdicts also judged to audit agreement (default `0.1`) |
| `PROJECT_TRANSCRIPTS` | No | Enable redacted project transcripts (default `true`) |
| `TRANSCRIPT_MAX_ENTRY_CHARS` | No | Max chars per transcript entry (default `12000`) |
| `TRANSCRIPTS_DIR` / `PACKS_DIR` / `ENTITIES_DIR` | No | Override storage directories |
| `PACK_REVIEW` | No | `off` disables the post-turn pack/entity reviewer (default on) |
| `PACK_REVIEW_MODEL` | No | Model for the reviewer (default `haiku`) |
| `PACK_MATCH_THRESHOLD` / `ENTITY_MATCH_THRESHOLD` | No | Router match score thresholds (default `2`) |
| `DREAM` | No | `off` disables the nightly memory consolidation pass (default on) |
| `DREAM_CRON` | No | Schedule for the dream pass (default `0 4 * * *`) |
| `DREAM_PROVIDER` | No | Provider for dream and introspection (`claude` or `codex`); otherwise scheduled work resolves through `DEFAULT_PROVIDER` |
| `DREAM_MODEL_CLAUDE` / `DREAM_MODEL_CODEX` | No | Exact per-provider dream model override; legacy `DREAM_MODEL` remains a Claude-only compatibility alias |
| `DREAM_TIER` | No | Provider-owned model tier for the dream pass: `low`, `medium`, or `high` (default) |
| `DREAM_FULL_SWEEP_DAYS` | No | Days between full-corpus dream sweeps; other nights are cheap deltas over recently-touched packs (default `30`) |
| `ENFORCER_PROVIDER` | No | Provider for the independent external-person guard (`claude` or `codex`) |
| `ENFORCER_MODEL_CLAUDE` / `ENFORCER_MODEL_CODEX` | No | Exact per-provider guard model override; legacy `ENFORCER_MODEL` remains a Claude-only compatibility alias |
| `PROVIDER_FALLBACKS` | No | Explicit ordered utility fallback list (for example `codex`); the enforcer never invents an unconfigured fallback |
| `PERSONA_FILE` | No | Override the persona file location |
| `WEB_UI` / `WEB_PORT` / `WEB_PASSWORD` | No | Web UI toggle, port, and password |
| `WHISPER_CLI` / `WHISPER_MODEL` | No | whisper.cpp binary and model for voice notes |
| `FFMPEG` | No | Path to ffmpeg binary |

\* Required for the Telegram channel.

## Background Service

### macOS (launchd)

Set up during `open-claudia setup`, or manually:

```bash
# The setup wizard retains the legacy-compatible service id com.claude-telegram-bot
# To manage:
launchctl load ~/Library/LaunchAgents/com.claude-telegram-bot.plist
launchctl unload ~/Library/LaunchAgents/com.claude-telegram-bot.plist
```

**Important**: If a provider CLI is installed in a non-standard location, make sure that path is included in the launchd plist's `PATH` environment variable or configure its explicit path.

### Linux (systemd)

```bash
# The setup wizard creates /etc/systemd/system/claude-telegram-bot.service
# To manage:
sudo systemctl enable claude-telegram-bot
sudo systemctl start claude-telegram-bot
sudo systemctl status claude-telegram-bot
```

The systemd unit name is retained as a legacy service identifier so upgrades manage the existing unit instead of installing a duplicate; it does not select the coding-agent provider.

## Auto-Updates

The bot checks npm for new versions every 5 minutes. When an update is available, you get a chat notification. Send `/upgrade` to update — the bot installs the new version, restarts, runs a doctor check, and notifies you it's back.

For direct npm installs, `/upgrade` updates Open Claudia itself and does not install optional provider CLIs such as Codex. Container deployments should roll out a new Docker image when bundled CLI tools change.

If a release goes bad, `/downgrade` rolls back to the previously-running version (boot history remembers what ran before), and `/downgrade <version>` targets any published release. If the bot ever enters a boot crash loop (3 consecutive boots dying before stable uptime), it comes up in **safe mode** — adapters and diagnostic commands stay alive so you can `/doctor`, `/upgrade`, `/downgrade`, or `/safemode continue` from chat instead of being stranded with a dead process.

## Cron Jobs

Schedule recurring tasks:

```
/cron add "0 9 * * 1-5" "Morning standup: summarize git changes since yesterday"
/cron add "0 18 * * *" "Git digest: what changed today?"
/cron add "*/30 * * * *" "Health check: verify the API is responding"
```

Presets available via `/cron` menu. The agent can also schedule its own jobs with `open-claudia cron-add` / `schedule-wakeup` (see Background Work).

## Vault

Store sensitive credentials encrypted:

```
/vault                    # Unlock vault (prompts for password)
/vault set AWS_KEY xxx    # Store a credential
/vault remove AWS_KEY     # Remove a credential
/vault lock               # Lock vault
```

The agent can read vault credentials when unlocked — useful for deployment scripts and API calls.

## License

MIT
