Skip to content

Files & config

threadle writes to exactly one directory. Everything else on your disk it treats as read-only.

~/.config/threadle/
├── settings.json
├── triggers.json # optional — cron / path-watch
├── workflow-folders.json
├── favorites.json # jump-list bookmarks (sessions, workflows, …)
├── graphs/
│ ├── starter.json
│ ├── <id>.json
│ └── versions/<id>/<iso>.json
├── mcp/
│ └── servers.json
├── payloads/
│ ├── <aa>/<sha256>.json
│ ├── <aa>/<sha256>.md
│ └── tags.json
├── nodes/
│ └── <name>/node.json · node.ts
├── skills/
│ ├── custom/
│ └── imported/
├── runs/
│ ├── jobs.jsonl
│ ├── injects.jsonl
│ ├── logs/<jobId>.jsonl
│ └── <jobId>/outputs.json
├── search.db
├── models-pricing.json
├── cursor-usage.json
└── tmp/

PathContentsClearable in UI
settings.jsonEditor, billing, examples, MCP client/allowlist. See Settingsno
graphs/One JSON per workflow or sub-workflow, named by graph id. The seeded starter graph is always starter.json. Snapshots: graphs/versions/<id>/. Graph historyno
triggers.jsonOptional cron / path-watch entries for threadle daemon. Triggers
workflow-folders.jsonWorkflows sidebar folder treeno
favorites.jsonJump-list bookmarks (workflows, sessions, payloads, skills, rules, files). See Favorites
mcp/servers.jsonOptional threadle-owned MCP registry (stdio / HTTP / SSE). See MCPno
payloads/Content-addressed context payloads, sharded by the first two hex characters of their SHA-256yes (destructive)
payloads/tags.jsonSidecar map of hash → tags, so stored payloads stay immutable
nodes/Custom nodes. A node.json manifest or a TypeScript class entry, plus whatever the node shipsno
skills/customSkillsets you authored inside threadleno
skills/importedSkillsets imported into threadle. Project-repo skills override these on a name clashyes

Import / export / toggle from the shell: threadle skills (needs a running server). See Skills & rules · CLI. | runs/jobs.jsonl | Append-only record of every run shown in the Runs view | yes | | runs/logs/<jobId>.jsonl | Per-run log, one JSON line per emitted line ({ts, lane, line}) | yes | | runs/<jobId>/outputs.json | Cached node texts for partial / replay runs | yes | | runs/injects.jsonl | Which payload was injected into which session. Powers Lineage | yes (destructive) | | search.db | SQLite full-text index over transcripts and payloads. Deleting it just makes the next search slower | yes | | models-pricing.json | Legacy price-list leftover (optional. Prices ship bundled) | yes | | cursor-usage.json | Token counts captured from the Cursor CLI’s own usage object after a run | | | antigravity-usage.json | Token counts captured from the agy CLI’s own usage object after a run | | | tmp/ | Scratch files written while injecting context into sessions. Files older than 72 h are garbage-collected | yes |

Settings → threadle internals lists these live, with sizes and file counts, and clears the safe ones.


A payload’s identity is sha256(kind \0 provider \0 sessionId \0 content). Distill the same session twice with the same result and you get one file, not two.

Each payload is stored twice in the same shard directory:

  • <hash>.json. The payload object (kind, source, content, metadata)
  • <hash>.md. A plain-text sidecar so the directory is readable by a human or by grep. Written for every kind except files.

Writes are atomic: content goes to <hash>.json.tmp and is renamed into place. Graph writes use the same trick with a random suffix.

Because the hash is the identity, a portable graph strips payloadHash on export. The blob is local to the machine that made it.


VariableEffect
THREADLE_CONFIG_DIRReplaces ~/.config/threadle entirely. Every path above is relative to it
THREADLE_MCP_PROJECT_DIRProject dir for agent CLIs when running under threadle mcp

Default on Windows is %USERPROFILE%\.config\threadle (same ~/.config/threadle layout).

MCP hosts and the canvas ◈ MCP tool node also read:

  • project / user .mcp.json (and Cursor / Claude / opencode / Antigravity / Codex host configs where present). See MCP
  • ~/.config/threadle/mcp/servers.json: threadle-owned registry (under the config dir, stdio or HTTP/SSE)

Project/host .mcp.json files are not under the config dir. They live next to your project or in the host’s user config.

Set it to keep separate profiles, or to point threadle at a scratch directory during experiments:

Terminal window
THREADLE_CONFIG_DIR=/tmp/threadle-scratch threadle --no-open

Provider storage is parsed in place. Nothing under these paths is ever created, modified, or deleted by threadle.

ProviderPathEnv override
Claude Code~/.claude/projects/<slug>/<uuid>.jsonl, ~/.claude/history.jsonl, ~/.claude/sessions/*.json, ~/.claude/agents/*.mdCLAUDE_CONFIG_DIR
opencode~/.local/share/opencode/opencode.db (opened readOnly: true)OPENCODE_DATA_DIR
Cursor~/.cursor/projects/<slug>/agent-transcripts/…, ~/.cursor/chats/<md5>/…/meta.jsonCURSOR_CONFIG_DIR
Antigravity~/.gemini/antigravity-cli/brain/…/transcript_full.jsonl, conversation_summaries.dbANTIGRAVITY_HOME / JETSKI_APP_DATA_DIR
Codex~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl, archived_sessions/CODEX_HOME
GitHub Copilot~/.copilot/session-store.db, session-state/COPILOT_HOME
Grok Build~/.grok/sessions/<urlencoded-cwd>/<session-id>/, active_sessions.jsonGROK_HOME
Muse Code~/.local/share/muse/sessions/<id>/session.jsonl, session-index.db, ~/.muse (auth, never write)MUSE_DATA_DIR / MUSE_HOME / MUSE_PATH

Two more files are read but not written: ~/.claude.json (for the detected plan shown in Settings) and ~/.cache/opencode/models.json (preferred source for model prices).

Project directories are read for skills and rules files, and for agent definitions in <projectDir>/.claude/agents/. When you run an agent, the agent’s own CLI writes its own session storage exactly as it would from a terminal. That writing belongs to the tool, not to threadle.


  • Settings. The keys inside settings.json
  • Trust model. The read-only guarantee in full
  • Providers. How each storage format is parsed
  • CLI. Where a headless run persists its results