Read and write .cortex/ directory files — the filesystem interface for Cortex Protocol.
CortexIO
CortexIO is the filesystem interface for reading and writing .cortex/ directory files. It handles the protocol envelope (header + checksum) transparently. All protocol classes (DNAManager, Timeline, SwarmProtocol) use CortexIO internally.
import { CortexIO } from '@codmir/cortex';Constructor
new CortexIO(projectRoot: string)| Parameter | Type | Description |
|---|---|---|
projectRoot | string | Absolute path to the project root. The .cortex/ directory is created inside this. |
const io = new CortexIO('/home/dev/my-project');
// io.dir === '/home/dev/my-project/.cortex'Properties
| Property | Type | Description |
|---|---|---|
dir | string | Absolute path to the .cortex/ directory |
Lifecycle
init()
Creates the .cortex/ directory and the reasoning/ subdirectory if they do not exist.
async init(): Promise<void>const io = new CortexIO('/home/dev/my-project');
await io.init();exists()
Checks whether the .cortex/ directory exists.
async exists(): Promise<boolean>if (await io.exists()) {
const dna = await io.readDNA();
}Read Methods
All read methods return a CortexFile<T> containing both the header and data, or null if the file does not exist or is unreadable.
readDNA()
Reads manifest.crtx containing the ProjectDNA.
async readDNA(): Promise<CortexFile<ProjectDNA> | null>const file = await io.readDNA();
if (file) {
console.log(file.header.updated);
console.log(file.data.project.name);
}readTimeline()
Reads timeline.crtx containing all timeline entries.
async readTimeline(): Promise<CortexFile<TimelineEntry[]> | null>readGraph()
Reads graph.crtx containing the semantic graph.
async readGraph(): Promise<CortexFile<SemanticGraph> | null>readSwarm()
Reads swarm.crtx containing the active swarm manifest.
async readSwarm(): Promise<CortexFile<SwarmManifest> | null>readReasoning()
Reads a per-task reasoning file from reasoning/<taskId>.crtx.
async readReasoning(taskId: string): Promise<CortexFile<TimelineEntry[]> | null>| Parameter | Type | Description |
|---|---|---|
taskId | string | Task identifier (used as filename) |
listReasoningFiles()
Lists all task IDs that have reasoning files.
async listReasoningFiles(): Promise<string[]>Returns task IDs (filenames without the .crtx extension).
const taskIds = await io.listReasoningFiles();
// ['task_abc', 'task_def', 'task_ghi']Write Methods
All write methods create the protocol envelope automatically, including version, type, project ID, timestamps, and checksum.
writeDNA()
Writes manifest.crtx with the given ProjectDNA.
async writeDNA(dna: ProjectDNA): Promise<void>writeTimeline()
Writes timeline.crtx with the given entries. Reads the current DNA to set the project ID in the header.
async writeTimeline(entries: TimelineEntry[]): Promise<void>appendTimeline()
Appends a single entry to timeline.crtx. Reads the existing file, adds the entry, and writes it back.
async appendTimeline(entry: TimelineEntry): Promise<void>writeGraph()
Writes graph.crtx with the given semantic graph.
async writeGraph(graph: SemanticGraph): Promise<void>writeSwarm()
Writes swarm.crtx with the given swarm manifest.
async writeSwarm(manifest: SwarmManifest): Promise<void>writeReasoning()
Writes a per-task reasoning file to reasoning/<taskId>.crtx.
async writeReasoning(taskId: string, entries: TimelineEntry[]): Promise<void>appendReasoning()
Appends a single entry to a per-task reasoning file.
async appendReasoning(taskId: string, entry: TimelineEntry): Promise<void>clearSwarm()
Deletes swarm.crtx.
async clearSwarm(): Promise<void>Example
import { CortexIO } from '@codmir/cortex';
import type { ProjectDNA, TimelineEntry } from '@codmir/cortex';
const io = new CortexIO('/home/dev/my-project');
// Initialize the directory
await io.init();
// Write project DNA
const dna: ProjectDNA = {
version: 1,
project: {
id: 'proj_001',
name: 'My App',
purpose: 'A Next.js SaaS application',
created: Date.now(),
updated: Date.now(),
},
stack: {
languages: ['TypeScript'],
frameworks: ['Next.js', 'React'],
databases: ['PostgreSQL'],
infrastructure: ['Vercel', 'AWS'],
aiProviders: ['Anthropic'],
buildTools: ['turbo', 'tsup'],
},
architecture: {
type: 'monorepo',
entryPoints: ['apps/web/src/app/layout.tsx'],
boundaries: [],
dataFlow: [],
},
constraints: [],
patterns: [],
risks: [],
owner: { style: 'pragmatic', preferences: ['TypeScript', 'Tailwind'] },
};
await io.writeDNA(dna);
// Read it back
const file = await io.readDNA();
console.log(file?.data.project.name); // 'My App'
console.log(file?.header.checksum); // '1a2b3c'
// Append a timeline entry
const entry: TimelineEntry = {
id: 'entry_1',
timestamp: Date.now(),
agentId: 'agent_alpha',
type: 'decision',
action: 'Chose PostgreSQL over MySQL',
reasoning: 'Better JSON support and Prisma compatibility',
confidence: 0.95,
context: { files: ['prisma/schema.prisma'], state: {} },
refs: [],
outcome: 'success',
};
await io.appendTimeline(entry);
// List reasoning files
const tasks = await io.listReasoningFiles();
console.log(tasks); // []