Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
curl -fsSL https://codedb.codegraff.com/install.sh | bash
```

Downloads the binary for your platform and auto-registers codedb as an MCP server in **Claude Code**, **Codex**, **Gemini CLI**, and **Cursor**.
Downloads the binary for your platform and auto-registers codedb as an MCP server in **Claude Code**, **Codex**, **Gemini CLI**, and **Cursor**. The installer prints the exact `codedb mcp` command it registered plus hook setup pointers for Codex and Claude Code.

| Platform | Binary | Signed |
|----------|--------|--------|
Expand All @@ -85,7 +85,7 @@ Or install manually from [GitHub Releases](https://github.com/justrach/codedb/re

### As an MCP server (recommended)

After installing, codedb is automatically registered. Just open a project and the 12 MCP tools are available to your AI agent.
After installing, codedb is automatically registered. Just open a project and the 16 MCP tools are available to your AI agent.

```bash
# Manual MCP start (auto-configured by install script)
Expand Down Expand Up @@ -131,37 +131,46 @@ codedb hot # recently modified files
| `codedb_status` | Index status (file count, current sequence) |
| `codedb_snapshot` | Full pre-rendered JSON snapshot of the codebase |
| `codedb_bundle` | Batch multiple read-only queries in one call (max 20 ops) |
| `codedb_remote` | Query any GitHub repo via cloud intelligence — no local clone needed |
| `codedb_remote` | Query indexed public repos via api.wiki.codes — no local clone needed |
| `codedb_projects` | List all locally indexed projects on this machine |
| `codedb_index` | Index a local folder and create a codedb.snapshot |


### `codedb_remote` — Cloud Intelligence

Query any public GitHub repo without cloning it. The default backend uses `codedb.codegraff.com`; `backend="wiki"` uses `api.wiki.codes` for code intelligence plus dependency/security artifacts.
Query any indexed public GitHub repo without cloning it. `codedb_remote` always uses `api.wiki.codes`; the old `codegraff` backend name is no longer a supported route. Omit `backend`, or keep `backend="wiki"` only for older prompts.

```
# Get the file tree of an external repo via the default backend
codedb_remote repo="vercel/next.js" action="tree"
# Check what the remote slug supports
codedb_remote repo="vercel/next.js" action="actions"

# Get a compact directory summary instead of dumping a huge file list
codedb_remote repo="vercel/next.js" action="tree" expand=false

# Page a file tree by prefix and limit
codedb_remote repo="vercel/next.js" action="tree" prefix="packages/" limit=100

# Search for code in a dependency
codedb_remote repo="justrach/merjs" action="search" query="handleRequest"

# Exact symbol lookup through api.wiki.codes
codedb_remote repo="justrach/codedb" backend="wiki" action="symbol" query="buildSnapshot"
# Read a small file slice
codedb_remote repo="openai/codex" action="read" path="codex-rs/core/src/codex.rs" lines="1-80"

# Exact symbol lookup
codedb_remote repo="justrach/codedb" action="symbol" query="buildSnapshot"

# Check dependency CVE evidence; scope can be runtime or all
codedb_remote repo="axios/axios" backend="wiki" action="cves" scope="runtime"
codedb_remote repo="axios/axios" action="cves" scope="runtime"

# Raw wiki slugs are accepted for repos that are indexed that way
codedb_remote repo="chromium" backend="wiki" action="policy"
codedb_remote repo="chromium" action="policy"
```

**Default actions:** `tree`, `outline`, `search`, `meta`
**Remote actions:** `actions`, `tree`, `outline`, `search`, `read`, `symbol`, `policy`, `deps`, `score`, `cves`, `commits`, `branches`, `dep-history`

**Wiki actions:** `tree`, `outline`, `search`, `symbol`, `policy`, `deps`, `score`, `cves`, `commits`, `branches`, `dep-history`
For Codex and Claude Code hook examples around `codedb_remote`, see [`docs/hooks-labs.md`](docs/hooks-labs.md).

