Archive AI coding-agent sessions (Claude Code, Codex, Gemini, Cline, OpenCode, Hermes) as index-safe Markdown notes in an Obsidian vault.
Project description
agent-vault
Archive your AI coding-agent sessions as clean, index-safe Markdown notes in an Obsidian vault.
If you use tools like Claude Code or Codex daily, your session history piles up in undocumented JSONL files and SQLite databases scattered across your machine. agent-vault sweeps those sources on a schedule and renders every session as a readable, searchable, wikilink-connected Markdown note — without ever freezing Obsidian's indexer, no matter how pathological the transcript.
Why not just dump sessions to Markdown?
Because real agent transcripts are hostile to Obsidian. A single session can be 12 MB, contain 100,000-character physical lines, or embed NUL bytes — any of which can stall Obsidian's indexing for the whole vault. agent-vault was built after exactly that happened, and its pipeline is designed around preventing it:
- Text normalization — NULs removed, C0 control characters replaced, line endings normalized, physical line length capped (default 8,000 chars) with explicit continuation markers instead of silent truncation. Idempotent by construction.
- Multipart splitting — sessions are planned as a document set: one stable primary note plus
Part 001,Part 002, … part notes, grouped by complete message sections against a 750 KiB target with a 1 MiB hard ceiling (max_note_bytes). Wikilinks always target the primary note. - Deterministic, idempotent sync — a SQLite manifest tracks every generated file by content hash. Re-running an import produces zero writes. Interrupted runs converge on the next run. Files the tool didn't create are never touched or deleted.
Supported providers
| Provider | Source format |
|---|---|
| Claude Code | ~/.claude/projects JSONL session logs (including subagents) |
| Codex | ~/.codex/sessions rollout logs |
| Gemini (Antigravity) | ~/.gemini/antigravity/brain |
| Cline | ~/.cline task history |
| OpenCode | ~/.local/share/opencode session storage |
| Hermes | ~/.hermes state.db SQLite databases |
Multiple roots per provider are supported (e.g. a Windows path and a WSL //wsl.localhost/... path); identical sessions found in more than one place are deduplicated by content hash.
A note on fragility: these session formats are undocumented and change without notice as the upstream tools evolve. The adapters were last validated against real session data in July 2026, specifically: Claude Code 2.1.201, Codex CLI 1.17.15, and Hermes Agent 0.18.0 (plus Gemini/Antigravity, Cline, and OpenCode session stores current at that date). If an import reports
failedorunsupportedsessions after a tool update, the adapter likely needs a refresh — failures print per-file diagnostics to stderr and are itemized in the--report-jsonoutput. Issues and PRs welcome.
Install
Requires Python 3.11+. No runtime dependencies outside the standard library.
pip install obsidian-agent-vault
Quickstart
-
Copy
audit-config.example.json, setvaultto your Obsidian vault path, and remove any providers you don't use. -
Validate the config without touching anything:
agent-vault check --config my-config.json
-
Preview what an import would do — same planned paths and collision decisions as a real run, zero writes:
agent-vault audit --config my-config.json --dry-run --report-json report.json
-
Run it for real:
agent-vault audit --config my-config.json
Useful flags: --provider <name> scopes a run to one provider; --full re-imports sessions even if their sources appear unchanged; --report-json <path> writes run metrics.
Exit codes: 0 success, 1 source/output failures or unsupported providers, 2 invalid usage or config.
Configuration
{
"vault": "/path/to/your/obsidian/vault",
"sources": {
"claude": ["~/.claude/projects"],
"codex": ["~/.codex/sessions"],
"hermes": ["~/.hermes"]
},
"redact_patterns": [],
"max_tool_output": 1000,
"max_note_bytes": 1048576,
"max_line_chars": 8000
}
redact_patterns— regex patterns scrubbed from all content before rendering and before content hashes are computed.max_tool_output— character cap for individual tool-output bodies.max_note_bytes— hard byte ceiling for any generated note (default 1 MiB).max_line_chars— maximum physical Markdown line length (default 8,000; minimum 80).
All limits are validated before any audit starts; ~ is expanded in all paths.
What the output looks like
Notes land under 01_Transcripts/<Provider>/ in your vault with readable, date-prefixed, ID-disambiguated names:
01_Transcripts/Hermes/2026-06-30 Optimizing AI Setup (355c876a)/
├── 2026-06-30 Optimizing AI Setup (355c876a).md ← primary (index) note
├── 2026-06-30 Optimizing AI Setup (355c876a) Part 001.md
├── ...
- Every note carries frontmatter:
provider,session_id,title,project,started_at/ended_at,source, and tags. - Sessions that spawned subagents get a directory, with child-session notes nested inside and two-way parent/child wikilinks.
- Multipart notes add
document_kind(primary/part),part, andpart_count— filterdocument_kind != "part"in Obsidian Bases/Dataview views so each session shows once. - Small single-file sessions stay single files; the directory/part machinery only appears when needed.
Scheduling
The tool is headless and cron-friendly. A nightly run is one line:
# cron (Linux/macOS)
0 2 * * * agent-vault audit --config /path/to/config.json --report-json /path/to/nightly.json
# Windows Task Scheduler action
agent-vault audit --config config.json --report-json nightly.json
Before scheduling, run once manually and open the vault in Obsidian to confirm indexing completes.
Recovering from pathological notes
If a note (typically one generated before you adopted this tool, or by an older version) stalls Obsidian's indexer:
- Move it out — don't delete it — to a quarantine folder outside the vault. Obsidian recovers immediately.
- Re-run the importer scoped to that provider. The session regenerates from its original source under the current normalization and splitting rules.
- Check the run report:
largest_note_bytesandlargest_line_charsshould be within your configured ceilings, and generated files should contain noU+0000. - Delete the quarantined original only after confirming the regenerated note indexes cleanly.
Finding leftovers: sessions deduplicated against an already-imported copy are never re-rendered, so a stale pre-existing note for such a session won't be cleaned up automatically — the tool refuses to delete files it doesn't currently manage. Use doctor (below) to find and quarantine them.
The doctor command
doctor scans everything actually on disk under 01_Transcripts/ — not just what the last run touched — and reports:
- orphaned — files that look like generated transcripts (frontmatter with
providerandsession_id) but that no manifest row owns: leftovers from older importer versions or deduplicated sessions. Hand-written notes are left alone. - oversized_line / oversized_note / nul_bytes — violations of your configured index-safety limits, wherever they came from.
agent-vault doctor --config my-config.json --report-json doctor.json
# review the findings, then optionally:
agent-vault doctor --config my-config.json --quarantine-to /path/outside/vault/quarantine
agent-vault doctor --config my-config.json --quarantine-to /path/outside/vault/quarantine --only-unsafe
--quarantine-to moves only orphaned files (preserving their relative paths) — a hand-written note is never moved, even if it also trips oversized_line or another safety check, and manifest-owned files are never moved either, because the importer owns their lifecycle; regenerate those by re-running audit. Add --only-unsafe to narrow that further: only orphaned files that also carry a safety finding (oversized_line, oversized_note, or nul_bytes) get quarantined, so orphans that are merely harmless duplicates stay put for you to review. --only-unsafe requires --quarantine-to and exits 2 otherwise. Exit code is 1 when findings exist, 0 when clean, so it works as a scheduled health check.
Development
pip install pytest pytest-subtests
python -m pytest tests/ -q
The suite covers adapters (with synthetic fixtures for every provider), text normalization, oversized-message chunking, document-set planning, manifest migration, transactional sync (including one↔many part transitions and interruption recovery), CLI behavior, and end-to-end index-safety regressions modeled on real failure shapes (12 MB transcripts, 136k-char lines, embedded NULs).
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file obsidian_agent_vault-0.1.0.tar.gz.
File metadata
- Download URL: obsidian_agent_vault-0.1.0.tar.gz
- Upload date:
- Size: 53.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b52c7154799ad8d4c770c7dbd4b383d9465fb4cdbdd8e602a38fe4d311e42e68
|
|
| MD5 |
345607f9666c5ef0cdf73c87a42534d3
|
|
| BLAKE2b-256 |
ea7f814a624bee61964fb4c3743922ab2f847be432296139578d093c2c07f4db
|
Provenance
The following attestation bundles were made for obsidian_agent_vault-0.1.0.tar.gz:
Publisher:
publish.yml on spawnofsociety2/agent-vault
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
obsidian_agent_vault-0.1.0.tar.gz -
Subject digest:
b52c7154799ad8d4c770c7dbd4b383d9465fb4cdbdd8e602a38fe4d311e42e68 - Sigstore transparency entry: 2147627057
- Sigstore integration time:
-
Permalink:
spawnofsociety2/agent-vault@bbeeca7669d40ecd5edf2391f38ff0ffba8d3fc8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/spawnofsociety2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bbeeca7669d40ecd5edf2391f38ff0ffba8d3fc8 -
Trigger Event:
release
-
Statement type:
File details
Details for the file obsidian_agent_vault-0.1.0-py3-none-any.whl.
File metadata
- Download URL: obsidian_agent_vault-0.1.0-py3-none-any.whl
- Upload date:
- Size: 34.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e113b19dad4f67b7a5803b78b3f062030b92c374e1207bec46f178aeb8111a45
|
|
| MD5 |
0b42997a1e4adf1c83be9d71509d2986
|
|
| BLAKE2b-256 |
ac6743b012ff8d3566ea7f7275d03ac73a72cba4699473f462b36ff7c2186447
|
Provenance
The following attestation bundles were made for obsidian_agent_vault-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on spawnofsociety2/agent-vault
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
obsidian_agent_vault-0.1.0-py3-none-any.whl -
Subject digest:
e113b19dad4f67b7a5803b78b3f062030b92c374e1207bec46f178aeb8111a45 - Sigstore transparency entry: 2147627526
- Sigstore integration time:
-
Permalink:
spawnofsociety2/agent-vault@bbeeca7669d40ecd5edf2391f38ff0ffba8d3fc8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/spawnofsociety2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bbeeca7669d40ecd5edf2391f38ff0ffba8d3fc8 -
Trigger Event:
release
-
Statement type: