Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

Cerebro is human-centric. The cortex is yours—plain markdown you can read, edit, and open in any tool. AI integration is optional, not a requirement.

The problem

You have side projects. Maybe 3, maybe 10. You work on them in bursts: a flurry of commits, then months of silence.

When you return, the question is always the same:

“Wait, what work was in progress? Where did things leave off?”

You scroll through git history. You grep for “TODO”. You search your notes. By the time you remember, you’ve already lost 20 minutes.

The solution

Cerebro watches your development activity and builds a personal mission control dashboard. It aggregates:

  1. AI sessions: Your AI pair-programming history (OpenCode, Pi, or both)
  2. Git activity: Commits, branches, file changes
  3. TODOs: TODO, Needs Fixing, Hack, and Placeholder comments in your code
  4. Manual notes: Your status, next actions, goals

When you return to a dormant project, your dashboard answers the question in seconds.

How it works

Cerebro uses a two-repo architecture:

flowchart LR
    subgraph "Sources"
        G[Git repos]
        O[AI sessions]
    end

    subgraph "cerebro (CLI)"
        C[cerebro build]
    end

    subgraph "cortex (your data directory)"
        CT[content/ generated md]
        NB[content/notes/ manual]
        BK[book/ rendered HTML]
    end

    subgraph "cerebro-mcp"
        MS[MCP server]
    end

    subgraph "cerebro-tui"
        TUI[Terminal UI]
    end

    subgraph "Consumers"
        TERM[Terminal user]
        MDB[mdbook]
        OC[OpenCode]
    end

    G -->|scrape| C
    O -->|scrape| C
    C -->|writes| CT
    NB -. manual .-> CT
    CT -->|mdbook| BK
    NB -->|mdbook| BK
    MS -->|reads| CT
    MS -->|reads| NB
    OC <-->|JSON-RPC| MS
    TUI -->|reads| CT
    TUI -->|reads| NB
    TERM <-->|interactive| TUI

The two repos

RepoPurpose
~/Projects/cerebroSource code: command-line tool, MCP, Terminal User Interface, shared types
~/Projects/<name>Your cortex: config, generated content, manual notes, rendered HTML

The three binaries

BinaryPurposeUsed by
cerebroCommand-line tool: scrape repos, generate markdownYou, cron
cerebro-mcpMCP server: answer questions about projectsAny MCP client
cerebro-tuiTerminal UI: browse projects interactivelyYou

Content boundaries

Your cortex’s content/ has a clear split:

PathGenerated byEdit?
content/index.mdcerebroNo
content/projects/*.mdcerebroNo
content/journal/cerebroNo
content/today.mdcerebroNo
content/this-week.mdcerebroNo
content/intent/HumanYes
content/notes/HumanYes
content/SUMMARY.mdHumanYes

An AGENTS.md file in your cortex enforces the boundary. AI agents should not edit manual content.

Why it works

Cerebro succeeds when it reduces context-switching friction. You’ll notice it when:

  • You return to a project you haven’t touched in weeks
  • You have too many projects to track mentally
  • You use AI assistants and want to remember what you worked on

Key concepts

TermMeaning
CollectorA source of data (git, opencode, todos, notes)
GeneratorCreates output files from collected data
ProjectA repo + notes + activity you’re tracking
DashboardThe generated markdown output
CortexYour data directory: config, content, rendered book
Terminal User InterfaceTerminal UI for interactive browsing

Architecture

Cerebro is a Rust workspace with four crates:

  • cerebro: Command-line tool: coordinates collectors and generators, manages cache
  • cerebro-core: Shared types, traits, collector implementations, and query operations
  • cerebro-mcp: MCP server for OpenCode integration
  • cerebro-tui: Ratatui terminal UI for browsing projects interactively

Next steps

  1. Quick Start: Get running in 5 minutes
  2. Dashboard Guide: Understand the output
  3. Configuration: Customize for your projects

Quick start

Get your dashboard running in 5 minutes.

1. Install

cargo install --path crates/cerebro

2. Create config

Place config.toml at the XDG default location ($XDG_CONFIG_HOME/cerebro/config.toml, or ~/.config/cerebro/config.toml if XDG_CONFIG_HOME is unset — same on every platform):

[settings]
output_dir = "~/Projects/cortex/content"

[[projects]]
name = "my-project"
repo_path = "~/Projects/my-project"
active = true

(Override the path with --config <file> or by setting CORTEX_PATH and putting config.toml in the cortex data dir — see Configuration.)

3. Build

cerebro build

This generates your dashboard in the output_dir you set in config (default: ~/Projects/cortex/content/).

4. Serve

cd ~/Projects/cortex && mdbook serve --port 3456

Open http://localhost:3456 to see your dashboard.

Your first win

After a few days of use, come back to a dormant project. Instead of:

“Wait, what work was in progress? Where did things leave off?”

Your dashboard shows:

  • Last activity: 3 days ago: “feat: add user authentication”
  • OpenCode session: “Debugging JWT token refresh”
  • TODOs left: src/auth.rs:42: “TODO: handle expired tokens”
  • Next action: From your notes: “Test the login flow”

That’s the moment cerebro earns its place in your workflow.

Next steps

Dashboard guide

Understanding the output cerebro generates.

Output structure

{cerebro-dashboard}/
├── index.md                    # Your mission control
├── today.md                    # Today's activity
├── this-week.md              # This week's activity
├── projects/
│   └── {name}.md            # Per-project pages
└── journal/
    └── {year}/
        └── {mm}/
            └── {dd}.md      # Daily journal pages

Index.md: Your mission control

The main dashboard shows:

Activity overview

  • Projects at a glance: Which have recent activity
  • Git commit counts: How much you’ve shipped
  • AI-assisted sessions: How many sessions your AI coding tools logged (OpenCode + Pi, only shown if configured)
  • TODO totals: Work waiting

Project cards

Each project shows:

  • Last activity: When you last worked on it
  • Recent commits: What you shipped
  • AI-assisted sessions: AI-assisted work
  • TODOs: Outstanding items
  • Status: From your notes, such as “paused” or “actively developing”
  • Next action: Your stated next step

Projects/{name}.md: Deep dive

Click any project card to see full context:

  • Repository path
  • Last activity timestamp
  • Status badge

Your notes

Whatever you’ve written in notes/projects/{name}.md:

## Status
building: integrating Stripe API

## Next
- Test webhook endpoints locally
- Deploy to staging

Git activity

Recent commits with messages, dates, and files changed.

AI-assisted sessions

AI-assisted work sessions with titles and timestamps.

TODOs

List of TODO, Needs Fixing, Hack, and Placeholder items found in code:

- TODO: handle expired JWT tokens (src/auth.rs:42)
- FIXME: race condition in cache (src/cache.rs:18)
- HACK: temporary rate limiting (src/api.rs:103)

Today.md: Daily pulse

Today’s activity, scoped to the last 24 hours.

This-week.md: Weekly review

This week’s activity, scoped to 7 days.

Journal/{date}.md: Historical record

Daily pages with all activity for that date. Useful for:

  • Reviewing what you accomplished
  • Identifying patterns in your work
  • Journaling your development journey

Using the dashboard

For context switching

When returning to a project:

  1. Open the dashboard
  2. Find your project by searching or clicking
  3. Read: status → next → TODOs → recent activity

For daily standup

  • Check today.md for today’s work
  • Review this-week.md for the week’s progress

For planning

  • Read your notes in each project
  • Review TODOs to see what’s left

Customization

The dashboard is just markdown. You can:

  • Add it to git for version control
  • Deploy it to a static host
  • Customize the templates in generators/
  • Add your own data sources

Terminal User Interface guide

Launch the terminal UI with:

cerebro tui

Or run the standalone binary directly:

cerebro-tui

The Terminal User Interface provides a rich, interactive terminal interface for browsing all your project activity data, including sessions, commits, TODOs, journal entries, and manual notes, without leaving your terminal.

Layout

┌─────────────────────────────────────────────────────┐
│ Cerebro TUI                                         │
├──────────┬──────────────────────────────────────────┤
│ Dashboard│  [Content area: changes per view]       │
│ Projects │                                          │
│ Journal  │                                          │
│ TODOs    │                                          │
│ Config   │                                          │
├──────────┴──────────────────────────────────────────┤
│ r refresh  b build  Space leader  q quit  ? help    │
└─────────────────────────────────────────────────────┘

Main views

KeyAction
j / Next item in sidebar
k / Previous item in sidebar
TabCycle focus between sidebar and content
Shift+TabCycle focus backward
EnterSwitch to selected view from sidebar
1 / gDashboard
2Projects
3Journal
4TODOs
5 / GConfig

Leader key

Press Space then a letter to jump directly:

SequenceAction
Space dDashboard
Space pProjects
Space jJournal
Space tTODOs
Space cConfig

The leader key is active everywhere except during text input, such as journal editing, note editing, or form input. Press Esc to cancel a pending leader sequence.

Focus management

KeyAction
Right / lMove focus from sidebar to content
Left / hMove focus from content to sidebar

Views

Dashboard

Summary of all projects with session counts, commit counts, and TODO counts. Press Enter on a project to drill into its detail view.

Projects

Without a selected project, the view shows a list of all projects with activity counts. Navigate with j/k, press Enter to select.

After selecting a project, three tabs appear:

KeyTab
1Sessions
2Commits
3TODOs
TabNext tab
Shift+TabPrevious tab

Within each tab, navigate items with j/k. Press Enter on a TODO to preview its full context. Press e to edit the project’s status/next notes. Press Esc to deselect and return to the project list.

Journal

Shows journal entries from all projects. Date headers, such as ### 2026-04-25, group the entries, or the view shows a single entry per project if no date headers exist.

KeyAction
j / Next entry
k / Previous entry
gFirst entry
GLast entry
EnterView full entry
iEdit journal for the selected project
EscClose preview / cancel edit

Journal entries come from ## Journal sections in your project notes files under content/notes/projects/. If no journal sections exist, the view is empty.

TODOs

Aggregates TODOs from all projects. Navigate with j/k, press Enter to preview the full TODO with file context. Press Esc to close preview.

Config

Toggle project active/inactive status and add new projects. The TUI writes changes to config.toml on disk.

Global commands

KeyAction
rRefresh data from all sources
bRun cerebro build, which generates the dashboard
qQuit
?Toggle help overlay
EscClose overlays, go back

Mouse support

Click any item in the sidebar to switch views. Click a project in the project list to select it.

What the Terminal User Interface does

  • Browse OpenCode sessions, git commits, and TODOs per project
  • View project status and next-session notes
  • Edit status and next notes directly from the TUI
  • Read journal entries from daily logs
  • Toggle project active/inactive status
  • Add new projects to config
  • Refresh data on demand
  • Build the markdown dashboard from the TUI

What the Terminal User Interface doesn’t do yet

  • Session message content: Sessions show titles and timestamps but not individual messages
  • Session preview: Can’t view the conversation inside a session
  • Commit diff: Shows commit messages but not file changes
  • TODO editing: Can view TODOs but not mark them complete, since they are code comments
  • Search/filter: No text search across sessions, commits, or TODOs yet
  • Activity graph: No heatmap or timeline visualization
  • Multi-project comparison: Can’t view two projects side by side
  • Git branch info: Doesn’t show current branch or uncommitted changes per project

Configuration

Cerebro reads a config.toml file. The CLI and TUI use the XDG default ($XDG_CONFIG_HOME/cerebro/config.toml, or ~/.config/cerebro/config.toml if XDG_CONFIG_HOME is unset — same on every platform). The MCP server uses CORTEX_PATH to locate the cortex data directory (falls back to ~/Projects/cortex).

Where the config is loaded from

Priority:

  1. --config <path> CLI flag (explicit override)
  2. XDG config dir ($XDG_CONFIG_HOME/cerebro/config.toml, falling back to $HOME/.config/cerebro/config.toml) — the default
  3. CORTEX_PATH env var (legacy fallback for users who colocate config with their cortex data dir)
  4. ./config.toml in the current working directory (last-resort fallback)

Example Configuration

[settings]
opencode_db_path = "~/.local/share/opencode/opencode.db"
pi_sessions_path = "~/.pi/agent/sessions"
output_dir = "./content"

[[projects]]
name = "my-project"
repo_path = "~/Projects/my-project"
active = true

Settings

SettingRequiredDescriptionDefault
output_dirNoWhere to write the generated dashboard./content
opencode_db_pathNoPath to OpenCode’s session database. Only needed if you want OpenCode session history.None
pi_sessions_pathNoPath to Pi’s sessions directory. Only needed if you want Pi session history.None

Project Configuration

Define each project with:

SettingDescriptionRequired
nameProject nameYes
repo_pathPath to git repositoryYes
activeInclude in dashboard generationYes

Manual notes

Manual notes aren’t configured per-project. They live directly in your cortex:

PathPurposeEdited by
content/intent/Goals for daily, weekly, monthly, or yearly periodsHuman only
content/notes/Evergreen notes and documentationHuman only
content/SUMMARY.mdNavigation structureHuman only

An AGENTS.md file in your cortex defines the boundary between auto-generated and manual content. Cerebro only writes to content/index.md, content/projects/, content/journal/, content/today.md, and content/this-week.md.

Commands

Cerebro provides the following command-line tool commands:

Build commands

cerebro build

Generate the dashboard. Uses cached data where fresh.

cerebro build                    # Build all projects
cerebro build --project my-proj  # Build specific project
cerebro build --fresh            # Force rebuild, ignoring cache

cerebro serve

Serve the generated dashboard with mdBook locally.

cerebro serve              # Default port is 3000
cerebro serve --port 8080  # Custom port

Note: this spawns mdbook in the configured output_dir and exits immediately. For a persistent server, run mdbook serve directly in your cortex.

Status commands

cerebro status

Check cache status for all projects.

cerebro status

Shows last build time per project, cache TTL remaining, and any stale data.

Query commands

These commands read cortex data and output JSON: useful for scripting or piping.

cerebro projects list

List all tracked projects.

cerebro projects list              # All projects
cerebro projects list --active-only  # Only active projects

cerebro projects read <name>

Read the full context for a specific project.

cerebro projects read my-project

Returns sessions, commits, TODOs, and manual notes for the named project.

cerebro journal read <date>

Read a journal entry for a specific date.

cerebro journal read 2026-05-17

cerebro journal today

Read today’s journal entry.

cerebro journal today

cerebro intent <period> <identifier>

Read intent/goals for a period.

cerebro intent daily 2026-05-17
cerebro intent weekly 2026-W20
cerebro intent monthly 2026-05
cerebro intent yearly 2026

cerebro todos

Search TODO comments across all projects.

cerebro todos                       # All TODOs
cerebro todos --keyword FIXME       # Filter by keyword
cerebro todos --project my-project  # Filter by project

cerebro stats

Get overall cortex statistics.

cerebro stats

Returns project count, session count, commit count, TODO count, and recent activity metrics.

MCP commands

cerebro mcp

Start the MCP server. Works with any MCP-compliant client, including OpenCode, Claude, and Cursor. Reads from the cortex directory containing the config file.

cerebro mcp

Reads CORTEX_PATH to locate the cortex data dir (falls back to ~/Projects/cortex). For the CLI/TUI config, see Configuration.

TUI

cerebro tui

Launch the Terminal User Interface for browsing projects interactively.

cerebro tui

The Terminal User Interface shares data types with the command-line tool, cerebro-core, and reads the same cortex content that mdbook renders. A standalone binary cerebro-tui is also available for running the Terminal User Interface independently.

MCP tools reference

The cerebro MCP server provides 7 tools that allow AI assistants to query cortex data. All tools are thin wrappers over cerebro-core query operations.

Tool list

list_projects

List all tracked projects with their metadata.

Parameters:

NameTypeRequiredDescription
active_onlybooleanNoIf true, only return active projects. Default: true

Returns: array of project objects with name, repo_path, active status, and last activity timestamp.


read_project

Read combined generated and manual content for a specific project.

Parameters:

NameTypeRequiredDescription
namestringYesProject name to read

Returns: combined content including project config, sessions, commits, TODOs, and manual notes, covering status, next actions, and journal excerpts.


read_journal

Read a journal entry for a specific date.

Parameters:

NameTypeRequiredDescription
datestringYesDate in YYYY-MM-DD format

Returns: journal entry content for the specified date, or empty if no entry exists.


read_today

Read today’s journal entry.

Parameters: none

Returns: today’s journal entry content, or empty if no entry exists for today.


read_intent

Read intent/goals for a specific period.

Parameters:

NameTypeRequiredDescription
periodstringYesPeriod type: daily, weekly, monthly, or yearly
identifierstringYesPeriod identifier, such as 2026-04-15 for daily, 2026-W15 for weekly, 2026-04 for monthly, 2026 for yearly

Returns: intent/goals content for the specified period.


search_todos

Search TODO comments across all projects.

Parameters:

NameTypeRequiredDescription
keywordstringNoFilter by keyword: TODO, Needs Fixing, Hack, or Placeholder
projectstringNoFilter by project name

Returns: array of TODO items with path, line number, keyword type, and comment text.


get_stats

Get overall cortex statistics.

Parameters: none

Returns: statistics including project count, total TODO count, session count, commit count, and recent activity metrics.

Configuration

The MCP server reads CORTEX_PATH to locate the cortex data directory. If unset, it falls back to ~/Projects/cortex. Most users with the default layout don’t need to set it.

Start it from any MCP-compliant client. The example below uses OpenCode:

{
  "mcpServers": {
    "cerebro": {
      "command": "cerebro",
      "args": ["mcp"],
      "env": {
        "CORTEX_PATH": "/path/to/cortex"
      }
    }
  }
}

Configure the command and environment variables according to your client’s documentation. The server speaks standard MCP (JSON-RPC) and has no dependency on any specific client.

Command-line tool equivalents

Each MCP tool has a corresponding command-line tool command that returns the same data as human-readable output. If you don’t use an AI assistant, the command-line tool commands give you direct access to your cortex from the terminal.

MCP toolCommand-line tool equivalent
list_projectscerebro projects list
read_projectcerebro projects read <name>
read_journalcerebro journal read <date>
read_todaycerebro journal today
read_intentcerebro intent <period> <identifier>
search_todoscerebro todos
get_statscerebro stats

Troubleshooting

Common issues and solutions.

Installation

“Command not found: cerebro”

Make sure the cargo bin is in your PATH:

export PATH="$HOME/.cargo/bin:$PATH"

Add this to your shell profile, such as ~/.zshrc or ~/.bashrc, to persist.

“Couldn’t find cerebro

Run cargo install cerebro from the project directory:

cargo install --path .

Configuration

“Config file not found”

Create config.toml:

cp config.toml.example config.toml

Or create manually:

[settings]
opencode_db_path = "~/.local/share/opencode/opencode.db"
pi_sessions_path = "~/.pi/agent/sessions"
output_dir = "./content"

[[projects]]
name = "my-project"
repo_path = "~/Projects/my-project"
active = true

“Couldn’t parse config”

Check your TOML syntax:

  • Use = not :
  • String values need quotes: "path" not path
  • Arrays use brackets: [[projects]] not [projects]

Validate with:

cargo run -- build

“Repo not found”

Verify repo_path exists:

ls -la ~/Projects/my-project

Build

“No activity found”

Likely causes:

  • No git commits yet: Commit something first
  • No AI sessions: Only relevant if you have configured opencode_db_path or pi_sessions_path
  • No TODOs: Add a TODO or Needs Fixing comment

This is normal for new projects. Activity appears as you work.

“Build is slow”

First build can be slow on large repos. Subsequent builds use cache.

Force a fresh build:

cerebro build --fresh

Clear cache manually:

cerebro status
# Note the cache location
rm {cache_file}

“OpenCode database not found”

Set the correct path in config:

opencode_db_path = "~/.local/share/opencode/opencode.db"

Verify the file exists:

ls -la ~/.local/share/opencode/opencode.db

MCP server

“MCP tools not available”

Restart OpenCode after configuring the MCP server.

Set CORTEX_PATH if your cortex data dir is not at the default ~/Projects/cortex:

export CORTEX_PATH="~/Projects/my-data-dir"

Test the server directly:

cargo run -p cerebro-mcp

“No projects found in MCP”

Verify your config includes the project and it’s set to active = true.

Serving

“Port already in use”

Pick a different port:

cerebro serve --port 3001

“Dashboard not updating”

Rebuild with --fresh:

cerebro build --fresh

Then refresh your browser.

General

“Unexpected behavior”

Run with debug logging:

RUST_LOG=debug cargo run -- build

“It’s broken and the cause is unclear”

Clear everything and start fresh:

# Remove output
rm -rf ~/cerebro-dashboard

# Remove cache
rm -rf ~/Library/Caches/cerebro  # macOS
rm -rf ~/.cache/cerebro          # Linux

# Rebuild
cerebro build --fresh

Development setup

Prerequisites

  • Rust 1.85 or later
  • Cargo, included with Rust

Building

# Development build
cargo build

# Release build
cargo build --release

Testing

cargo test

Quality checks

# Format check
cargo fmt --check

# Lint check
cargo clippy -- -D warnings

# All quality checks
cargo check

Workspace structure

cerebro/
├── crates/
│   ├── cerebro/        # CLI tool
│   ├── cerebro-core/   # Shared types
│   ├── cerebro-mcp/    # MCP server
│   └── cerebro-tui/    # Terminal UI
├── docs/              # Documentation
└── book.toml         # mdbook config

Running locally

# Build and run
cargo run -- build

# With arguments
cargo run -- build --project my-project

MCP server

The MCP server lives in crates/cerebro-mcp/ and provides standard MCP tools for querying cortex data.

Building

cargo build --release -p cerebro-mcp

The binary is output to target/release/cerebro-mcp.

Running

# Via cargo
cargo run -p cerebro-mcp

# Or directly
./target/release/cerebro-mcp

Environment variables

VariableDefaultDescription
CORTEX_PATH~/Projects/cortex (MCP) / unset (CLI, TUI)Path to the cortex data directory. Used by cerebro-mcp to read generated content; legacy fallback for cerebro/cerebro-tui config lookup. The CLI/TUI prefer the XDG config (~/.config/cerebro/config.toml) and only fall through to CORTEX_PATH if no XDG config exists.
RUST_LOGinfoLog level: debug, info, warn, or error

Testing guide

Cerebro uses a multi-layer testing strategy across its four crates.

Running tests

cargo test --workspace          # All tests
cargo test -p cerebro-core      # Core library only
cargo test -p cerebro-mcp       # MCP server only
cargo test -p cerebro-tui       # TUI only
cargo test -- --nocapture       # Show stdout during tests

Test layers

Unit tests

Each module contains #[cfg(test)] blocks testing individual functions, methods, and state transitions. These are the fastest and most numerous tests.

Examples:

  • Collector parsing, including TODO regular expression matching and git commit parsing
  • Action enum serialization/deserialization
  • Key binding resolution
  • Input mode state checks
  • Config loading and validation

Integration tests

The TUI crate uses ratatui::backend::TestBackend to render components to an in-memory buffer and assert on the rendered content:

#![allow(unused)]
fn main() {
let backend = TestBackend::new(80, 24);
let mut terminal = Terminal::new(backend)?;
// Render component, assert buffer string
}

For full app lifecycle tests, construct Home directly with mock dependencies, call set_cerebro_config() and do_initial_load_sync().await, then render the terminal and assert against it.

Navigation tests verify home.view_name() changes, not just that text appears somewhere in the buffer, since sidebar text is always visible.

Behavior-driven development tests

Write user-facing scenarios in Gherkin with step definitions in tests/cucumber.rs. The BDD workflow:

  1. Write Gherkin scenarios describing user behavior in terms of what the user does and sees
  2. Write step definitions that assert against real component state, such as home.view_name()
  3. Run: must go red before implementation changes
  4. Implement to make it green
  5. Commit only when the full suite passes

Step definitions must never assert against buffer text that happens to match: that produces false positives. Always check component state directly.

System tests with Ghostty

The TUI has system-level tests using Ghostty devtools for:

  • Terminal lifecycle, including startup, shutdown, and panic recovery
  • Layout adaptation on resize
  • UI responsiveness during long operations

These tests run against the actual binary in a real terminal, not a mock backend.

Test coverage by crate

CrateUnitIntegrationBDDSystem
cerebroConfig, cache, generators
cerebro-coreCollectors, types, queries
cerebro-mcpServer setup
cerebro-tuiComponents, actions, keybindingsFull app renderUser scenariosGhostty lifecycle

Adding tests

Adding a new component: add at least one snapshot test using assert_buffer_snapshot! to verify rendered output.

Adding a new function or method: add unit tests for happy path and edge cases.

Fixing a bug: add a regression test that would have caught the bug.

Refactoring: ensure existing tests still pass. Add tests if coverage was zero.

AI workflow audit plan

Based on Dru Knox, Stop Prompting, Start Engineering, YouTube, February 25, 2026.

This document captures actionable infrastructure changes to improve how cerebro manages AI workflows. The goal is to treat AI context and session behavior as observable, measurable systems, not as opaque chat sessions.

Mindset: from individual contributor to tech lead

When using AI agents, the human role shifts from individual contributor to tech lead. The job is no longer writing all the code directly. It’s ensuring the team writes good code by maintaining standards, documentation, and quality gates.

This document notes this shift but requires no tool changes. It’s a framing device for the infrastructure decisions that follow.

Problem: Non-deterministic tooling waste

AI agents are non-deterministic. They repeat tasks, thrash between approaches, make unnecessary tool calls, and burn tokens on false paths. Without telemetry, this waste is invisible. Instrument the agent’s behavior to detect and eliminate waste programmatically, not by watching every session.

Audit Infrastructure

1. Session log analysis scripts

OpenCode stores session logs locally in SQLite at ~/.local/share/opencode/opencode.db. The database is already read for dashboard rendering. Add analysis scripts to extract waste patterns from session history.

Waste patterns to detect

PatternDescriptionSignal
ThrashingAgent switches approaches repeatedly without progressSame tool called >3x with similar args in one session
Retry loopsAgent retries after failures without changing strategycargo check fails, agent reruns same command
Over-toolingAgent uses tools when direct reasoning sufficesFile read followed by immediate file read of same content
Apology taxAgent apologizes and backtracksPhrases like “sorry,” “you’re absolutely right” in assistant messages
Token bloatContext window fills with redundant planningRepeated restatement of plan without new information

Proposed script: cerebro audit sessions

A new command-line tool subcommand, or standalone script in scripts/, that:

  1. Queries the opencode database for recent sessions
  2. Parses message history for waste patterns
  3. Outputs a summary report with:
    • Sessions analyzed
    • Waste events detected, grouped by category
    • Estimated token cost of waste
    • Suggested configuration changes

Example output:

Sessions analyzed: 12
Thrashing events: 3 (25% of sessions)
Retry loops: 7 (58% of sessions)
Over-tooling: 2 (17% of sessions)

Top suggestion: Add `cargo check` pre-validation to agent context
  Affected sessions: 5
  Waste pattern: Agent runs `cargo check`, sees error, proposes fix,
                 runs `cargo check` again without applying fix first.

2. Static analysis for hallucination prevention

As agents perform more divergent and inductive reasoning, the risk of hallucinated APIs, incorrect types, and phantom dependencies increases. Static analysis is the first line of defense: it catches nonsense before it compiles, before it runs, before it gets committed.

The project already enforces clippy::pedantic at the workspace level. This section proposes expanding that enforcement specifically for AI-generated code paths.

Current state

The project already forbids unwrap(), panic!(), and expect() in production code. This is an excellent baseline. Extend this philosophy.

Proposed additions

CheckPurposeHow
Import validationPrevent phantom crate referencescargo check in CI must pass before any PR
Type strictnessPrevent inferred-type hallucinationsEnable clippy::pedantic lints that reject implicit conversions
Documentation coverageForce agents to document public APIscargo doc --no-deps must pass without warnings
Dead code detectionCatch abandoned experimentsclippy::dead_code as deny, not warn
TODO/Needs Fixing enforcementPrevent permanent placeholder codeAlready exists; ensure it runs on AI-generated commits too

Pre-flight hook for agent sessions

Consider a lightweight cargo alias or script that agents run before submitting:

# In .cargo/config.toml or agent context
[alias]
preflight = "fmt --check && clippy --workspace -- -D warnings && check"

Instruct agents to run cargo preflight before declaring a task complete. This catches hallucinations at the agent’s workstation, not in CI.

3. Configuration to prevent thrashing

OpenCode and similar agents accept configuration that shapes their behavior. Codify anti-thrashing settings in the project’s AGENTS.md and explore opencode configuration options.

Token budget awareness

SettingSuggestionRationale
Context window limitExplicitly state the project’s preferred maxPrevents agents from stuffing irrelevant files into context
Tool call budgetConfigure max sequential tool callsForces agent to reason rather than search
Retry limitCap retries at 2 with forced pausePrevents infinite retry loops on flaky operations

Context hygiene rules

Add to AGENTS.md:

## Agent Efficiency Rules

1. **Run `cargo preflight` before every completion claim.**
2. **If a command fails twice with the same error, stop and ask.**
3. **Do not read a file you already read in this session unless it changed.**
4. **Before using a new crate or API, verify it exists in `Cargo.lock`.**
5. **Keep context focused: only include files relevant to the current task.**

4. CI/CD Integration

Woodpecker CI is already in use. The audit plan should extend CI to catch AI workflow regressions.

Proposed CI checks

StageCheckTrigger
Lintcargo clippy --workspace -- -D warningsEvery push
Formatcargo fmt --checkEvery push
Doccargo doc --no-depsEvery push
Testcargo test --workspaceEvery push
AuditRun session waste analyzer on last 7 daysWeekly cron, or run manually

The weekly audit stage is lightweight: it queries the local opencode database, or a centralized copy, and posts a summary comment on the PR if waste patterns spike.

5. Plugin and Linter Integration

Rather than building custom LLM-as-judge evals, leverage existing tools and explore opencode plugins that reduce waste.

Tool Inventory

ToolCurrent UseAI Workflow Enhancement
clippyLint enforcementAdd lints that catch common AI mistakes, such as unused imports from hallucinated code
cargo-denyLicense checkingCould extend to detect unexpected crate additions
lefthookPre-commit hooksAdd hook that warns if AGENTS.md context is stale
dprintMarkdown formattingEnsure AGENTS.md and context files stay parseable

Opencode plugin opportunities

The opencode ecosystem may support plugins that:

  • Intercept tool calls and cache file reads for the session duration
  • Enforce a “budget” of tool calls per task
  • Auto-run cargo preflight before allowing the agent to report success
  • Summarize session waste and append it to the cortex journal

These are research items. This plan flags them for investigation.

Measurement: tracked metrics

The audit infrastructure collects:

MetricSourceTarget
Session durationopencode.dbReduce median by 20%
Tool calls per sessionopencode.dbReduce median by 30%
cargo check failures before successopencode.db + git logReduce retry rate below 10%
Clippy warnings on AI-generated commitsgit diff + cargo clippyZero warnings
Agent backtracks, such as saying “sorry” or “you’re right”opencode.db message textReduce by 50%

Immediate actions

  1. Write the session analyzer script. A standalone Rust binary or Python script that reads opencode.db and outputs waste statistics.
  2. Update AGENTS.md with agent efficiency rules. Codify the anti-thrashing guidelines.
  3. Add cargo preflight alias. Make it trivial for agents to self-check.
  4. Schedule weekly CI audit job. Run the analyzer and surface trends.
  5. Research opencode plugin API. Determine if custom plugins can enforce tool budgets.

Deferred actions

  • Evals / statistical testing: Not pursued. The cost of LLM-as-judge evals outweighs the benefit for this project. The project uses deterministic static analysis instead.
  • Automated context updates via PR scanning: Interesting but requires a stable context format first. Revisit after AGENTS.md structure matures.

References

Architecture

Cerebro is a Rust workspace with four crates that share types and read from a common cortex data directory.

System overview

flowchart TB
    subgraph cerebro_repo["~/Projects/cerebro (source code)"]
        CLI_CRATE["crates/cerebro<br/>CLI binary"]
        CORE_CRATE["crates/cerebro-core<br/>shared types"]
        MCP_CRATE["crates/cerebro-mcp<br/>MCP library"]
        TUI_CRATE["crates/cerebro-tui<br/>TUI binary"]
        DOCS["docs/<br/>tool documentation"]
    end

    subgraph cortex_dir["~/Projects/<name> (your cortex)"]
        CFG["config.toml"]
        AUTO["content/ (auto-generated)<br/>index.md, projects/, journal/"]
        MANUAL["content/ (manual)<br/>intent/, notes/, SUMMARY.md"]
        BOOK["book/<br/>rendered HTML"]
        AGENTS["AGENTS.md<br/>edit boundaries"]
    end

    subgraph external["External data sources"]
        GIT["project git repos"]
        OODB["opencode sessions.db"]
    end

    subgraph consumers["Consumers"]
        MDBOOK["mdbook"]
        OPENCODE["OpenCode"]
        TERMINAL["Terminal user"]
    end

    CLI_CRATE -->|scrapes| GIT
    CLI_CRATE -->|queries| OODB
    CLI_CRATE -->|reads| CFG
    CLI_CRATE -->|writes| AUTO

    TUI_CRATE -->|reads same data| AUTO
    TUI_CRATE -->|reads| MANUAL
    TUI_CRATE -->|uses types| CORE_CRATE

    MCP_CRATE -->|reads| AUTO
    MCP_CRATE -->|reads| MANUAL

    MANUAL -. "human edits" .-> MANUAL
    AGENTS -. "defines boundaries" .-> MANUAL

    AUTO -->|mdbook src| MDBOOK
    MANUAL -->|mdbook src| MDBOOK
    MDBOOK -->|renders| BOOK

    OPENCODE <-->|JSON-RPC| MCP_CRATE
    TERMINAL <-->|interactive| TUI_CRATE

    style CLI_CRATE fill:#4a9eff,color:#fff
    style TUI_CRATE fill:#9b59b6,color:#fff
    style MCP_CRATE fill:#ff6b6b,color:#fff
    style AUTO fill:#ff8
    style MANUAL fill:#f8f
    style BOOK fill:#8f8

The two repos

cerebro at ~/Projects/cerebro

The source code repository. Contains:

  • Command-line tool binary at crates/cerebro/: Scrapes data sources and generates markdown
  • Shared types at crates/cerebro-core/: Config, ProjectContext, Storage trait, collectors, queries
  • Model Context Protocol, or MCP, server at crates/cerebro-mcp/: JSON-Remote Procedure Call, or RPC, server for OpenCode
  • Terminal User Interface, or TUI, at crates/cerebro-tui/: Ratatui terminal UI for interactive browsing
  • Documentation at docs/: mdBook docs about the cerebro tool itself

Your cortex

The cortex, named whatever you choose: cortex in this project’s case. Contains:

  • config.toml: Project list and settings. Read by cerebro.
  • content/: mdBook source. A mix of auto-generated and manual content.
  • book/: Rendered HTML output
  • AGENTS.md: Defines edit boundaries for AI agents
  • book.toml: mdBook configuration

The four binaries

cerebro, the command-line tool

cerebro build            # Scrape repos, generate markdown
cerebro build --fresh    # Ignore cache
cerebro build --project X  # Single project
cerebro status           # Show cache status
cerebro serve            # Spawn mdbook in output_dir
cerebro serve --port N   # Custom port
cerebro mcp              # Start MCP server
cerebro tui              # Launch terminal UI

Data flow:

  1. Reads config.toml from your cortex
  2. For each project: scrapes git, queries OpenCode DB, scans TODOs, reads manual notes
  3. Writes markdown to output_dir. The default is ./content.
  4. Cache stored alongside config to avoid redundant scraping

cerebro-mcp, the Model Context Protocol server

# Started by OpenCode via opencode.json:
#   "command": ["cerebro", "mcp"]
# Or standalone:
cerebro-mcp    # Reads CORTEX_PATH env var; falls back to ~/Projects/cortex

Tools provided:

  • read_project: Combined generated + manual content for a project
  • list_projects: All tracked projects with metadata
  • read_journal: Journal entry by date
  • read_today: Today’s journal entry
  • read_intent: Goals by period. Options are daily, weekly, monthly, or yearly.
  • search_todos: Search TODOs across projects
  • get_stats: Overall statistics

Path resolution:

  • CORTEX_PATH env var. Optional: points to the cortex data dir; falls back to ~/Projects/cortex if unset.
  • Reads generated content from {CORTEX_PATH}/content/
  • Reads manual notes from {CORTEX_PATH}/content/notes/ and {CORTEX_PATH}/content/intent/

cerebro-tui, the Terminal UI

Interactive terminal UI for browsing projects without opening a browser. Shares cerebro-core types with the command-line tool and reads the same cortex content that mdbook renders.

Views:

  • Dashboard: Project overview with summary cards and scrollable project table
  • Projects: Tabbed Sessions/Commits/TODOs per project, detail modals, manual note editor
  • Journal: Date-grouped entries with activity indicators, entry editor
  • TODOs: Cross-project table with project/keyword filter cycling, text search
  • Config: Project list with active toggle, add-project form, Tom’s Obvious Minimal Language, or TOML, persistence

See TUI Architecture for the component pattern and data flow.

Content boundaries

The cortex’s content/ has a strict split between auto-generated and manual content:

Auto-generated: cerebro writes, humans don’t edit

FileContent
index.mdDashboard homepage with project cards
projects/{name}.mdPer-project status pages
journal/{year}/{mm}/{dd}.mdDaily activity logs
today.mdLast 24 hours of activity
this-week.mdLast 7 days of activity

Manual: humans write, cerebro doesn’t modify

FileContent
intent/daily/Daily goals
intent/weekly/Weekly goals
intent/monthly/Monthly goals
intent/yearly/Yearly goals
notes/Evergreen notes and documentation
notes/projects/Per-project manual notes
SUMMARY.mdmdBook navigation structure

An AGENTS.md file in your cortex enforces the boundary, instructing AI agents which files are safe to overwrite and which are human-only.

Cron workflow

0 5,9 * * *    cerebro build && mdbook build
59 23 * * *    cerebro build && mdbook build

Runs from your cortex. Scrape → generate → render, three times daily.

Shared type system

All binaries share types from cerebro-core:

ProjectConfig     : Name, repo_path, active flag
ProjectContext    : Full context: commits, sessions, todos, notes
ManualNotes       : Status, next actions, journal excerpt
Config            : Settings + project list
Cache             : Timestamps for incremental scraping

The TUI uses these same types to render views, ensuring consistency between what you see in the browser via mdbook, the terminal via the TUI, and what OpenCode reads via MCP.

Data flow pipeline

flowchart TD
    subgraph Config["Configuration"]
        C[config.toml]
    end

    subgraph Collect["Collectors"]
        O[OpenCode] --> S[Session history]
        G[Git] --> CMT[Commits, files]
        T[TODOs] --> TC[TODO/FIXME comments]
        N[Notes] --> MN[Manual notes]
    end

    subgraph Generate["Generators"]
        D[Dashboard] --> MD[Markdown]
        J[Journal] --> MJ[Markdown]
        P[Periodic] --> MP[Markdown]
        PR[Project] --> MPR[Markdown]
    end

    subgraph Out["Output"]
        ODIR[content/]
    end

    C --> Collect
    Collect --> Generate
    Generate --> Out

Collection sources

SourceData Collected
OpenCodeSession history, AI interactions
GitCommits, file changes, branch activity
TODOsTODO, FIXME, HACK, XXX comments
Manual NotesStatus, journal entries, intent

Crate details

cerebro

The main command-line tool binary. Entry point that:

  • Parses command-line arguments via clap
  • Coordinates collection and generation
  • Manages the file-based cache
  • Spawns the TUI and MCP server as subcommands
crates/cerebro/src/
├── main.rs          # Entry point, clap subcommands
├── cli.rs           # CLI argument definitions
├── config.rs        # Configuration loading
├── cache.rs         # Cache management
└── generators/      # Output generation (dashboard, project, journal, periodic)

cerebro-core

Shared library used by all other crates. Contains:

  • Types: ProjectConfig, ProjectContext, ManualNotes, Config, Cache
  • Traits: Storage, Git, Database for dependency injection
  • Collectors: OpenCode, Git, TODO, and manual notes collection implementations
  • Queries: Read operations used by command-line tool subcommands and MCP tools
crates/cerebro-core/src/
├── lib.rs           # Type definitions, re-exports
├── storage.rs       # Storage, Git, Database traits
├── collectors/      # Data collection implementations
└── queries/         # Read operations (projects, journal, todos, intent, stats)

cerebro-mcp

Model Context Protocol, or MCP, server for OpenCode integration. Provides JSON-RPC tools that allow AI assistants to query cortex data.

crates/cerebro-mcp/src/
├── server.rs        # MCP server setup and event loop
└── tools/           # Tool implementations (re-export cerebro-core queries)

cerebro-tui

Ratatui terminal UI for interactive project browsing. Uses the Component + Action pattern with async tokio event loop.

crates/cerebro-tui/src/
├── app.rs           # App struct, initialization
├── action.rs        # Action enum, View, KeyBinding, InputMode
├── tui.rs           # Terminal setup, event loop
├── cli.rs           # TUI-specific CLI args
├── errors.rs        # Error handling
├── lib.rs           # Library re-exports
└── components/      # UI components (home, dashboard, projects, journal, todos, config, sidebar, help, widgets)

Architecture diagrams

Architectural diagrams for cerebro, following the C4 model and Simon Brown’s diagramming principles.

Created with D2. Source files live in diagrams/assets/current/.

For standalone SVG generation, such as for sharing, run just diagrams.

Current architecture

System context, C4 level 1

Shows cerebro, the developer, external systems such as git repos and the OpenCode DB, the cortex data directory, and AI agents connected via MCP.

Note: mdbook is an implementation detail of cortex, rendering content/ to book/, not a consumer. The real consumers are AI agents, such as OpenCode and Pi, via the MCP server, and the developer via the Terminal User Interface.

Source: diagrams/assets/current/01-system-context.d2

Data flow pipeline

4-phase pipeline: scrape, process, store, consume. Shows how data flows from external sources through collectors and generators into the cortex, then to consumers, including AI agents via MCP and the Terminal User Interface.

Source: diagrams/assets/current/02-data-flow.d2

Component structure, C4 level 3

Crate-level overview with module detail layers.

LayerDescription
Crate Overview4 crates + cross-crate dependencies
cerebro modulesCommand-line tool binary module structure
cerebro-core modulesShared types library
cerebro-mcp modulesMCP server module structure
cerebro-tui modulesTerminal User Interface binary module structure

Source: diagrams/assets/current/03-components.d2

Type model

Core types from cerebro-core and their relationships.

Source: diagrams/assets/current/04-data-model.d2

Diagram conventions

All diagrams follow Simon Brown’s principles:

  • Title: “Diagram Type: Scope” on every diagram
  • Legend: Explains shapes, colors, line styles
  • Directional arrows: One-way only, with specific labels
  • Explicit types: [Person], [Software System], [Container], [Component]
  • Stand-alone: Makes sense without a presenter

All diagrams import nord-config.d2 for consistent Nord dark theming via D2’s theme-overrides system.

Terminal User Interface architecture

The cerebro TUI, in crates/cerebro-tui, is a Ratatui-based terminal app that provides interactive browsing of project activity data. It uses the Component + Action architecture pattern recommended by the Ratatui community.

Architecture pattern

Component trait

All UI components implement the Component trait:

#![allow(unused)]
fn main() {
pub trait Component {
    fn init(&mut self, area: Size) -> Result<()>;
    fn handle_events(&mut self, event: Option<Event>) -> Result<Option<Action>>;
    fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>>;
    fn handle_mouse_event(&mut self, mouse: MouseEvent) -> Result<Option<Action>>;
    fn update(&mut self, action: Action) -> Result<Option<Action>>;
    fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()>;
    fn as_any_mut(&mut self) -> &mut dyn Any;
    fn help_entries(&self) -> Vec<HelpEntry>;
}
}

Each component encapsulates its own state, including scroll positions, filter selections, and text input focus, and communicates with other components through the Action dispatch system.

Action dispatch

The Action enum is the single communication channel between components and the Home orchestrator:

Component ──Action──> Home ──Action──> Component

Actions fall into these categories:

CategoryExamples
LifecycleTick, Render, Resize, Quit, ClearScreen
Data loadingDataLoaded, LoadError, TriggerRefresh, RefreshComplete
NavigationSwitchView, SelectProject, SwitchTab
UI stateShowPreview, ClosePreview, SetInputMode
ConfigToggleProjectActive, SubmitAddProject, ConfigUpdated
BuildTriggerBuild, BuildOutput, BuildComplete, CloseBuildLog
Text inputStartJournalEntry, StartManualNote, SaveInput, CancelInput

Key binding system

A context-based system resolves key bindings to prevent collisions:

ContextKeysPurpose
Globalq, r, b, ?, Space, 1-5Always active: quit, refresh, build, help, leader key, view switching
Sidebarj/k, arrows, Tab, lNavigate sidebar list, switch focus to content
ContentTab, Shift+Tab, hSwitch focus back to sidebar

The leader key, Space, followed by d/p/j/t/c provides an alternative view switching path.

Component hierarchy

Home (orchestrator)
├── Sidebar (project list, view navigation)
├── Dashboard (summary cards, project table)
├── Projects (tabbed sessions/commits/todos, note editor)
├── Journal (date-grouped entries, entry editor)
├── Todos (filterable table, search)
├── Config (project toggle list, add-project form)
├── Help (keybinding overlay)
└── Widgets (shared)
    ├── Spinner (loading indicator)
    ├── Toast (notifications)
    ├── EmptyState (no-data display)
    ├── SummaryCard (dashboard stats)
    ├── BuildLog (build output modal)
    └── Modal (generic overlay)

Data flow

The TUI follows a Flux-inspired data flow:

1. Home.do_initial_load_sync() collects data from cortex
2. Action::DataLoaded(contexts) dispatched to all components
3. Each component stores relevant data in its own state
4. User interaction → Component.handle_key_event() → Action
5. Home.update() processes Action, may dispatch follow-up Actions
6. Components receive Actions via Component.update()
7. Frame render → Component.draw() reads from local state

Async operations

Long-running operations spawn tokio tasks and report back via Actions:

  • Data refresh: trigger_refresh() spawns collect_all() in a tokio task, sends DataLoaded or LoadError on completion
  • Config writes: spawn_config_toggle() writes TOML via toml_edit, sends ConfigUpdated
  • Build: TriggerBuild spawns cerebro build as a subprocess, streams output via BuildOutput events

Input modes

The TUI supports three input modes tracked by InputMode:

ModeDescriptionActive when
NavigationDefault: keys control UIAlways, except during text editing
JournalEntryMulti-line text editing with ratatui-textareaJournal view, editing an entry
ManualNoteMulti-line text editing with ratatui-textareaProjects view, editing status/next sections

In editing modes, the text input widget intercepts most navigation keys. Escape cancels input and returns to Navigation mode.

Testing strategy

The TUI uses three testing layers:

LayerToolPurpose
Unit tests#[cfg(test)]Component state transitions, action handling, key binding parsing
Integration testsratatui::backend::TestBackendRender full app to buffer, assert on content
BDD testsCucumber, defined in tests/cucumber.rsUser-facing scenarios in Gherkin
System testsGhostty devtoolsTerminal lifecycle, resize, responsiveness

Integration tests construct Home directly, call set_cerebro_config() and do_initial_load_sync().await, then render and assert against the buffer. BDD tests assert against real component state, such as home.view_name(), not buffer text.

Architecture decisions

This directory records the architectural decisions made during the development of Cerebro. Each decision follows the Nygard ADR format: context, decision, consequences.

Decisions

#TitleStatus
0001Record architecture decisionsAccepted
0002Monorepo structure with four cratesAccepted
0003Four data collectorsAccepted
0004Markdown output with mdbookAccepted
0005MCP server for OpenCodeAccepted
0006Cache strategyAccepted
0007TOML configuration formatAccepted
0008TODO regular expression patternAccepted
0009Storage trait for DIAccepted
0010Why Cerebro uses MCPAccepted

1. Record architecture decisions

Date: 2026-04-22

Status

Accepted

Context

The project needs to record the architectural decisions made on this project.

Decision

Architecture Decision Records are used, as described by Michael Nygard in his article “Documenting Architecture Decisions.”

Consequences

See Michael Nygard’s article, linked in the preceding section. For a lightweight ADR toolset, see Nat Pryce’s adr-tools.

2. Monorepo structure with four crates

Date: 2026-04-22

Status

Accepted

Context

Cerebro needs to support multiple use cases: command-line tool usage for building dashboards, library usage for other tools, OpenCode MCP integration, and an interactive terminal UI for browsing project data.

Decision

This project uses a Rust workspace with four crates:

  • cerebro: command-line tool, the main binary
  • cerebro-core: Shared types, traits, collectors, and queries, the library crate
  • cerebro-mcp: MCP server for OpenCode integration, a binary crate
  • cerebro-tui: Ratatui terminal UI for interactive browsing, a binary crate

Consequences

Pros

  • Clear separation between command-line tool, library, MCP, and Terminal User Interface concerns
  • other tools can use cerebro-core as a library
  • Each crate can evolve independently
  • Terminal User Interface shares types with command-line tool, ensuring consistency across delivery surfaces

Cons

  • Workspace complexity
  • More build artifacts to manage

Notes

See crates/ directory for actual structure.

3. Four data collectors

Date: 2026-04-22

Status

Accepted

Context

Cerebro aggregates signals from development activity to generate context. The design must specify which data sources to collect from.

Decision

Cerebro collects data from four sources:

SourceImplementationData
OpenCodeSQLite via opencode_db_pathSession history
Gitgit2 crateCommits, modified files
TODOsRegex scan on source filesTODO, Needs Fixing, Hack, and Placeholder comments
Manual Notesnotes/projects/{name}.mdStatus, journal, intent

Consequences

Pros

  • Comprehensive signal aggregation
  • Each collector is independent
  • Manual notes provide human context

Cons

  • Git collection can be slow on large repos
  • TODO regular expression may false-positive on strings

Notes

The collectors/mod.rs module orchestrates the collectors. Each is async and can run in parallel.

4. Markdown output with mdbook serving

Date: 2026-04-22

Status

Accepted

Context

Cerebro generates a personal dashboard. The design must determine the output format and serving method.

Decision

Output is markdown files served via mdbook:

  • Generators produce .md files
  • mdbook serves as a local web server
  • Output location configurable via config.toml

Output structure

{dashboard_path}/
├── index.md                    # Overview
├── projects/
│   └── {name}.md            # Per-project pages
├── today.md                  # Today's activity
├── this-week.md              # Weekly activity
└── journal/
    └── {year}/
        └── {mm}/
            └── {dd}.md      # Daily journal

Consequences

Pros

  • Human-readable output
  • Easy to version control
  • mdbook provides search/navigation

Cons

  • Requires mdbook for serving
  • Static generation without live updates

Notes

Default port is 3000. Use cerebro serve --port X to customize.

5. MCP server for OpenCode integration

Date: 2026-04-22

Status

Accepted

Context

AI assistants (OpenCode) should be able to query the dashboard directly. This requires a tool protocol.

Decision

The cerebro-mcp crate implements an MCP server:

Tools exposed

ToolPurpose
read_projectRead project info + generated page
list_projectsList all tracked projects
get_statsOverall statistics
read_journalRead journal entry by date
read_todayRead today’s journal
read_intentRead intent for daily, weekly, monthly, or yearly periods
search_todosSearch TODOs across projects

Configuration

Reads CORTEX_PATH to locate the cortex data directory; falls back to ~/Projects/cortex if unset. (See ADR-0011 for the CLI/TUI config priority.)

Consequences

Pros

  • AI can access context directly
  • Enables AI-assisted workflow
  • Standard protocol

Cons

  • MCP SDK dependency
  • Server maintenance

Notes

Binary: target/release/cerebro-mcp. Configure in OpenCode’s opencode.json.

6. Cache strategy for collectors

Date: 2026-04-22

Status

Accepted

Context

Collectors (git, opencode, todos) can be expensive. Avoid re-running them on every build.

Decision

Cerebro uses file-based caching:

  • Cache stored in cache.json in system cache directory
  • Each entry tracks: opencode_last_query, git_last_scan, todo_last_scan
  • --fresh flag bypasses cache entirely
  • --project <name> limits to specific project

Cache Invalidation

Cerebro invalidates the cache when:

  1. --fresh flag for user override
  2. Timestamps in cache.json show data is stale
  3. Manual cerebro status shows cache status

Consequences

Pros

  • Fast subsequent builds
  • Respects user intent

Cons

  • Stale data if TTL too long
  • System cache dependency

Notes

See cache.rs for implementation.

7. TOML configuration format

Date: 2026-04-22

Status

Accepted

Context

Cerebro needs a user-friendly configuration format that supports multiple projects and settings.

Decision

Cerebro uses TOML with two sections:

[settings]
opencode_db_path = "..."        # Path to AI tool's SQLite DB (optional)
output_dir = "..."             # Dashboard output directory

[[projects]]
name = "project-name"         # Display name
repo_path = "~/Projects/..."   # Git repository path
active = true                  # Include in build

Cerebro reads manual notes from a fixed path derived from the output directory ({output_dir}/notes/projects/{name}.md) rather than a per-project note_path field.

Consequences

Pros

  • TOML is human-readable and well-supported in Rust
  • Clear separation between settings and project definitions
  • Easy to add new fields without breaking existing configs

Cons

  • Requires toml parsing dependency
  • ~ path expansion needed

Notes

Parsed in cerebro-core via toml crate. ~ expansion in config.rs.

8. TODO regular expression pattern and file scanning

Date: 2026-04-22

Status

Accepted

Context

Cerebro must find TODO, Needs Fixing, Hack, and Placeholder comments reliably in source code while avoiding false positives.

Decision

Regex pattern:

(?i)\b(TODO|FIXME|HACK|XXX)\b[\s:]*(.*)$

Features:

  • Case-insensitive matching using the (?i) flag
  • Word boundary anchors using \b
  • Captures keyword + optional text after : or whitespace

File scanning:

  • Uses ignore::WalkBuilder to respect .gitignore
  • Skips binary/non-source extensions (png, jpg, pdf, zip, etc.)

Sorting priority from highest to lowest covers Needs Fixing, then TODO, then Hack, then Placeholder.

Consequences

Pros

  • Case-insensitive catches todo:, TODO:, Todo:
  • Respects gitignore automatically
  • Skips common false positives, such as minified JS and images

Cons

  • Won’t catch multi-line comments
  • Won’t catch TODO in strings without keyword prefix

Notes

See collectors/todos.rs for implementation.

9. Storage trait for dependency injection

Date: 2026-04-22

Status

Accepted

Context

Collectors need to read files and access git/OpenCode databases. Collectors must support testing without real filesystems.

Decision

Cerebro defines traits for dependency injection:

#![allow(unused)]
fn main() {
pub trait Storage: Send + Sync {
    async fn exists(&self, path: &Path) -> bool;
    async fn read_to_string(&self, path: &Path) -> Result<String>;
    // ...
}

pub trait Git: Send + Sync {
    async fn commits(&self, repo_path: &Path) -> Result<Vec<GitCommit>>;
    async fn modified_files(&self, repo_path: &Path) -> Result<Vec<FileChange>>;
}
}

Implementations:

  • TokioStorage: Uses tokio for async file I/O
  • Git2: Uses git2 crate for git operations, with commits limited to 20 per project
  • SqlxDb: Uses sqlx for OpenCode SQLite queries

Consequences

Pros

  • Testable without real filesystem
  • Swap implementations, such as mock storage for tests
  • Clear abstraction boundaries

Cons

  • Trait indirection overhead
  • More complex DI setup

Notes

See cerebro-core/src/storage.rs.

Why Cerebro uses Model Context Protocol, or MCP: The right tool for the job

The problem to solve

The cerebro MCP server solves this specific problem:

Provide AI assistants with standardized, secure access to cerebro’s aggregated developer activity data to enable context-aware assistance during coding tasks.

More specifically:

  • Cerebro collects and processes data from: OpenCode sessions, git commits, TODO comments, manual notes, etc.
  • A cortex, located via CORTEX_PATH (defaulting to ~/Projects/cortex), stores this data
  • The value isn’t just in collecting it, but in making it accessible to reduce context switching
  • AI assistants, such as those in OpenCode, Claude Code, and others, need to query this data to provide relevant, personalized assistance

Why MCP is the right tool

1. MCP matches the data access pattern perfectly

MCP has three core concepts that align exactly with cerebro’s needs:

Resources, for data exposure:

  • Cerebro’s primary asset is its data store
  • MCP Resources are perfect for exposing:
    • Project information via the projects resource URI
    • Journal entries via the journal resource URI with a date parameter
    • Intent and goals via the intent resource URI with period and identifier parameters
    • TODO items via the todos resource URI with a project filter
    • Search results via the search resource URI with a query parameter

Tools, for actions:

  • Beyond reading data, users may want to trigger actions:
    • cerebro_build - Trigger a dashboard rebuild
    • add_journal_entry - Add a manual note
    • update_project_status - Mark project as active/inactive
    • refresh_cache - Force data re-collection

Prompts, for predefined interactions:

  • Common query patterns to define:
    • summarize_recent_activity
    • get_project_status
    • find_related_todos

2. Standards-based integration eliminates custom work

Without MCP, cerebro would need to:

  • Build custom HTTP/WebSocket APIs for each assistant type
  • Document and maintain separate integrations for OpenCode, Claude Code, etc.
  • Handle authentication, rate limiting, and error handling per integration

With MCP:

  • Implement the MCP protocol once
  • Any MCP-compatible assistant can automatically discover and use cerebro’s capabilities
  • OpenCode, Claude Code, and other MCP hosts handle the client-side complexity
  • Single source of truth for what data/actions are available

3. Security and boundaries by design

MCP provides natural security boundaries:

  • The assistant can only access what the MCP server explicitly exposes
  • No risk of arbitrary database access or unintended side effects
  • Tool invocations require explicit approval, configurable via permissions
  • Read-only resources vs. write-capable tools are clearly distinguished

4. Layering on existing infrastructure is efficient

Cerebro already had:

  • Data collection logic (OpenCode, git, TODOs)
  • Processing and storage systems
  • Dashboard generation algorithms
  • Query capabilities for the web interface

The MCP server is a thin adaptation layer that:

  • Exposes existing capabilities through standard MCP interfaces
  • Requires minimal new business logic
  • Leverages all the existing data processing work
  • Avoids re-implementing core cerebro features

5. Enables ecosystem benefits

By adopting MCP, cerebro gains:

  • Compatibility with growing list of MCP-hosted assistants
  • Future-proofing as more tools adopt the standard
  • Ability to benefit from MCP ecosystem improvements
  • Reduced integration burden for users trying multiple assistants

Why it’s not just a Retrieval-Augmented Generation problem

While a Retrieval-Augmented Generation, or RAG, system could use cerebro’s data, Model Context Protocol is more appropriate because:

RAG is a pattern. MCP is a protocol.

  • Retrieval-Augmented Generation describes how to retrieve and use context within a single Large Language Model, or LLM, interaction
  • MCP defines how systems connect to provide that context and more

MCP is broader than just retrieval:

  • RAG focuses on fetching relevant information for a prompt
  • MCP also supports invoking actions, through tools, and defining interaction patterns, through prompts
  • Cerebro isn’t just about reading data - it may want to allow assistants to trigger builds, add notes, etc.

They can work together:

  • An agent could use MCP to discover what cerebro offers
  • Then use RAG techniques to find the most relevant parts of large datasets
  • Or use MCP resources as the data source for a RAG system

Concrete example: How an assistant uses Cerebro MCP

When a user asks in OpenCode: “What work happened yesterday on the web-project?”

  1. OpenCode, acting as MCP host, connects to cerebro-mcp server
  2. Server advertises available resources/tools via MCP protocol
  3. OpenCode sees resources like: cerebro://journal/2026-04-16, cerebro://projects/web-project
  4. OpenCode reads the journal resource for yesterday
  5. Optionally reads project-specific data
  6. Combines this with the user’s question to form a complete prompt for the LLM
  7. LLM responds with a summary of yesterday’s work on web-project
  8. If the user wants to take action, for example marking this project as inactive, OpenCode can invoke the appropriate MCP tool

Addressing the “RAG-shaped problem” intuition

You’re right that at its core, this is about making data available to augment LLM context - which is what RAG does. However:

  • MCP solves the connection and discovery layer: how to get the data to the assistant
  • RAG solves the relevance filtering layer: how to find the right data within a large corpus
  • Cerebro needs both layers:
    • MCP provides standardized access to the cerebro data store
    • RAG-like techniques could help cerebro rank journal entries by relevance, or help the assistant process large result sets

MCP is the right foundational choice because it establishes the standard connection mechanism. Whether that data then gets used via simple retrieval, RAG, or other methods is a separate concern that MCP doesn’t prescribe—it simply makes the data available in a standardized way.

Conclusion

The cerebro MCP is the right tool for the job because:

  1. Job: Make cerebro’s developer activity data accessible to AI assistants in a standard, secure way
  2. MCP Fit: MCP’s Resources/Tools/Prompts map directly to cerebro’s data access and action needs
  3. Advantages: Standards-based, secure, leverages existing infrastructure, enables ecosystem benefits
  4. Not Overkill: It’s not unnecessarily complex—it’s the minimally sufficient standard protocol for this exact use case
  5. Complementary: Works well with RAG techniques rather than replacing them

This isn’t just following trends. It applies the right tool, MCP, to the right problem: standardized AI assistant access to structured personal data stores.

11. XDG as default config location; CORTEX_PATH becomes a legacy fallback

Date: 2026-06-06

Status

Accepted. Supersedes the implicit decision in 0007: TOML configuration format (which assumed CORTEX_PATH would point at the config).

Context

The cerebro CLI and TUI load config.toml via this priority:

CORTEX_PATH env var > --config CLI flag > XDG config dir > ./config.toml

That ordering made CORTEX_PATH the de-facto requirement: a user who didn’t set it would either find an XDG config (if one happened to exist) or fail. The README and onboarding docs reflected this by instructing users to “place config.toml in your cortex” — i.e., the directory pointed to by CORTEX_PATH.

In practice, this means the user had to:

  1. Decide on a cortex location.
  2. Set CORTEX_PATH in their shell rc.
  3. Restart the shell.
  4. Only then would the binary find the config.

If any step was missed, the binary either picked up an unintended file (the ./config.toml fallback) or errored out. The MCP server kept working because it falls back to ~/Projects/cortex, but the CLI/TUI did not — they sat silently on an absent config.

The principle of least surprise: a freshly installed tool should not require environment variables to do its job. The XDG base-directory spec already gives us a sensible default: $XDG_CONFIG_HOME/cerebro/config.toml, falling back to $HOME/.config/cerebro/config.toml when XDG_CONFIG_HOME is unset. The same path works on every platform, which avoids the surprise of dirs::config_dir() returning ~/Library/Application Support on macOS for users coming from Linux. The CORTEX_PATH mechanism was solving two unrelated problems at once (where is my config, where is my data) and the conflation was the source of the confusion.

Decision

The CLI and TUI (cerebro, cerebro-tui) use this new resolution order:

  1. --config <path> CLI flag — explicit override, always wins.
  2. XDG config dir ($XDG_CONFIG_HOME/cerebro/config.toml, or $HOME/.config/cerebro/config.toml if XDG_CONFIG_HOME is unset) — the default. Users who do nothing get this. Same path on every platform.
  3. CORTEX_PATH env var — legacy fallback. If a user already has CORTEX_PATH pointing at a directory that contains config.toml, it still works.
  4. ./config.toml in the current working directory — last-resort fallback (unchanged).

The MCP server (cerebro-mcp) is unchanged: it still uses CORTEX_PATH to locate the cortex data directory (where generated content/ lives) and falls back to ~/Projects/cortex. This is a separate concern from config and was never the source of confusion.

crates/cerebro/src/main.rs::resolve_config_path and crates/cerebro-tui/src/bin/cerebro-tui.rs::resolve_config_path both implement the new priority. Integration tests in crates/cerebro/tests/integration.rs now pass --config explicitly so they don’t pick up a developer’s real XDG config from their machine.

Consequences

Pros

  • New users: install, run cerebro build, it reads the XDG default. No env vars required.
  • Existing users with CORTEX_PATH set: still work via fallback #3.
  • Power users / scripted runs: --config always wins, no surprises.
  • CORTEX_PATH is now documented for what it is: a data-directory pointer used by the MCP server, not a config prerequisite.

Cons

  • A user with both an XDG config and CORTEX_PATH set to a different cortex will silently get the XDG config. This is the desired behavior, but it means CORTEX_PATH no longer “wins” — release notes should call this out.
  • Tests now depend on --config being passed; future test authors must remember to do so. The existing integration tests were updated as part of this change.
  • The example config.toml in the README was reworked; any external tutorials/screenshots showing the old “put it in your cortex” pattern are stale.

Migration

For users currently relying on CORTEX_PATH to point at their config:

# Old: config was at $CORTEX_PATH/config.toml
# New: move it to the XDG location
mv "$CORTEX_PATH/config.toml" ~/.config/cerebro/config.toml
# CORTEX_PATH can stay set (MCP still uses it) or be unset if you accept the default

For users with no config at all, run cerebro build once after install and follow the “config not found” error message — it points at the XDG path.

Notes

  • The dirs crate handles home_dir(); we read XDG_CONFIG_HOME ourselves with $HOME/.config as the fallback so the resolution is identical on every platform. We intentionally do NOT use dirs::config_dir(), which on macOS returns ~/Library/Application Support and would surprise users coming from Linux.
  • The integration tests previously relied on CORTEX_PATH for config; they now pass --config explicitly. Unit tests in main.rs::tests were already structured to not depend on a real XDG config and required no changes.
  • The MCP server’s use of CORTEX_PATH is intentionally not touched — it serves a different purpose (data dir, not config).