Skip to main content
Glama

codebugs

Persistent code finding, requirements, and release tracker for AI assistants. SQLite-backed, exposed via MCP server + CLI.

AI assistants lose context between sessions. codebugs gives them durable memory for code review findings, requirements, dependency blockers, parallel-agent coordination, and release milestones — with minimal token overhead.

Session 1:  Review code → log 50 findings → forget them
Session 2:  summary → instant orientation → fix 20 → update status
Session 3:  pull_next → claim work → mark integrated → next agent picks up

No context lost. No re-reading files. No token-heavy recaps. Parallel agents don't race.

Why codebugs

Building a real codebase with AI assistants creates four problems that compound over time:

  1. Findings get lost. You spend 20K tokens reviewing a file, log 12 bugs in chat, and the next session has no idea they exist.

  2. Requirements drift. REQUIREMENTS.md gets edited by hand, forgotten, contradicted by code, and nobody catches it.

  3. Parallel agents race. Two agents both pick the same bug, both edit the same file, both think they've shipped it.

  4. Releases lose track of what's in them. Work sits stranded on feature branches for 9 days. "Where are we on 1.1?" has no single answer.

codebugs is one SQLite database (.codebugs/findings.db) that solves all four. Nine self-contained modules, 66 MCP tools, one CLI.

Related MCP server: iranti

Install

# Global install (recommended)
pipx install codebugs

# Or with pip/uv
pip install codebugs

Setup

Create the tracker

Run this once per project, in the project root:

codebugs init

This creates .codebugs/findings.db. init is the only command that creates a tracker — every other command discovers an existing one by walking up from the current directory (unless you point it somewhere explicitly, see below), and refuses with an actionable error if there is none. That refusal is deliberate: silently creating an empty database is how findings go missing.

There is one deliberate exception, and it is worth stating precisely because it looks like the rule being broken. The upward walk treats an existing .codebugs/ directory as the opt-in, so if that directory is there but holds no findings.db, the next command creates the database inside it rather than refusing. The common way to end up in that state is an interrupted init — the directory is created before the database — and self-healing on the next command is more useful there than demanding a second init.

A tracker you name explicitly is held to the stricter rule. --repo, --tracker-root and $CODEBUGS_ROOT must resolve to a directory that actually contains findings.db; a .codebugs/ without one is refused, and the message names which channel pointed there. The difference is about evidence: standing inside a directory says something about where you are, while a named path is an assertion that can be mistyped, or exported into a shell days ago and inherited by an unrelated process. That is exactly where a silent empty tracker does the most damage.

Two consequences worth knowing:

  • Run init at the project root, not in a subdirectory. Discovery binds to the nearest .codebugs/, so a nested tracker hides the project's real one from everything beneath it. init refuses to do this unless you pass --force.

  • Git worktrees share the main repo's tracker. A worktree's .git is a file pointing at the main repo, which discovery follows — so findings filed from a worktree land in the project's database, not in a throwaway that dies with the worktree. init refuses to run inside a worktree for the same reason; run it in the main checkout.

    Two layouts are the exception: if the main repo is bare or was created with --separate-git-dir, git records no path back to a main checkout — its own git worktree list reports the git directory instead. Discovery usually refuses those with an explicit error rather than guessing. There is one case it cannot detect: a --separate-git-dir repo whose git directory is itself named .git looks exactly like a normal checkout, so discovery binds to the directory holding the git dir instead of the real checkout, silently. Nothing local can distinguish the two — git reports that directory as a valid work tree as well — so the remedy is to state the root explicitly (below). Run init in the main checkout before creating worktrees.

Pointing codebugs at a specific tracker

Discovery is a heuristic, so it has an override:

codebugs --tracker-root /path/to/project query   # this invocation only
export CODEBUGS_ROOT=/path/to/project            # this shell and anything it spawns

Resolution order, most specific first: a command's own explicit path argument (--repo, where a command has one) → --tracker-rootCODEBUGS_ROOT → walking up from the current directory. A per-command argument outranks a declaration because it names one operation's target, while a declaration is process-wide.

codebugs where     # show the current binding and which channel decided it

where is a diagnostic, not a precedence level: it prints the resolved root, the database path, and the channel — the fastest way to check that a command is about to read the tracker you think it is.

Two things worth knowing. A declared root that contains no .codebugs/ is a hard error, never a new tracker: the value may be a stale export inherited from another shell, and silently creating an empty database there is how findings go missing. And init ignores the declaration — it always creates where you are standing — but warns if the declaration points somewhere else, since otherwise it would report success for a tracker no other command will read.