**Note:** This tool calls remote HTTPS services. No API key required. The selected service must be available for this tool to work.
**Note:** This tool calls `https://api.wiki.codes`. No API key required. The repo must already be indexed by the public service.

### CLI Commands

Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ JSON-RPC 2.0 over stdio with Content-Length framing. Implements the Model Contex
| `codedb_status` | Index status |
| `codedb_snapshot` | Full snapshot |
| `codedb_bundle` | Batch multiple queries (max 20 ops) |
| `codedb_remote` | Query GitHub repos via codedb.codegraff.com or api.wiki.codes |
| `codedb_remote` | Query indexed public repos via api.wiki.codes |
| `codedb_projects` | List locally indexed projects |
| `codedb_index` | Index a local folder |
**Safety:** path validation, oversized message handling (drains >1MB lines instead of killing the loop).
Expand Down
210 changes: 210 additions & 0 deletions docs/hooks-labs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
# codedb Hooks Labs

codedb does not have its own hook runtime. It installs an MCP server, and Codex
or Claude Code can run hooks around MCP tool calls. Use hooks for local policy,
logging, and guardrails around calls such as `codedb_remote`; do not use them as
the only security boundary.

The installer registers the MCP server. Hook configuration is separate because
hooks execute arbitrary commands with your user permissions.

## Lab 1: Codex Hooks

Enable Codex hooks in `~/.codex/config.toml`:

```toml
[features]
codex_hooks = true
```

The codedb MCP registration should look like this:

```toml
[mcp_servers.codedb]
command = "/Users/you/bin/codedb"
args = ["mcp"]
startup_timeout_sec = 30
```

Codex discovers hooks next to active config layers:

- `~/.codex/hooks.json`
- `~/.codex/config.toml`
- `<repo>/.codex/hooks.json`
- `<repo>/.codex/config.toml`

Project-local hooks load only when the project `.codex/` layer is trusted.
Matching hooks from multiple files all run.

### Guard remote tree calls

This hook blocks unbounded `codedb_remote action=tree` calls unless the agent
uses `limit`, `prefix`, or compact summary mode. That keeps huge remote repos
from dumping too much context.

`.codex/hooks.json`:

```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__codedb__codedb_remote",
"hooks": [
{
"type": "command",
"command": "/usr/bin/env bash \"$(git rev-parse --show-toplevel)/.codex/hooks/codedb_remote_guard.sh\"",
"timeout": 5,
"statusMessage": "Checking codedb_remote request"
}
]
}
]
}
}
```

`.codex/hooks/codedb_remote_guard.sh`:

```bash
#!/usr/bin/env bash
set -euo pipefail

input="$(cat)"
action="$(printf '%s' "$input" | jq -r '.tool_input.action // empty')"
limit="$(printf '%s' "$input" | jq -r '.tool_input.limit // empty')"
prefix="$(printf '%s' "$input" | jq -r '.tool_input.prefix // empty')"
expand="$(printf '%s' "$input" | jq -r '.tool_input.expand // empty')"

if [ "$action" = "tree" ] && [ -z "$limit" ] && [ -z "$prefix" ] && [ "$expand" != "false" ]; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Use codedb_remote tree with expand=false, a prefix, or a limit."
}
}'
fi
```

Useful Codex hook events for codedb:

- `PreToolUse`: block or ask before a `mcp__codedb__...` call.
- `PostToolUse`: summarize or log MCP output after it returns.
- `PermissionRequest`: decide approval prompts.
- `UserPromptSubmit`: add repo-specific context before the prompt reaches the model.
- `Stop`: continue a turn when validation is still missing.

## Lab 2: Claude Code Hooks

Claude Code hook settings live in Claude settings files, while codedb MCP
registration may live in `~/.claude.json` depending on the installed Claude
Code version.

Claude Code's documentation index is published at
`https://code.claude.com/docs/llms.txt`; use it to discover the current hook
reference pages before relying on advanced events.

Common hook locations:

- `~/.claude/settings.json`
- `.claude/settings.json`
- `.claude/settings.local.json`
- managed policy settings
- plugin `hooks/hooks.json`
- skill or agent frontmatter

Claude Code MCP tool names use the same `mcp__<server>__<tool>` shape, so
codedb tools match as `mcp__codedb__codedb_remote`,
`mcp__codedb__codedb_search`, or `mcp__codedb__.*`.

`.claude/settings.json`:

```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__codedb__codedb_remote",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/codedb_remote_guard.sh",
"timeout": 5,
"statusMessage": "Checking codedb_remote request"
}
]
}
],
"PostToolUse": [
{
"matcher": "mcp__codedb__.*",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/log_codedb_tool.sh",
"async": true,
"timeout": 30
}
]
}
]
}
}
```

The same `codedb_remote_guard.sh` script from the Codex lab works for Claude
Code because both clients pass MCP tool input as JSON and accept
`hookSpecificOutput.permissionDecision`.

`.claude/hooks/log_codedb_tool.sh`:

```bash
#!/usr/bin/env bash
set -euo pipefail

input="$(cat)"
tool="$(printf '%s' "$input" | jq -r '.tool_name // "unknown"')"
event="$(printf '%s' "$input" | jq -r '.hook_event_name // "unknown"')"
repo="$(printf '%s' "$input" | jq -r '.tool_input.repo // empty')"
action="$(printf '%s' "$input" | jq -r '.tool_input.action // empty')"

mkdir -p .claude/logs
printf '%s\t%s\t%s\t%s\n' "$event" "$tool" "$repo" "$action" >> .claude/logs/codedb-tools.tsv
```

Claude Code has more hook events and handler types than Codex. The ones most
useful for codedb are:

- `PreToolUse`, `PostToolUse`, and `PostToolUseFailure` for MCP tool policy and telemetry.
- `PostToolBatch` when the next model call needs context from a full batch of tools.
- `UserPromptSubmit` and `UserPromptExpansion` for prompt-time repo context.
- `Stop` or `SubagentStop` for validation gates before an agent finishes.
- `ConfigChange`, `CwdChanged`, and `FileChanged` for environment reloads.

Claude Code also supports command, HTTP, MCP-tool, prompt, and agent hook
handlers. Prefer command hooks for deterministic policy checks; use async
command hooks for logging that should not block the agent loop.

## codedb_remote Defaults

`codedb_remote` always calls `https://api.wiki.codes`. The old `codegraff`
backend name is no longer a supported route. Keep `backend="wiki"` only for
compatibility with older prompts, or omit `backend` entirely.

Start with:

```text
codedb_remote repo="openai/codex" action="actions"
codedb_remote repo="openai/codex" action="tree" expand=false
codedb_remote repo="openai/codex" action="tree" prefix="codex-rs/" limit=100
codedb_remote repo="openai/codex" action="read" path="codex-rs/core/src/codex.rs" lines="1-80"
```

Use `scope="runtime"` for user-facing dependency risk and `scope="all"` when
you also need dev and tooling dependencies:

```text
codedb_remote repo="vercel/next.js" action="score" scope="runtime"
codedb_remote repo="vercel/next.js" action="cves" scope="all"
```
15 changes: 15 additions & 0 deletions install/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,20 @@ PYEOF
printf " ${G}✓${N} cursor ${D}→ $config${N}\n"
}

print_hook_notes() {
local codedb_bin="$1"

echo ""
printf " ${W}mcp command${N}\n"
printf " ${C}$codedb_bin mcp${N}\n"
echo ""
printf " ${W}optional hooks${N}\n"
printf " ${D}codex${N} enable [features].codex_hooks in ~/.codex/config.toml\n"
printf " ${D}codex paths${N} ~/.codex/hooks.json or <repo>/.codex/hooks.json\n"
printf " ${D}claude paths${N} ~/.claude/settings.json or <repo>/.claude/settings.json\n"
printf " ${D}examples${N} https://github.com/justrach/codedb/blob/release/0.2.579/docs/hooks-labs.md\n"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Build hook-doc URL from the installed version

The installer computes version dynamically, but this note hard-codes release/0.2.579 for the hook examples. As soon as users install a newer release, the printed URL can become stale (or disappear), so the setup guidance no longer matches the binary they just installed. Please derive this link from $version (or use a stable docs URL); the same hard-coded line is mirrored in the website installer copies.

Useful? React with 👍 / 👎.

}

