.ctx Directory Structure
The .ctx directory is a local, content-addressed version control system designed specifically for AI agent executions. It serves as the primary data store for context packs, blobs, and metadata. When you run ctx init, this directory is initialized in your project root.
The internal structure is modeled after developer-native primitives (similar to Git), ensuring that agent runs remain immutable and reproducible.
Directory Layout
A typical .ctx directory contains the following components:
.ctx/
├── config.json # Local configuration and model settings
├── objects/ # Content-addressed blob storage (CAS)
├── packs/ # Index of finalized context pack manifests
├── refs/ # Named pointers to specific pack hashes
└── drafts/ # Mutable workspaces for 'ctx fork' and 'ctx finalize'
config.json
The primary configuration file for the context store. It contains project-level metadata and defaults used when packing logs or replaying executions.
objects/
The core of the substrate's immutability. All data—including system prompts, input files, tool outputs, and the manifests themselves—are stored here as content-addressed blobs.
- Addressability: Files are named based on the hash of their content.
- Deduplication: If multiple execution packs share the same input file or system prompt, only one copy is stored in
objects/.
packs/
This directory acts as the registry for all finalized Context Packs. When a log is processed via ctx pack, a manifest is generated and its hash is registered here.
- Files in this directory are named by their hex-encoded hash.
- Each file contains the full content-addressable manifest that links together the inputs, steps, and outputs of a specific agent run.
refs/
Contains pointers to specific pack hashes. This allows the CLI to resolve human-readable names or short-hand identifiers to specific, immutable snapshots in the object store.
drafts/
Used during the ctx fork workflow. Unlike the immutable objects in the main store, drafts are mutable JSON representations of a context pack. This allows developers to modify prompts or parameters manually before "finalizing" the draft into a new immutable pack.
Content-Addressable Mechanism
ContextSubstrate uses a deterministic hashing mechanism to ensure data integrity.
Blobs
When an execution log is "packed," the following components are converted into blobs:
- Prompts: System and user messages.
- Inputs: The literal content of files or configurations provided to the agent.
- Step Outputs: The raw data returned by tools or LLM reasoning steps.
- Manifest: A JSON object (the Pack) that maps all the above blob hashes into a structured sequence.
The Pack Manifest
The Pack manifest is the "source of truth" for a run. It follows a strict schema that includes:
- Environment: OS, runtime (e.g.,
go1.22), and tool versions. - Model: The model identifier and hyperparameters (e.g.,
temperature). - DAG of Hashes: Instead of storing raw text, it references hashes in the
objects/directory.
Example Manifest Reference
When inspecting a pack with ctx show <hash>, the tool resolves the manifest from .ctx/objects/. The technical relationship looks like this:
| Field | Storage Type | Reference Type |
| :--- | :--- | :--- |
| system_prompt | Blob | Hash |
| inputs[].content_ref | Blob | Hash |
| steps[].output_ref | Blob | Hash |
| parent | Pack | Hash |
This structure ensures that if even a single byte of a tool output changes, the resulting Pack Hash will change, making "drift" immediately detectable via ctx diff.