CODEBUGS_ROOT is inherited by every subprocess, so export it only when you mean "this shell works on that project". For one-off use across projects, prefer --tracker-root.

Claude Code (MCP)

Add to ~/.claude.json (global) or .mcp.json (per-project):

{
  "mcpServers": {
    "codebugs": {
      "command": "codebugs-mcp"
    }
  }
}

The database lives at .codebugs/findings.db, discovered by walking up from the server's working directory — each project gets its own. Run codebugs init in the project first (see above), or every tool call will fail with "no .codebugs/ found".

The server connects lazily, per tool call, so it starts successfully even when no tracker is reachable. At startup it writes one line to stderr — which MCP clients log — if discovery failed, or if a root was declared rather than discovered; on the ordinary path it says nothing. It never refuses to start: a project directory that appears later must still work.

To pin one server to one tracker instead of deriving it from the working directory:

{
  "mcpServers": {
    "codebugs": {
      "command": "codebugs-mcp",
      "args": ["--tracker-root", "/path/to/project"]
    }
  }
}

Only do this when you want that server bound to a single project — the default cwd-derived behavior is what lets one registration serve many. Add .codebugs/ to your .gitignore.

Running Modules Independently

Use --mode to load only the tools you need:

{
  "mcpServers": {
    "codebugs": {
      "command": "codebugs-mcp",
      "args": ["--mode", "findings"]
    }
  }
}

Mode

Tools

Use it when

findings

8

Code review / bug tracking only

provenance

1

Staleness checks against git history

reqs

12

Specification tracking only

sweep

9

Batch iteration / state-machine tasks

bench

4

Performance benchmarks

merge

5

Multi-agent merge coordination

blockers

4

Cross-entity dependency tracking

milestones

18

Release + stream + capacity-aware pull

claims

5

"Who holds this card" for parallel agents

all

66

Default — everything

The CLI takes the same flag: codebugs --mode findings summary.

Other MCP Clients

Any MCP-compatible client can connect to codebugs-mcp via stdio transport.

The nine modules

Module

Domain

Headline tools

findings

Bugs, tech-debt, review findings

summary, add, query, categories

reqs

Functional requirements (FR-N)

reqs_summary, reqs_add, reqs_verify, reqs_search_similar

blockers

"X is blocked by Y" dependency graph

blockers_add, blockers_check

sweep

Batch iteration with state machines

codesweep_create, codesweep_next, codesweep_mark

bench

Performance benchmark snapshots

codebench_import, codebench_query

merge

Parallel-agent merge serialization

codemerge_start, codemerge_claim

milestones

Releases, streams, capacity-aware pull

pull_next, milestone_status, milestone_close

provenance

Staleness vs git history, commit trailers

staleness_check

claims

Which agent holds a finding or requirement

claims_claim, claims_release, claims_who_holds

Modules are self-registering — adding a new one is local to its own file. See docs/superpowers/specs/ for the architecture history.

Quick tour

Findings — log it, never re-discover it

MCP tools:

Tool

Purpose

summary

Dashboard overview — start here for orientation

add

Log a finding with severity, category, file, description

batch_add

Log multiple findings at once

update

Change status, severity, notes, tags or metadata (append_note adds, notes replaces)

query

Search/filter with pagination and group-by

stats

Cross-tabulated counts (severity x category/file/status)

categories

List existing categories — call before add for consistency

staleness_check

Compare against git history; mark obsolete findings stale

CLI:

codebugs add -s high -c n_plus_one -f src/api.py -d "Query in loop at line 42"
codebugs summary
codebugs query --status open --severity critical
codebugs update CB-1 --status fixed --append-note "Fixed in PR #42"
codebugs categories

--append-note adds to a finding's notes; --notes replaces them wholesale. Prefer --append-note when recording investigation history — --notes will discard whatever was there, which is usually not what you want on a finding others have been working.

When a new finding is added, the milestones auto-router automatically attaches it to stream/triage (or stream/security when severity=critical and category starts with security:). The finding and its triage entry land in the same transaction.

Requirements — verify what shipped, surface contradictions

MCP tools:

Tool

Purpose

reqs_summary

Requirements dashboard — start here

reqs_add

Add a requirement (FR-001, priority, status, test coverage)

reqs_update

Change status, description, priority, test coverage

reqs_query

Search/filter by status, priority, section, free text