main() {
local platform version ext=""
platform="$(detect_platform)"
Expand Down Expand Up @@ -247,6 +261,7 @@ main() {
register_codex "$dest"
register_gemini "$dest"
register_cursor "$dest"
print_hook_notes "$dest"

# Check PATH
case ":$PATH:" in
Expand Down
4 changes: 2 additions & 2 deletions src/mcp.zig
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ const tools_list =
\\{"name":"codedb_status","description":"Get current codedb status: number of indexed files and current sequence number.","inputSchema":{"type":"object","properties":{"project":{"type":"string","description":"Optional absolute path to a different project (must have codedb.snapshot)"}},"required":[]}},
\\{"name":"codedb_snapshot","description":"Get the full pre-rendered snapshot of the codebase as a single JSON blob. Contains tree, all outlines, symbol index, and dependency graph. Ideal for caching or deploying to edge workers.","inputSchema":{"type":"object","properties":{"project":{"type":"string","description":"Optional absolute path to a different project (must have codedb.snapshot)"}},"required":[]}},
\\{"name":"codedb_bundle","description":"Batch multiple queries in one call. Max 20 ops. WARNING: Avoid bundling multiple codedb_read calls on large files — use codedb_outline + codedb_symbol instead. Bundle outline+symbol+search, not full file reads. Total response is not size-capped, so large bundles can exceed token limits.","inputSchema":{"type":"object","properties":{"ops":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string","description":"Tool name (e.g. codedb_outline, codedb_symbol, codedb_read)"},"arguments":{"type":"object","description":"Tool arguments"}},"required":["tool"]},"description":"Array of tool calls to execute"},"project":{"type":"string","description":"Optional absolute path to a different project (must have codedb.snapshot)"}},"required":["ops"]}},
\\{"name":"codedb_remote","description":"Query indexed GitHub repos through api.wiki.codes. Supports tree pagination, search, exact symbol lookup, outlines, file reads, dependency/CVE scoring artifacts, commit metadata, and capabilities. For huge repos paginate tree with limit/offset/prefix and commits/dep-history with since/limit. Use action=read with path and optional lines='10-60' to fetch file slices.","inputSchema":{"type":"object","properties":{"repo":{"type":"string","description":"GitHub repo in owner/repo format (e.g. vercel/next.js) or a raw wiki slug such as chromium."},"action":{"type":"string","enum":["tree","outline","search","read","actions","symbol","policy","deps","score","cves","commits","branches","dep-history"],"description":"What to query from api.wiki.codes: tree, outline, search, read, actions, symbol, policy, deps, score, cves, commits, branches, dep-history."},"query":{"type":"string","description":"Action-specific argument. search: text query. symbol: identifier name. outline: file path."},"path":{"type":"string","description":"For action=read: the file path to fetch."},"lines":{"type":"string","description":"For action=read: line range like '10-60' (1-indexed, inclusive). Omit for full file."},"limit":{"type":"integer","description":"For tree/commits/dep-history: cap the number of items returned (server may enforce its own ceiling)."},"offset":{"type":"integer","description":"For tree: skip the first N items (pagination)."},"prefix":{"type":"string","description":"For tree: only return paths starting with this prefix (e.g. 'src/')."},"expand":{"type":"boolean","description":"For tree: when true, return the full file list. When false (and the server supports it) returns a compact directory summary."},"since":{"type":"string","description":"For commits/dep-history: ISO timestamp or commit SHA to start from."},"scope":{"type":"string","enum":["runtime","all"],"description":"For score/cves only. Defaults to runtime; use all to include dev/tooling dependencies."},"backend":{"type":"string","enum":["wiki"],"description":"Deprecated compatibility field. Only 'wiki' is accepted; requests always use api.wiki.codes."}},"required":["repo","action"]}},
\\{"name":"codedb_remote","description":"Query indexed public repos through api.wiki.codes, the only remote backend. Use action=actions first when unsure what a slug supports. Use tree with expand=false for a compact directory summary, or expand=true with limit/offset/prefix for paged file lists. Use read with path and optional lines='10-60' for file slices. Search, symbol, outline, deps, score, cves, commits, branches, and dep-history expose code and artifact metadata without cloning.","inputSchema":{"type":"object","properties":{"repo":{"type":"string","description":"GitHub repo in owner/repo format (e.g. vercel/next.js) or a raw wiki slug such as chromium."},"action":{"type":"string","enum":["tree","outline","search","read","actions","symbol","policy","deps","score","cves","commits","branches","dep-history"],"description":"What to query from api.wiki.codes: actions, tree, search, outline, read, symbol, policy, deps, score, cves, commits, branches, dep-history."},"query":{"type":"string","description":"Action-specific argument. search: text query. symbol: identifier name. outline: file path."},"path":{"type":"string","description":"For action=read: the file path to fetch."},"lines":{"type":"string","description":"For action=read: line range like '10-60' (1-indexed, inclusive). Omit for full file."},"limit":{"type":"integer","description":"For tree/commits/dep-history: cap the number of items returned (server may enforce its own ceiling)."},"offset":{"type":"integer","description":"For tree: skip the first N items (pagination)."},"prefix":{"type":"string","description":"For tree: only return paths starting with this prefix (e.g. 'src/')."},"expand":{"type":"boolean","description":"For tree: when true, return the full file list. When false returns a compact directory summary when supported."},"since":{"type":"string","description":"For commits/dep-history: ISO timestamp or commit SHA to start from."},"scope":{"type":"string","enum":["runtime","all"],"description":"For score/cves only. Defaults to runtime; use all to include dev/tooling dependencies."},"backend":{"type":"string","enum":["wiki"],"description":"Deprecated compatibility field. Only 'wiki' is accepted; requests always use api.wiki.codes."}},"required":["repo","action"]}},
\\{"name":"codedb_projects","description":"List all locally indexed projects on this machine. Shows project paths, data directory hashes, and whether a snapshot exists. Use to discover what codebases are available.","inputSchema":{"type":"object","properties":{},"required":[]}},
\\{"name":"codedb_index","description":"Index a local folder on this machine. Scans all source files, builds outlines/trigrams/word indexes, and creates a codedb.snapshot in the target directory. After indexing, the folder is queryable via the project param on any tool.","inputSchema":{"type":"object","properties":{"path":{"type":"string","description":"Absolute path to the folder to index (e.g. /Users/you/myproject)"}},"required":["path"]}},
\\{"name":"codedb_find","description":"Fuzzy file search — finds files by approximate name. Typo-tolerant subsequence matching with word-boundary and filename bonuses. Use when you know roughly what file you're looking for but not the exact path. Much faster than codedb_tree + manual scan.","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"Fuzzy search query (e.g. 'authmidlware', 'test_auth', 'main.zig')"},"max_results":{"type":"integer","description":"Maximum results to return (default: 10)"},"project":{"type":"string","description":"Optional absolute path to a different project (must have codedb.snapshot)"}},"required":["query"]}},
Expand Down Expand Up @@ -1564,7 +1564,7 @@ fn handleRemote(alloc: std.mem.Allocator, args: *const std.json.ObjectMap, out:
return;
};
const action = getStr(args, "action") orelse {
out.appendSlice(alloc, "error: missing 'action' (tree, outline, search, meta, read, symbol, policy, deps, score, cves, commits, branches, dep-history)") catch {};
out.appendSlice(alloc, "error: missing 'action' (actions, tree, outline, search, read, symbol, policy, deps, score, cves, commits, branches, dep-history)") catch {};
return;
};

Expand Down
Loading
Loading