Overview
~/.comis/ is the single directory where Comis stores all runtime state: your config, secrets, conversation memory, logs, and the pm2 supervisor file. It is created automatically the first time you run comis init or start the daemon.
Directory layout
Some entries only appear under specific conditions.
secrets.db— created only whenSECRETS_MASTER_KEYis set andsecurity.storage: encrypted(the default).auth-profiles.json,mcp-tokens/,secrets.json— only present whensecurity.storage: file. Inencryptedmode, OAuth profiles and secrets live insecrets.dbtables instead..daemon.lock— present only while the daemon is running. Safe to delete when the daemon is stopped (it will be recreated on the next start).daemon.console.log— present only when the daemon was launched by the CLI (thecomis initwizard’s start step orcomis daemon start). Under systemd the process output goes to the journal instead, and under pm2 to~/.pm2/logs/— so this file is absent in those setups.broker.sock— present only when the credential broker is active (executor.broker.enabled: trueinconfig.yaml). Ephemeral — deleted and recreated on each daemon start.ecosystem.config.js— created only bycomis pm2 setup.- Named workspaces like
workspace-myagent/— appear only when you define more than one agent.
File-by-file reference
config.yaml
Your main configuration file. The daemon reads it at every startup. You edit this directly or through comis config set.
Written by: comis init wizard, or you manually.
Safe to delete? No. Without it the daemon will not start.
config.last-good.yaml
A copy of config.yaml snapshotted after every successful daemon startup. If the daemon crashes on boot, this file lets you roll back.
Written by: the daemon automatically, after logging “Comis daemon started”.
Safe to delete? Yes. The next successful start re-creates it. You lose the ability to roll back until then.
To restore manually:
config.local.yaml
Optional second config file loaded after config.yaml. Values here override the main file. Useful for machine-specific settings you don’t want in version control.
Written by: you, manually.
Safe to delete? Yes. The daemon falls back to config.yaml alone.
.env
Secret environment variables — LLM API keys, channel tokens, SECRETS_MASTER_KEY. The daemon loads this file before anything else, then scrubs the values from process.env so child processes cannot inherit them.
Written by: comis init or you manually.
Safe to delete? Only if you have all credentials stored in secrets.db or injected via environment instead. Deleting it means the daemon will not have access to any keys defined here.
memory.db
The main SQLite database. It stores conversation sessions, long-term memory entries, delivery queue state, observability rows, DAG context engine tables, embedding cache, and more. This is the most important file in the data directory.
The observability rows live in the obs_diagnostics table, grouped by a category label. Among them, model_health is a one-shot diagnostic recorded once per boot that captures the daemon’s load-level recall signals — whether an embedding provider is available, whether the GGUF reranker loaded, and whether the reranker model is present on disk. It carries booleans only (no model paths, no secrets) and lets the fleet health lens explain why recall was degraded on a given daemon without grepping the log.
config_posture is likewise a one-shot snapshot recorded once per boot, capturing the daemon’s security posture — whether the gateway is running without TLS, the per-family counts of stranded secrets (credentials left in the inactive store that the active security.storage mode cannot reach), and a canary-fallback aggregate (how many agents fall back to deterministic canary tokens because CANARY_SECRET is unset). It records counts and closed labels only — never a secret value — so the fleet health lens can surface a TLS-off / stranded-secret / canary posture without opening the log.
LCD Store — Durable Conversation History
memory.db also contains the LCD store: the durable, lossless conversation history. Three layers work together, each with a distinct durability contract:
| Layer | Tables | Durability |
|---|---|---|
| LCD store | lcd_messages, lcd_message_parts, lcd_context_items, lcd_summaries | Durable — the truth. Every turn is persisted verbatim (auto-condensed past 75%). Survives daemon restarts, redeploys, and JSONL deletions. |
| RAG memory | memory_* | Durable. Distilled facts learned from conversations. Cleared per-session via comis sessions reset --memory (deletes paired + LCD-distilled memories by source_session_key and unlinks consolidated observations; --purge-derived also purges derived observations). |
| SDK session JSONL | ~/.comis/workspace/sessions/.../<key>.jsonl | Disposable — the SDK’s per-session working transcript. Routinely deleted by the operator (housekeeping) and wiped by comis sessions reset. |
The SDK session JSONL is disposable. Deleting it directly (for any reason — operator housekeeping,
rm, daemon restart) is always treated as “continue”: the LCD store keeps its full history and appends the fresh transcript as a continuation. The daemon cannot distinguish disk-space housekeeping from a deliberate reset, so it never infers forget from a file deletion — it always continues. To perform an explicit reset, use comis sessions reset which clears both layers atomically.sessions reset clears two layers atomically: the LCD lossless-store history (dag mode) and the daemon sessionStore working transcript (both modes). A follow-up turn has no prior context regardless of which context engine the session uses.
See CLI Reference for the full command reference.
Written by: the daemon continuously during operation.
Safe to delete? Deleting it erases all conversation history, stored memories, pending deliveries, and cached embeddings. The daemon will recreate an empty database on next start, but you lose all data permanently.
secrets.db
An encrypted SQLite database for secrets managed with comis secrets set. Each value is encrypted with AES-256-GCM using the key in SECRETS_MASTER_KEY. Only created when that variable is set.
Written by: comis secrets set and the daemon on startup.
Safe to delete? Only if you have not stored any secrets here, or you have them backed up elsewhere. Deleting it with a valid master key means those secrets are gone.
ecosystem.config.js
The pm2 process definition, generated by comis pm2 setup. It tells pm2 where the daemon binary lives, what environment to pass (COMIS_CONFIG_PATHS), and restart behavior.
Written by: comis pm2 setup, one time.
Safe to delete? Yes, if you re-run comis pm2 setup afterward. pm2 will not be able to start the daemon until you do.
logs/daemon.log
The daemon’s own structured JSON log, written via pino-roll. The live file always carries a numeric index — daemon.1.log on a fresh boot, advancing to daemon.2.log, … when the current file reaches 10 MB (configurable via daemon.logging.maxSize and daemon.logging.maxFiles); pino-roll never writes the bare daemon.log name, so a daemon.log you see in the directory is a stale artifact, not the live log. The newest daemon.N.log is the file to tail; aged siblings are gzipped to daemon.N.log.gz by the startup rotation sweep (the sweep never touches the newest uncompressed indexed file). This is the canonical application log — leveled lines with traceId, agentId, durationMs, etc. — and the file you parse to diagnose behaviour. The base path is set by daemon.logging.filePath (default ~/.comis/logs/daemon.log).
Written by: the daemon continuously.
Safe to delete? Yes. The daemon creates a new file on next start. You lose historical log data. Under pm2, logs are also captured to ~/.pm2/logs/ as a separate copy.
daemon.console.log
The raw stdout/stderr of the detached daemon process, captured by the CLI that launched it. Distinct from logs/daemon.log: it is not structured and not written by the daemon’s logging subsystem — it lives at the data-dir root alongside daemon.pid/.daemon.lock as a process-lifecycle artifact. Its value is capturing output that the structured logger never sees: early-boot progress (e.g. embedding-model download), native-library warnings, and FATAL: Bootstrap failed crashes that exit before the logger is configured. comis daemon logs tails this file (override with COMIS_LOG_PATH).
Written by: the comis init wizard’s “start daemon” step and comis daemon start. Absent under systemd (output → journal) and pm2 (output → ~/.pm2/logs/).
Safe to delete? Yes. Recreated on the next CLI launch.
traces/
Per-session JSONL execution traces, rotated at 5 MB per file (3 files kept by default). Controlled by daemon.logging.tracing. Each agent can override the output directory in its own config block.
Written by: the daemon on each LLM call (when tracing is enabled).
Safe to delete? Yes. The daemon creates new trace files as needed.
workspace/ and workspace-<agentId>/
Each agent gets a dedicated workspace directory. The default agent uses workspace/; additional named agents get workspace-<agentId>/. Inside each workspace:
- Agent identity files (
AGENTS.md,SOUL.md,USER.md,IDENTITY.md) - A
.scheduler/subdirectory withcron-jobs.jsonand execution logs - A
skills/subdirectory for agent-specific prompt skills - Subdirectories seeded by Comis:
projects/,scripts/,documents/,media/,data/,output/
agents/
Holds per-agent RPC state such as subagent result files written during multi-agent graph execution.
Written by: the daemon during subagent runs.
Safe to delete? Yes, between runs. Active runs may be disrupted.
background-tasks/
Persisted state for long-running background tasks promoted out of the LLM execution loop. Each task is a small JSON file.
Written by: the daemon when background tasks are created or updated.
Safe to delete? Yes, when no tasks are running. The daemon will lose track of any in-progress background work.
identity/device.json
An Ed25519 key pair that uniquely identifies this Comis installation. Generated on first startup. Used for device-level signing. Stored with mode 0o600.
Written by: the daemon on first startup (if it does not exist).
Safe to delete? Technically yes, but the device will get a new identity on next start. Any device-pairing records that reference the old key will become invalid.
devices/
Paired-device records, written when another Comis installation pairs with this one. Each file is a small JSON record signed against the device identity above.
Written by: the daemon on pairing.
Safe to delete? Yes. The pairing is invalidated and the other side will need to re-pair.
dead-letters.jsonl
Append-only JSONL of announcement-delivery failures that exhausted in-process retries (channel down, bot blocked, etc.). The delivery system replays these on provider recovery and expires entries after one hour. Only created when at least one announcement has been dead-lettered.
Written by: the announcement delivery subsystem.
Safe to delete? Yes. Pending re-deliveries are dropped; entries auto-expire after one hour anyway.
.daemon.lock
The daemon acquires this exclusive lock (O_EXCL) at startup to prevent two daemon processes from running against the same data directory simultaneously. If the file is present when the daemon starts, it attempts stale-lock recovery (opens the file, checks whether the recorded PID is still running, and removes the stale lock if not).
Written by: the daemon at startup.
Safe to delete? Yes — but ONLY when you are certain the daemon is stopped. Deleting this file while the daemon is running will break the lock invariant and may allow a second daemon instance to start.
To check if the lock is stale:
auth-profiles.json (file mode only)
Stores OAuth profiles (access and refresh tokens) when security.storage: file is configured. Each profile is a JSON entry identified by provider and email. The file is written atomically (tmp then rename) with mode 0o600.
Written by: comis auth login and the daemon’s OAuth refresh path.
Safe to delete? Deleting this file removes all stored OAuth credentials — you will need to re-run comis auth login for each provider. Do not delete while the daemon is running.
Not present when: security.storage: encrypted (the default) — OAuth profiles are stored in the oauth_profiles table inside secrets.db instead.
mcp-tokens/ (file mode only)
A directory holding per-MCP-server OAuth token JSON files when security.storage: file is configured. Each file is named after the MCP server identifier. These are the access tokens issued during comis mcp login.
Written by: comis mcp login and the daemon’s MCP OAuth refresh path.
Safe to delete? Deleting the directory (or individual files) clears stored MCP OAuth tokens for those servers — you will need to re-run comis mcp login. Do not delete while the daemon is running.
Not present when: security.storage: encrypted — MCP tokens are stored in the mcp_credentials table inside secrets.db instead. Also not present in security.storage: env mode, where MCP OAuth login is unavailable (there is no writable MCP token store — comis mcp login fails with an actionable storage-mode error rather than writing a plaintext file).
secrets.json (file mode only)
The plaintext secret store when security.storage: file is configured. Contains named secret key-value pairs (for example, ANTHROPIC_API_KEY). Mode 0o600. Written atomically.
Written by: comis secrets set and the daemon’s secrets RPC path.
Safe to delete? Deleting this file removes all stored named secrets — every agent that depends on those secrets will fail to make API calls until the secrets are re-added. Do not delete while the daemon is running.
Not present when: security.storage: encrypted (the default) — named secrets are stored in the secrets table inside secrets.db instead.
broker.sock
A Unix domain socket created by the credential broker at daemon startup when the broker is active. Agents connect to this socket to get ephemeral single-use bearer tokens injected into their outbound HTTP requests, so the raw API key never enters the agent namespace.
Written by: the daemon at startup (when executor.broker is configured).
Safe to delete? The socket is ephemeral — deleted and recreated on each daemon start. If you see a stale broker.sock after a crash, you can delete it safely before restarting.
Not present when: executor.broker is not configured or the broker is disabled.
Backing up
To migrate to a new machine, back up these items:config.last-good.yaml, logs/, traces/, and ecosystem.config.js are machine-specific or regenerated and do not need to be included.
If you use
secrets.db, make sure you also have your SECRETS_MASTER_KEY stored somewhere safe. Without it the database is unreadable, even with the file itself.Custom location
By default Comis resolves config from~/.comis/config.yaml and ~/.comis/config.local.yaml. You can override this with COMIS_CONFIG_PATHS, a colon-separated list of absolute paths:
~/.comis/) is separately controlled by COMIS_DATA_DIR. See Configuration for a full reference.
Permissions
Comis enforces strict file modes on startup. If any of the following are wrong, the daemon corrects them automatically and logs what it changed:| Path | Required mode |
|---|---|
~/.comis/ (directory) | 0o700 (owner-only) |
config.yaml | 0o600 |
config.local.yaml | 0o600 |
.env | 0o600 |
secrets.db | 0o600 |
ecosystem.config.js | 0o600 (set by pm2 setup) |
identity/device.json | 0o600 |