reqs_stats

Cross-tabulated counts (status x priority)

reqs_verify

Automated checks: ghost test files, duplicate IDs, status contradictions

reqs_import

Import from REQUIREMENTS.md (parses markdown tables)

reqs_embed / reqs_batch_embed

Store embedding vectors

reqs_search_similar

Semantic search across requirements

reqs_embedding_stats

Report on embedding coverage

CLI:

codebugs reqs-import REQUIREMENTS.md
codebugs reqs-summary
codebugs reqs-verify
codebugs reqs-query --status Implemented --priority Must
codebugs reqs-update FR-090 --status Superseded --notes "Replaced by vault architecture"
codebugs reqs-export REQUIREMENTS.md

Blockers — "X is blocked by Y", with auto-unblock

MCP tools:

Tool

Purpose

blockers_add

Defer an item until another item resolves, a date passes, or a manual signal

blockers_query

List blockers filtered by item, dependency, trigger type

blockers_check

Find currently-actionable items (all blockers satisfied)

blockers_resolve

Cancel or manually resolve a blocker

Triggers come in three flavors: entity_resolved (waits for another finding/requirement to reach a terminal state), date (unblocks on a specific datetime), and manual (operator signal). When you mark a finding fixed, every blocker that was waiting on it auto-unblocks and surfaces in the next blockers_check.

Milestones — release containers + standing streams + capacity-aware pull

MCP tools:

Tool

Purpose

milestone_status

Rollup for one milestone (counts by status/size, branch-only, blocked, days to target)

milestone_list

List milestones, filter by kind / state

milestone_create

Create a release or stream

milestone_update

Mutate description, target_date, state

milestone_add_item

Attach a bug / requirement / external ref to a milestone

milestone_move_item

Move an item between milestones

milestone_set_status

Open / in_progress / done / dismissed / deferred

milestone_defer

Move to stream/maintenance with status='deferred'

milestone_close

Refuses if open / branch-only / blocked items remain (force overrides, except for streams)

milestone_audit_query

Full state-transition history

triage_inbox

Items waiting to be triaged

triage_dismiss

Reject a triage item; propagates to underlying entity

triage_promote

Move a triage item to a target milestone

pull_next

Atomically claim the next eligible item for the calling agent

release_item

Free agent capacity (status='done' or 'abandoned')

wip_status

Snapshot of agent_capacity per agent

mark_branch_only

Flag an item as living on a feature branch only

mark_integrated

Mark merged-to-main with commit SHA; clears branch_only

Four seed milestones are created automatically:

  • stream/triage — inbox for unsorted findings (default destination)

  • stream/maintenance — deferred / boy-scout work

  • stream/security — urgent fixes (preempts release work)

  • release/1.1 — first post-1.0 release

pull_next priority order: stream/security > release/* (earliest target_date first) > stream/triage > stream/maintenance. Within a milestone: priority ASC, then created_at ASC.

Eligibility: item is open, no active blockers (skipped for item_kind='external'), acceptance required for size='large', and a large bug in a release milestone must declare linked_frs whose ids resolve to rows in requirements. Concurrent calls from multiple agents are atomic — claims are serialized via BEGIN IMMEDIATE.

CLI:

codebugs milestone-list
codebugs milestone-status release/1.1
codebugs triage-inbox
codebugs wip-status
codebugs milestone-audit --milestone release/1.1

A typical autonomous-agent loop:

# 1. Agent claims the next eligible item.
item = pull_next(agent_id="agent-A", capacity={"large": 1, "small": 2, "triage": 5})

# 2. (Optional) flag a feature branch.
mark_branch_only(item_ref=item["item_ref"], branch_name="feat/CB-1234")

# 3. After integration, mark it done with the commit SHA.
mark_integrated(item_ref=item["item_ref"], commit="abc123…")

# 4. Free the agent's capacity slot.
release_item(item_ref=item["item_ref"], status="done")

Closing a release runs the close-gate: unfinished, branch-only, and blocker-gated items refuse to let the milestone ship. force=True (with a logged reason) overrides — but stream/* milestones cannot be closed, even with force.

Sweeps — batch iteration with recurrence-aware lifecycles

MCP tools:

Tool

Purpose

codesweep_create

Create a new sweep (optional lifecycle=[...], terminal_states=[...], transitions={...} for state machines)

codesweep_add

Add items. Atomic upsert: existing items bump recurrence_count, refresh last_seen, un-archive

codesweep_next

Next batch of unprocessed (non-terminal, non-archived) items

codesweep_mark

Transition state (legacy processed=True still works)

codesweep_status

Progress overview

codesweep_archive / codesweep_archive_items

Soft-delete

codesweep_list_items / codesweep_list

Inspection

codebugs sweep-create --name lint-pass --batch-size 5
codebugs sweep-add lint-pass src/*.py --tags critical
codebugs sweep-next lint-pass
codebugs sweep-mark lint-pass src/api.py
codebugs sweep-status lint-pass

With a custom lifecycle (e.g. for retro findings):

codebugs sweep-create --name retro-findings \
    --lifecycle DETECTED,CONFIRMED,ESCALATED,RESOLVED,DROPPED \
    --terminal-states RESOLVED,DROPPED
codebugs sweep-add retro-findings finding-2026-04-todo-bypassed --tags silent_abandonment
codebugs sweep-mark retro-findings finding-2026-04-todo-bypassed --state CONFIRMED
codebugs sweep-archive-items retro-findings --state RESOLVED --older-than 30d

Bench — performance snapshots over time

MCP tools:

Tool

Purpose

codebench_import

Import benchmark results (file or inline)

codebench_query

Filter and trend metrics across runs

codebench_list

List recorded runs

codebench_delete

Remove a run

Merge — parallel-agent merge serialization

MCP tools:

Tool

Purpose

codemerge_start

Open a merge session

codemerge_claim

Claim files for the session (advisory file-level claims)

codemerge_check

Check for overlapping claims against main

codemerge_merge

Mark merge in progress (acquires the global merge lock with TTL)

codemerge_finish

Release the lock

How It Works

The Problem

AI code review sessions produce findings that get lost. Multiple agents working in parallel double-claim work. Requirements files drift. Releases lose track of what's in them.

The Solution

codebugs stores everything in one local SQLite database. AI assistants write findings, requirements, and milestone items as they discover them, then query the database in future sessions for instant context recovery. Concurrent agents coordinate via the same database — no race conditions, atomic claims.

Token savings: A summary call returns a structured JSON overview in ~200 tokens. Without codebugs, re-establishing the same context costs 2K–10K+ tokens of file reading and conversation history.

Typical Workflows

Code review loop:

  1. AI reviews code, calls categories for naming consistency, then add for each finding.

  2. Each add auto-routes the finding to stream/triage.

  3. Next session: AI calls summary → 50 open findings → query --severity critical → fixes the worst → update CB-N --status fixed.

  4. Over time, categories reveals systemic issues — "12 tz_naive_datetime fixed across 9 files → time for a lint rule."

Release loop:

  1. Triage: AI calls triage_inboxtriage_dismiss non-bugs, triage_promote real items to release/1.1 (with linked_frs for the ones that need an FR row).

  2. Execution: Each parallel agent calls pull_next(agent_id=..., capacity=...) → claims the next eligible item.

  3. After landing: mark_integrated(item, commit)release_item(item, status='done').

  4. Close: milestone_close("release/1.1"). Refuses if anything is stranded on a branch; lists the offenders with the branch name.

Schema (highlights)

All tables share .codebugs/findings.db with flexible JSON columns. Schemas are additive — every module owns its tables, declares dependencies, and migrates additively.

Findings

Field

Type

Description

id

text

Auto-generated (CB-1, CB-2, ...) or user-provided

severity

text

critical, high, medium, low

category

text

User-defined (e.g. n_plus_one, missing_validation, security:xss)

file

text

File path relative to project root

status

text

open, in_progress, fixed, not_a_bug, wont_fix, stale

description

text

What's wrong

source

text

claude, ruff, human, mypy, ...

tags

json

Array of strings for ad-hoc grouping

meta

json

lines, module, rule_code, cwe_id, ...

reported_at_commit, reported_at_ref

text

Provenance for staleness checks

Requirements

Field

Type

Description

id

text

User-provided (FR-001, NFR-001, ...)

section, description, priority, status, source, test_coverage

text

per-row metadata

embedding

blob

Optional float32 vector for semantic search

tags, meta

json

Milestones

Table

Purpose

milestones

Slug (release/1.1, stream/triage), kind, state, target_date, description

milestone_items

(milestone_id, item_kind, item_ref) link, size, priority, status, acceptance, branch_only, done_commit

milestone_audit

Append-only log: actor, action, from_state → to_state, reason, timestamp

agent_capacity

Per-agent WIP (large_held, small_held, triage_held, last pull/release)

Item kinds are bug (validated against findings), requirement (validated against requirements), or external (free-form, blockers skipped). The (milestone_id, item_kind, item_ref) unique constraint prevents double-attach.

Blockers

Field

Type

Description

item_id, item_type

text

Blocked entity (e.g. CB-5 / finding)

blocked_by, blocked_by_type

text

Dependency (or null for date/manual triggers)

trigger_type

text

entity_resolved, date, manual

trigger_at

text

UTC datetime for date triggers

reason

text

Human explanation

Sweeps

Table

Purpose

codesweeps

sweep_id, name, description, lifecycle, terminal_states, transitions DAG

codesweep_items

(sweep_id, item) unique key; state, recurrence_count, first_seen, last_seen, archived_at

Killer features

Pattern detection over time

$ codebugs categories
category                        total  open  fixed
tz_naive_datetime                  15     3     12
n_plus_one                          8     2      6
missing_input_validation            6     4      2

If you keep fixing the same category → time for a lint rule. codebugs turns reactive bug-fixing into proactive prevention.

Requirements verification

reqs_verify catches documentation rot before it ships:

$ codebugs reqs-verify
Verified 683 requirements.

12 issue(s) found:
check   sev       id      message
tests   high      FR-350  Test file not found: test_entity_graph.py
status  high      FR-090  Description mentions 'superseded' but status is 'Planned'
status  medium    FR-006  Must-priority requirement implemented without test coverage
ids     medium    --      Numbering gaps (5+): FR-025..FR-029, FR-316..FR-329

Store embeddings (caller generates vectors via any embedding API) and find related requirements semantically:

reqs_embed(req_id="FR-001", embedding=[0.1, 0.2, ...])
reqs_search_similar(query_embedding=[...], limit=5, min_similarity=0.3)

Float32 BLOB storage in SQLite; brute-force cosine similarity — fast for thousands of requirements.

Close-gate enforcement

milestone_close("release/1.1") won't let you ship a release with work stranded on a branch:

$ codebugs milestone-status release/1.1
release/1.1  (release, state=open)
  target: 2026-06-15 (35 days)

Items: 12 total (3 open/in_progress, 9 done)
  Branch-only: CB-1234
  Blocked: CB-1240

When you try to close it:

ValueError: cannot close release/1.1: unfinished items (3): CB-1234, CB-1240, CB-1242;
            branch-only items (1): CB-1234@feat/CB-1234;
            items with active blockers (1): CB-1240
            (use force=True with reason to override)

Streams (stream/*) refuse to close at all — they're permanent buckets.

Requirements

  • Python 3.11+

  • No external runtime dependencies beyond mcp>=1.0.0 (for the server)

  • SQLite (bundled with Python)

Development

# Run tests
uv run python -m pytest tests/ -v

# Lint
uv run ruff check src/ tests/

# Format
uv run ruff format src/ tests/

See CLAUDE.md for architectural rules and conventions.

License

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
<1hResponse time
Release cycle
Releases (12mo)
Commit activity
Issues opened vs closed

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    -
    quality
    C
    maintenance
    Provides AI coding assistants with persistent project memory to retain architectural decisions, code patterns, and domain knowledge across sessions. It stores data locally in a SQLite database, allowing agents to remember, recall, and manage project-specific context using full-text search.
    8
    Apache 2.0
  • A
    license
    A
    quality
    A
    maintenance
    Persistent shared memory for AI coding agents. Stores facts as entity/key/value triples with hybrid semantic search, task checkpoints, and conflict resolution — shared across Claude Code, Codex CLI, and GitHub Copilot.
    16
    235
    5
    AGPL 3.0
  • A
    license
    -
    quality
    B
    maintenance
    Gives AI assistants persistent, queryable project memory for decisions, patterns, and rules, reducing the need to re-explain context in every prompt.
    11
    Apache 2.0
  • A
    license
    -
    quality
    D
    maintenance
    Repository-native, Git-reviewable memory extension for AI coding assistants to persist project context across features, using SQLite caching for up to 10x token reduction.
    14
    MIT

View all related MCP servers

Related MCP Connectors

  • Give your AI agent a persistent map of your project's structure, dependencies, and bugs.

  • Persistent memory for AI agents. Search, store, and recall across sessions.

  • Persistent memory and knowledge graphs for AI agents. Hybrid search, context checkpoints, and more.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/faxik/codebugs'

If you have feedback or need assistance with the MCP directory API, please join our Discord server