Skip to main content
devin-internals-spec

tests PyPI OpenSSF Scorecard OpenSSF Best Practices DeepWiki

ci License: MIT Python 3.10+ GitHub stars Last commit devin-* ecosystem PRs welcome

Part of the DEVIN ecosystem
Track: Understand · Nature: infrastructure
For: Developers, Maintainers
Interface: CLI / Python library
Path: Developers · step 3/4 — after devin-skill-catalog, before devin-powerups

devin-internals-spec

Linux · Personal Windows · Corporate Windows

Part of the awesome-devin ecosystem: the curated hub for the devin-* tools.

Unofficial community project. Not affiliated with, endorsed by, or sponsored by Cognition AI. "Devin" is a trademark of Cognition AI.

Windows · Linux · English

A documented map of Devin's local session stores — the CLI sessions.db, the Desktop GUI acp-messages/*.db and state.vscdb — plus a schema-version detector and deterministic synthetic fixtures, so tooling fails loudly instead of silently misreading your data.

The problem

Everything Devin stores on your disk is kept in undocumented SQLite databases whose schema changes without notice: sessions.db has already gone through 17 migrations (v1–v15 on 2026-05-06, v16 on 2026-07-05, v17 on 2026-09-14). Any tool that reads these stores has to reverse-engineer the format — and when Cognition ships the next migration, those tools break silently: wrong counts, missed rows, or corrupted interpretation, with no error raised.

The Devin Desktop app is worse off than the CLI: its stores (acp-messages/*.db, state.vscdb, session locks, the refinery_schema_history migration ledger) are not documented anywhere.

Prior art

Session-log tooling exists for other agent CLIs — e.g. tokmesh and UniSessions document and parse Devin's CLI sessions.db. This project does not reinvent that: it borrows the same idea (SQLite schema → typed parsing) and extends it to what those tools don't cover — the Desktop GUI stores — and adds the piece they lack: an explicit schema-version gate so a parser refuses to run against a schema it has never seen.

What makes it Devin-native

The differentiator, in one sentence: it's the map of what Devin keeps on your disk — and it warns you when that changes.

  1. Side-by-side: it covers acp-messages/*.db, state.vscdb (windsurfSpace.* keys) and refinery_schema_history, which no existing tool documents.
  2. No-Devin: remove Devin and there is no store to document — the extra disappears entirely.
  3. Loud failure: detect_schema_version() returns a version contract and raises on anything unknown, instead of guessing at bytes.

Install

Python ≥ 3.10 required; install with uv (recommended) or pipx.

uv tool install devin-internals-spec

or with pipx (install it via pip install --user pipx or your package manager, then pipx ensurepath):

pipx install devin-internals-spec

For development:

pip install -e ".[dev]"
pytest

Usage

devin-inspect schema   <sessions.db>      # schema-detection contract (JSON)
devin-inspect sessions <sessions.db>      # list sessions (id, title, cwd, …)
devin-inspect health   <devin-data-dir>   # locate + check all three stores
devin-inspect contract <devin-data-dir>   # unified drift check: schema +
                                          # acp meta + usage shape, one report
devin-inspect make-fixture <out>          # deterministic synthetic stores
                                          # for tests/demos (--kind, --seed,
                                          # --schema-version, --n-sessions)

contract is the single drift boundary for the whole catalog: it reports sessions.db schema version, acp-messages meta schema_version (observed: 6; 1 on legacy DBs) and unexpected meta keys, and the verified usage shape (no cost persisted — num_tokens_preceding only). On Linux it resolves the split layout automatically (~/.local/share/devin data root + ~/.config/Devin GUI root). Exit code is non-zero on any drift.

AcpMessagesStore.typed_meta() decodes the meta table into a typed view (schema_version normalized to int, message_count, truncated, title from the info JSON blob) with raw as fallback. devin_internals.projects gives the canonical project key/path used to join sessions across tools, and devin_internals.commits.commit_references() extracts git commit SHAs (40-hex + /commit/<sha> URLs, with repo context) from tool_call_state payloads — short SHAs are ignored on purpose (precision over recall for graph joins).

Every subcommand is read-only and accepts --json. The Python library is the supported interface — the CLI is a thin wrapper:

import os
import sys
from pathlib import Path
from devin_internals import detect_schema_version
from devin_internals.parsers import SessionsStore

if os.name == "nt":
    root = Path(os.environ["APPDATA"]) / "devin"
elif sys.platform == "darwin":
    root = Path.home() / "Library" / "Application Support" / "devin"
else:
    data_home = Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local/share"))
    root = data_home / "devin"
sessions_db = root / "cli" / "sessions.db"

detect_schema_version(sessions_db)
# {"schema_version": 17, "known": True, "min_supported": 15, ...}

with SessionsStore(sessions_db) as store:
    store.sessions()  # typed dataclasses

Canonical store locations (paths + identity)

devin_internals.paths is the canonical convention for where Devin keeps its on-disk state — the reference the ecosystem's vendored paths.py copies (11+ packages) converge on (decision D-2026-10-08):

platform data root UI config root
Linux $XDG_DATA_HOME/devin → ~/.local/share/devin $XDG_CONFIG_HOME/Devin → ~/.config/Devin
Windows %APPDATA%\devin %APPDATA%\Devin
macOS ~/Library/Application Support/devin ~/Library/Application Support/Devin

resolve() returns a frozen DevinPaths with every store a consumer needs: sessions_db, session_locks_dir and credentials_toml under the data root; acp_messages_dir and state_vscdb under the config root's User/ tree; and ecosystem_dir — <config>/.devin-ecosystem/ — anchoring ecosystem bookkeeping (machine-id, devin-profile.json, hooks.json, scheduled.json, plans.jsonl, metrics/). DEVIN_DATA_DIR / DEVIN_CONFIG_DIR override the roots; candidate-order helpers cover files that may live under data or config roots — including the legacy lowercase $XDG_CONFIG_HOME/devin CLI root on Linux — and a unified User/-under-data layout is detected per store. The ecosystem anchor is resolved separately from UI-store probing (ecosystem_anchor_dir), so a User/ tree appearing later can never move an existing identity. environ/platform are injectable for tests. Per-OS path details live in the platform guides: Linux, Windows, Corporate Windows.

devin_internals.identity resolves the shared machine identity the same way every devin-* tool does: machine_id() returns DEVIN_MACHINE_ID or a random 16-hex id published once at <ecosystem>/machine-id (mode 0600, atomic link-claim — on filesystems with hard-link support the file never exists empty or partially written; concurrent losers adopt the winner, never regenerated); profile() resolves DEVIN_ECOSYSTEM_PROFILE, then devin-profile.json (canonical ecosystem location first, then the legacy config-root copies, lowercase sibling included), failing closed to "corporate" whenever a resolved value is invalid.

from devin_internals.paths import resolve
from devin_internals.identity import provenance

paths = resolve()          # frozen DevinPaths for this machine —
                           # the one API that picks platform conventions;
                           # pass environ=/platform= to resolve for another
paths.sessions_db          # <data>/cli/sessions.db
paths.ecosystem_dir        # <config>/.devin-ecosystem

provenance()               # {"machine_id": ..., "profile": "corporate"|"personal"}

Incremental cursors (devin_internals.cursor)

Cursor is the shared incremental-watermark helper — one JSON object per cursor at <dir>/<name>-state.json, for learning extract, sweeps, digests and any "resume where I stopped" mechanism (spec: devin-powerups/docs/incrementality.md).

  • The anchor dir defaults to <cwd>/.devin and is overridable per cursor via the DEVIN_CURSOR_DIR env or an explicit dir= argument.
  • commit() is the only write: atomic (tmp + os.replace), called after the work so a crash re-scans instead of skipping, and it merges with whatever is on disk so two cursors sharing a name do not erase each other's keys.
  • Missing or corrupt state reads as empty (fail-open); non-finite values (NaN, inf) are rejected at commit time.
from devin_internals import cursor

c = cursor.Cursor("learning-extract")
last = c.get("last_ts", 0)
# ...process everything newer than last...
c.set("last_ts", newest_ts)
c.commit()

Works with Devin alone (Devin-only mode)

The spec is documentation plus a small local validation library: it reads Devin's stores to report the schema version and gates tools when the version is newer than what is known — it stops loudly instead of misparsing. Purely local; nothing external is needed.

Platform support

Pure stdlib Python — identical behavior on Windows, Linux and macOS. CI runs the suite on windows-latest + ubuntu-latest. Parsers and CLI subcommands take the target file or directory as an explicit argument; only devin_internals.paths/identity resolve platform conventions, and both accept injectable environ/platform plus the DEVIN_DATA_DIR/DEVIN_CONFIG_DIR overrides.

vscdb-scan — shape-only audit (IS-1)

devin-internals vscdb-scan <state.vscdb> audits the GUI key/value store and reports, per key: name, value shape (json-object/array/string/…), length, top-level JSON keys and risk flags (sensitive-key-name, looks-like-jwt, large-blob). Values are never printed — flags are heuristic and recall-biased; a real audit confirmed state.vscdb can hold auth tokens and PII. --fail-on-flags exits 1 for CI.

Limitations

  • Private, volatile internals. These stores are implementation details of Devin; the schema can change in any release. Only what is marked "verified" in docs/SPEC.md should be relied on.
  • Verified against schema v17 only (the latest at time of writing). The detector refuses versions it doesn't know — that's a feature, but it means new Devin releases will break detection until the spec is updated.
  • Read-only. This project never writes to Devin's databases.
  • Not a session exporter. It documents and guards the format; it does not dump your conversations (that is devin-history's job).
  • Fixtures contain synthetic data only — no real session content is ever copied, by design.

Development

pip install -e ".[dev]"
pytest

Ground rules in CONTRIBUTING.md: fixtures before parsers, small commits, a shared README and Windows/Linux platform guides.

When to use this

  • You are building a tool that reads Devin's local stores and need the documented schema, not reverse-engineering.
  • You want a schema-version gate: detect_schema_version() refuses loudly on unknown versions instead of misparsing.
  • You need deterministic synthetic fixtures to test parsers — no real session data required.
  • You need typed, read-only access to sessions.db via SessionsStore in Python.

When NOT to use this

  • You want to export or dump sessions — this documents and guards the format; devin-history does the exporting.
  • Your Devin release ships a schema newer than v17 — the detector refuses by design until the spec catches up.
  • You need writes — every parser and subcommand is strictly read-only.

FAQ

What data does Devin store locally, and where? Per this spec: a versioned sessions.db under cli/ (sessions, tool-call state, transcripts), one acp-messages/*.db per GUI session, a state.vscdb KV store with windsurfSpace.* keys, credentials.toml, and a refinery_schema_history migration ledger. The verified details live in docs/SPEC.md.

What happens when Devin ships a new schema version? Tools using this library fail loudly, not silently. detect_schema_version() returns a contract (known, min_supported) and raises on versions it does not recognize — verified against schema v17 at time of writing.

How is this different from other sessions.db parsers? It also documents the Desktop GUI stores (acp-messages/*.db, state.vscdb, session locks, the migration ledger) that other tools don't cover, and adds the explicit schema-version gate. The library is the supported interface; devin-inspect is a thin CLI wrapper.

License

MIT — see LICENSE.


If this saved you debugging time, a ⭐ on the repo helps others find it.

Metadata

Release files for devin-internals-spec 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for devin-internals-spec 0.3.2
File Size Uploaded
devin_internals_spec-0.3.2.tar.gz 55.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for devin-internals-spec 0.3.2
File Interpreter ABI Platform
devin_internals_spec-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 98.6 kB

Release files / devin_internals_spec-0.3.2.tar.gz

Download URL devin_internals_spec-0.3.2.tar.gz
Size 55.3 kB
Tags Source
SHA-256 checksum
How to use checksums
dc38baa7d35da5b55dc3b17170bafff27c6e3bd2278c3bdde62384d64b31ae71
BLAKE2b-256 checksum
How to use checksums
b41566e1be503979305fd451c48ea85123274261da7740f30f3936970b5b49c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release files / devin_internals_spec-0.3.2-py3-none-any.whl

Download URL devin_internals_spec-0.3.2-py3-none-any.whl
Size 43.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
47fbe2fb997e7d302ad85a0853ccdf3206bfaf3f49a11b231fb3ca5ebc7a0586
BLAKE2b-256 checksum
How to use checksums
4491d2eeae90f59cbee0641f2ce2ddaa058b50265f9daccbf63aae4b7a5b3a75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.2 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page