Skip to content

Paths and Files

This page describes every file and directory Chord reads or writes, and what is safe to delete.

Layer Default path Purpose
Config home $XDG_CONFIG_HOME/chord or ~/.config/chord Editable user config: providers, model pools, custom agents, custom skills, custom commands
State dir $XDG_STATE_HOME/chord or ~/.local/state/chord Durable runtime state you would not want to lose: sessions, exports, logs, project registry, worktrees
Cache dir $XDG_CACHE_HOME/chord or ~/.cache/chord Rebuildable runtime caches; can be deleted at any time

All three can be moved by environment variable, CLI flag, or config.yaml paths:; see Environment variables and CLI flags.

You edit these files. Treat them as source.

When the first-run setup wizard finishes, it prints the exact resolved paths for config.yaml and auth.yaml. This is especially useful when you launch with --config-home, CHORD_CONFIG_HOME, or on Windows where ~ is not the most discoverable form.

~/.config/chord/
├── config.yaml # global chord config
├── auth.yaml # API keys / OAuth tokens (chmod 600 recommended)
├── auth.state.json # machine-managed shared OAuth runtime state / quota cache
├── agents/ # global agent definitions (.md or .yaml)
├── commands/ # global custom slash commands (.md per command)
└── skills/ # global skills, each as <name>/SKILL.md

For the config.yaml schema, see Configuration & Auth. For agents, see Customization: Agents. For skills, see Customization: Skills. For custom slash commands, see Customization: Custom slash commands.

auth.state.json is a shared runtime cache for OAuth status, Codex quota snapshots, reset times, and warm-up timestamps. Chord manages it automatically; users normally should not hand-edit it. Deleting it is safe, but Chord will lose restart-stable cached quota ordering until warm-up repopulates it.

Chord writes here. Lose it and you lose history.

~/.local/state/chord/
├── sessions/
│ └── <project-key>/
│ ├── project.json # canonical-root, display-name, timestamps
│ └── <session-id>/ # one session
│ ├── main.jsonl
│ ├── traces/
│ │ └── llm-trace.jsonl # lightweight per-request LLM trace (always on)
│ └── … # additional session artifacts
├── projects/
│ └── <project-key>.json # registry pointer for cross-project lookup
├── exports/
│ └── <project-key>/ # `/export` output (markdown / JSON)
├── memory/
│ └── <project-key>/ # per-project memory machine state (see [Project Memory](/chord/project-memory/))
│ ├── extraction-checkpoints.json # per-session extraction coverage (rebuildable)
│ └── memory.lock # cross-process commit lock
├── worktrees/
│ └── <repo-id>/
│ └── <slug>/ # chord-managed git worktree (default location; `worktree.root` can move it)
└── logs/
├── chord.log # current log
├── chord.log.1 # rotated
├── chord.log.2 # rotated
├── chord-acp-mux-<pid>.log # `chord acp` frontend log
├── chord-acp-<session-id>.log # one per `chord acp` session
└── tui-dumps/ # `Ctrl+G` outputs

<session-id> is a 17-digit number (YYYYMMDDHHmmSSfff) generated from the local wall clock, so it reads as local date/time and stays safe as a directory or file name. The ID is an identifier and a rough creation-time hint, not the session ordering key. Session lists use the newer of two modification times, main.jsonl and an existing usage-summary.json. Chord stats these small per-session files instead of scanning full transcripts or maintaining a separate project-level index. Copying or restoring files can make filesystem times misleading, and activity that updates neither file may not affect the order.

Chord identifies a project by its canonical filesystem root, then derives a stable, sanitized key, for example HOME-projects-chord for ~/projects/chord. If two projects collide on the sanitized key, Chord appends an 8-character fingerprint to disambiguate. The full canonical root is stored alongside the key in project.json, so the registry stays unambiguous even when paths look similar.

Sessions and exports are keyed on this: that is how a fresh chord started in ~/projects/chord finds the previous session for the same project. Every checkout of a git repository resolves to the repository’s main-checkout key, so a chord-managed worktree shares its repository’s sessions instead of getting its own. The runtime cache is the exception: it is keyed on the checkout a session works in, so chord worktree remove can drop one checkout’s cache without touching another’s.

chord --worktree <name> creates a chord-managed git worktree under worktrees/<repo-id>/<slug>, outside the original repository by default; worktree.root can move it, and when the target directory is inside the repository Chord keeps a .gitignore in it so the checkouts stay out of git status. Every checkout of a repository resolves to the repository’s project key, so sessions and exports are shared by all of them while the runtime cache stays per checkout.

Keep the worktree root for chord’s own worktrees. When it lives inside the repository, that self-ignoring .gitignore hides whatever else you put there from git, and path evaluation treats every immediate child as a checkout root — so a repository-relative permission rule would resolve paths under a stray directory against that directory instead of the repository root.

Use chord worktree remove <name> to remove the working directory, its runtime cache, and its ownership metadata. The branch and the repository’s session history are kept: --delete-branch also deletes the branch (only if merged, unless --force is given), and --force also force-deletes a dirty worktree; see CLI: chord worktree. Manually deleting the worktree directory is not recommended; you would leave orphan registry entries that chord cleanup project would later flag.

Everything here is rebuildable; deleting it is safe at any time, at the cost of one re-warmup.

~/.cache/chord/
└── runtime/
└── session-cache/
└── <project-key>/
└── <session-id>/ # in-memory session snapshots, recovery state

When chord runs in a project for the first time, it ensures the project root has a .chord/ directory. This is the only chord directory that lives inside the user’s repository.

<project>/.chord/
├── config.yaml # project-level overrides (merged with global ~/.config/chord/config.yaml)
├── agents/ # project-level agents (override or extend global agents)
├── commands/ # project-level custom slash commands
├── skills/ # project-level skills
├── plans/ # user-visible planning documents
└── memory/ # detailed Memory records (see [Project Memory](/chord/project-memory/))
└── records/ # one immutable file per auto-extracted record

Project-level files have higher priority than global ones (same-name keys override). It is normal, and useful, to commit .chord/ into your repository so that team members share the same agent setup and slash commands. Memory records are ordinary project files: Chord does not stage or commit them, and you can keep them local via .gitignore or .git/info/exclude.

auth.yaml is never read from .chord/: credentials always live in ~/.config/chord/auth.yaml.

Use the project tree for content that describes how Chord should work in this project, or for user-visible artifacts that a team may review:

  • AGENTS.md contains repository instructions that applicable agents must follow.
  • .chord/config.yaml, .chord/agents/, .chord/commands/, and .chord/skills/ contain explicit project configuration and shared capabilities.
  • .chord/plans/ contains planning documents. Whether plans are committed is a project decision.
    • Planning documents for the planner → handoff workflow and topic/design documents both use the same naming convention: YYYYMMDD-<slug>.md (for example 20260903-session-key-isolation.md), where YYYYMMDD is the creation date and <slug> is a short descriptive name derived from the title. If a file with the same date and slug already exists (a later revision of the same topic), append -2, -3, and so on. Task-list plans are recognised by their ## Tasks body of ### N. items (a machine-readable format consumed by the execution handoff), not by their filename.
    • A document that replaces an earlier one declares it with a supersedes: <file> line near the top; move finished or superseded documents to plans/archive/ (archive files keep their original names).
  • .chord/notes/ holds human-readable working notes a session keeps for itself (findings, open-thread state) so long read-mostly sessions have a legal write target outside the tracked tree; whether notes are committed is a project decision. Name notes YYYYMMDD-<slug>.md so they sort and age visibly; keep them free-form and maintain no index; when a note’s conclusions are captured elsewhere, delete it or mark it superseded. Notes are not injected like MEMORY.md: nothing reads them unless the session opens the file, except for a bounded checkpoint header after a state_files reference.
  • Project-local Chord files should use paths relative to the project root when they refer to repository files, so the project remains portable when its directory moves.

Do not use .chord/ as a general runtime-state directory. Session transcripts, usage ledgers, recovery snapshots, project registry data, logs, locks, and other opaque runtime bookkeeping belong under the state directory or cache directory described above. Human-readable project artifacts may live in the project tree when direct editing, relative references, or portability requires it, but their Git and ownership semantics must be explicit. In particular, auth.yaml and other credentials must not be placed under the project tree.

The whole .chord/ directory is not automatically safe to commit or ignore. Project configuration and shared skills are commonly committed, while plans and any project-local private files should follow the repository’s own policy. Review untracked and ignored files before committing rather than assuming that every hidden project file is private.

File What it contains
<state-dir>/logs/chord.log Current run log (golog plain text)
<state-dir>/logs/chord.log.1 Previous rotation
<state-dir>/logs/chord.log.2 Older rotation
<state-dir>/logs/chord-acp-mux-<pid>.log chord acp frontend log (rotated the same way)
<state-dir>/logs/chord-acp-<session-id>.log One per chord acp session process
<state-dir>/logs/tui-dumps/ Ctrl+G snapshots for bug reports

Override the directory with --logs-dir <path> or CHORD_LOGS_DIR=<path>.

A typical log line looks like:

[I 2026-05-02 12:00:00 file:123 pwd=/path pid=1234 sid=20260502015258426] message key=value

Treat key-value fragments as human-readable text, not as a stable structured-logging schema.

Use chord cleanup rather than rm -rf: it knows which paths are safe and which would orphan registry entries.

Goal Command
See how big each layer is chord cleanup status
Free space from old sessions chord cleanup sessions --older-than 720h --yes
Reset the in-memory cache chord cleanup cache --yes
Trim log rotations chord cleanup logs --older-than 168h --yes
Remove orphan project entries chord cleanup project --yes
Remove a chord-managed worktree chord worktree remove <name>

All cleanup subcommands default to dry-run: without --yes they only list what would be removed. Full reference: CLI: chord cleanup.

Path Safe to delete?
~/.cache/chord/ Yes, anytime. Will be rebuilt on next start.
<state-dir>/logs/chord.log.1 and .2 Yes. Current chord.log is in use; prefer chord cleanup logs to avoid touching live files.
<state-dir>/exports/<project-key>/ Yes — these are user-facing /export outputs.
<state-dir>/sessions/<project-key>/<sid>/ Yes if you want to lose that session’s history. Prefer chord cleanup sessions --older-than ….
<state-dir>/sessions/<project-key>/ Avoid: this would lose all sessions for a project.
<state-dir>/projects/<project-key>.json Avoid: hand-editing leaves the project registry inconsistent. Use chord cleanup project instead.
<state-dir>/worktrees/... Avoid: use chord worktree remove <name>.
~/.config/chord/auth.state.json Yes. It is a machine-managed shared cache; deleting it only drops cached OAuth/quota state until warm-up repopulates it.
~/.config/chord/ Only if you want a clean reinstall. Do not delete auth.yaml unless you have your keys somewhere else.
<project>/.chord/ Only if you really want to drop the project’s chord overrides. Often committed to git.