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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ dist/
atlas.html
*.tgz
launch-drafts.md
devto-article.md
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Changelog

## 0.2.0 — 2026-07-22

**Multi-tool release** (SPEC_V2 M5–M8): one map across every AI coding tool on the machine.

### Added
- Adapter registry with `detect()` — only present tools are scanned; `--list-tools` and repeatable `--tool <name>` CLI flags; `tools` array in `--json`.
- **Codex CLI** adapter: MCP servers from `~/.codex/config.toml`, `AGENTS.md` (global + project), full usage from `~/.codex/sessions/**/*.jsonl`.
- **Cursor** adapter (inventory-only): global + project `mcp.json`, `skills-cursor/*/SKILL.md`, `.cursor/rules/*.mdc`, `.cursorrules`.
- **ORGN CDE** and **OpenCode** adapters (shared OpenCode-family core): agents/MCP/commands from `opencode.jsonc` (string-aware JSONC parser), partial usage from the local `opencode.db` SQLite store — opened strictly read-only, copy-on-read under WAL locks, degrades to inventory-only on schema surprises or Node < 22.5.
- Cross-tool diagnostics: duplicate MCP servers across tools (matched by normalized command/URL identity, usage contrast where honest), capability imbalance per axis, overlapping rules files flagged for human review.
- Renderer: tool badges (stroke color) + tool filter, "by tool" tuning view, fixed-size "usage unavailable" rendering for tools without usage data.
- Plugin-skill usage is now credited across prefix mismatches when the match is unambiguous (review finding 1).

### Breaking
- Item ids are tool-namespaced: `skill:git-workflow` → `claude-code/skill:git-workflow`. `InventoryItem` gains `tool`; MCP items gain `identity`; `--json` gains `tools` and `crossTool`.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,22 @@ In one picture you can answer questions you currently can't:
npx agent-atlas-cli
```

That's it. No config, no account. Works on **Claude Code** setups today (Cursor and friends are on the roadmap — the scanner is built behind an adapter interface).
That's it. No config, no account. v2 maps every supported tool it detects on your machine:

| Tool | Inventory | Usage data |
|---|---|---|
| **Claude Code** | skills, agents, MCP servers, hooks | full (session transcripts) |
| **Codex CLI** | MCP servers (`config.toml`), `AGENTS.md` | full (session logs) — CLI layout only; the desktop app keeps no public surface and shows as "not detected" |
| **ORGN CDE** | agents, MCP servers, commands (`opencode.jsonc`) | partial (local session DB, read-only) |
| **OpenCode** | same as ORGN CDE (shared format) | partial |
| **Cursor** | MCP servers, skills, rules files | none — nodes render at fixed size with a "usage unavailable" badge; we don't fake numbers |

**Why not ChatGPT / claude.ai / Gemini web?** Their configuration lives on company servers — there is nothing local to read, and no API exposes installed connectors plus usage. We'd rather not pretend. (Gemini CLI and Windsurf adapters are planned.)

```bash
npx agent-atlas --list-tools # what's detected on this machine
npx agent-atlas --tool cursor # restrict to one tool (repeatable)
```

Don't have an Anthropic API key handy? It still works:

Expand Down Expand Up @@ -72,6 +87,11 @@ Classification uses your `ANTHROPIC_API_KEY` environment variable if set; otherw
| M2 | Classifier — LLM pass, cache, overrides, no-key fallback | ✅ done |
| M3 | Renderer — interactive map + tuning bar (`atlas.html`) | ✅ done |
| M4 | Diagnostics (dead weight, overlaps, gaps) + shareable card | ✅ done |
| v2 M5 | Multi-tool adapter core — `detect()`, `--list-tools`, tool badges/filters | ✅ done |
| v2 M6 | Codex CLI + Cursor adapters | ✅ done |
| v2 M7 | ORGN CDE + OpenCode adapters (read-only SQLite usage) | ✅ done |
| v2 M8 | Cross-tool diagnostics + per-tool tuning bars | ✅ done |
| v2.x | Gemini CLI, Windsurf adapters; recommendations | 💭 planned |
| v2 | Adapters for Cursor, Codex CLI, Gemini CLI; recommendations | 💭 planned |

The full design lives in [SPEC.md](SPEC.md).
Expand Down
137 changes: 137 additions & 0 deletions SPEC_V2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Agent Atlas — v2 Spec: Multi-Tool Adapters

**Builds on:** `SPEC.md` (v1, shipped) — this spec covers the headline item deliberately cut from v1 (§9): support for AI assistants beyond Claude Code.
**Date:** 2026-07-22

---

## 1. Goal

v1 answers "what can my Claude Code setup do?" v2 answers **"what can my whole AI setup do?"** — one map across every AI coding assistant installed on the machine, plus the ORGN workspace, with cross-tool insights no single-tool view can give:

- *"You have the GitHub MCP server installed in four different tools — it fires in one of them."*
- *"Your Cursor setup is 80% engineering; your Claude Code setup carries all your writing and research capability."*
- *"Three tools have overlapping rules files that say different things."*

The honest boundary from v1 stands: **we can only map tools that keep their data where we can read it** (local files, or an API the user authorizes). Web-hosted assistants with server-side config (ChatGPT web, claude.ai, Gemini web) remain out of scope — there is nothing local to scan and no API that exposes installed connectors + usage.

## 2. Prerequisites (before any v2 work)

1. **Fix `report.md` findings 1 and 2** (plugin-skill usage attribution; project-scoped MCP servers in `~/.claude.json`). v2 multiplies inventory sources; attribution bugs multiply with them.
2. **One real-machine validation run** of v1 (`--json` against the real home dir) recorded as a golden reference.

## 3. Supported tools (the adapter roster)

Tiered by data quality. Every adapter is **verify-first**: config paths below are the implementation starting point, but each adapter's first task is confirming paths/formats against a real install and encoding them into fixtures — these tools change their layouts without notice.

### Tier A — full support (inventory + usage)

| Tool | Inventory sources | Usage source |
|---|---|---|
| **Claude Code** (v1, baseline) | `~/.claude` skills/agents/plugins, `~/.claude.json`, settings | `~/.claude/projects/*/*.jsonl` transcripts |
| **OpenAI Codex CLI** | `~/.codex/config.toml` (MCP servers, profiles), `AGENTS.md` (global + project) | `~/.codex/sessions/**/*.jsonl` session logs |
| **ORGN CDE** (OpenCode-based) | `~/.config/orgn/opencode.jsonc` (agents, MCP servers, commands, models via ORGN Gateway), `AGENTS.md` rules | `~/.local/share/orgn/opencode.db` — local SQLite session store (read-only queries) |
| **OpenCode** (vanilla) | `~/.config/opencode/opencode.json(c)` — same format as ORGN CDE | `~/.local/share/opencode/opencode.db` — shared adapter code with ORGN CDE |

### Tier B — inventory + partial or no usage

| Tool | Inventory sources | Usage caveat |
|---|---|---|
| **Cursor** | `~/.cursor/mcp.json`, project `.cursor/mcp.json`, `.cursor/rules/*.mdc`, `.cursorrules` | No reliably parseable local usage log — ships **inventory-only**; nodes render at uniform size with a "usage unavailable" badge |
| **Gemini CLI** | `~/.gemini/settings.json` (mcpServers), `GEMINI.md`, extensions dir | Local logs exist but format is unstable — attempt, degrade to inventory-only |
| **Windsurf** | `~/.codeium/windsurf/mcp_config.json`, rules files | Inventory-only |

### Tier C — explicitly out (say so in the README)

ChatGPT web / claude.ai / Gemini web (server-side config, no local data); VS Code Copilot (extension-internal storage, no stable surface); anything requiring scraping an app's private database. Listed in the README as "why not X" — honesty is part of the product's trust story.

**Adding a tool later** = one new adapter file + fixtures + a roster entry. That's the whole point of the interface.

## 4. Architecture changes

### 4.1 Adapter interface (generalized from v1)

v1's `ToolAdapter` assumed local filesystem + `homeDir`. v2 generalizes:

```ts
interface ToolAdapter {
name: string; // 'claude-code' | 'codex' | 'cursor' | 'orgn' | ...
displayName: string;
usageSupport: 'full' | 'partial' | 'none';
detect(ctx: AdapterContext): Promise<boolean>; // is this tool present/configured?
scan(ctx: AdapterContext): Promise<Inventory>;
mineUsage(ctx: AdapterContext): Promise<Usage>; // returns {totalSessions: 0, items: {}} when unsupported
}
```

- `AdapterContext` carries `homeDir`, `projectDir`, `days`, and (new) optional per-adapter config from `~/.agent-atlas/config.json` — this is where the ORGN API token lives.
- **Item ids become tool-namespaced:** `claude-code/skill:git-workflow`, `codex/mcp:github`. Every `InventoryItem` gains a `tool` field. This prevents cross-tool id collisions and makes attribution unambiguous. (v1 ids migrate to the `claude-code/` prefix — a breaking change to the `--json` shape; bump to 0.2.0 and note it.)
- **`detect()` before `scan()`:** the CLI runs every registered adapter's `detect()`, scans only the present ones, and reports "found: Claude Code, Codex, Cursor" so the user sees coverage explicitly.

### 4.2 The ORGN CDE adapter (OpenCode family)

ORGN CDE is built on OpenCode, so it is a **local, file-based Tier A adapter** — verified on a real install (2026-07-22):

- **Inventory:** `~/.config/orgn/opencode.jsonc` — OpenCode-format config carrying agents, MCP servers, commands, and model/provider setup (ORGN Gateway); plus `AGENTS.md` rules files (global + project) in the "context, not classified" bucket.
- **Usage:** `~/.local/share/orgn/opencode.db` — a local SQLite session store. The adapter opens it **read-only** (SQLite `mode=ro`, and copy-on-read if the DB is locked by a running CDE) and counts tool/agent/MCP invocations per session within the window. `better-sqlite3` or `node:sqlite` — pick at implementation time; schema survey is the milestone's first task.
- **Shared OpenCode core:** the parser for config + DB lives in an `opencode-family` module; the vanilla **OpenCode** adapter (`~/.config/opencode`, `~/.local/share/opencode`) is the same code with different paths. Two adapters for the price of one.
- **Optional workspace enrichment (stretch, not required for M7):** the ORGN studio API (the same surface the `ask-orgn` MCP server uses) can add workspace-level data — registered agents, task runs across the team. Auth via token in `~/.agent-atlas/config.json`, never a CLI flag. Without it, the adapter is fully functional on local data alone.
- **Privacy note:** the ORGN config contains team/user ids and the DB contains session content — same rule as v1 transcripts: mined locally, never sent to the classification API (only names/descriptions go out).

### 4.3 Classifier — unchanged, one addition

The classifier is already tool-agnostic (it sees name + description + kind). One addition: **rules files** (`.cursorrules`, `AGENTS.md`, `GEMINI.md`, `.cursor/rules/*.mdc`) join `CLAUDE.md` in the "memory/context, counted but not classified" bucket from v1 — same treatment, new sources.

### 4.4 Renderer additions

- **Tool badge on every node** (small icon/color ring) + a **tool filter** in the legend panel alongside the kind filter.
- **Per-tool tuning bars:** the header gains a "by tool" view — one mini tuning bar per detected tool, stacked. This is the "Cursor is all engineering, Claude Code carries your writing" insight in one glance.
- **Uniform-size rendering for usage-less tools** with a visible "usage unavailable" badge — never fake sizes, never grey them (grey means *never used*, which we can't claim without usage data).

### 4.5 Cross-tool diagnostics (the v2 payoff)

Three new diagnostic lists, alongside v1's three:

1. **Cross-tool duplicates:** the same MCP server (matched by command/URL, not just name) installed in N tools. Rendered with usage contrast where available: *"`github` MCP is installed in Claude Code, Codex, and Cursor — it has only ever fired in Claude Code."*
2. **Capability imbalance:** per-tool tuning profiles diverging sharply — surfaced as a plain-English line, not a judgment: *"All research capability lives in Claude Code; Codex and Cursor have none."*
3. **Conflicting rules files:** rules/context files across tools whose instructions overlap in topic (classifier similarity on their summaries) — flagged for human review only, no automated conflict detection: *"`.cursorrules` and `CLAUDE.md` both give code-style instructions — worth checking they agree."*

Dead-weight token math stays per-tool (context cost is per-session *within* a tool).

## 5. CLI surface

```bash
npx agent-atlas # auto-detect all tools, unified map
npx agent-atlas --tool codex # restrict to one tool (repeatable)
npx agent-atlas --list-tools # show detected tools + data quality, then exit
```

`--json` output gains `tools: [{name, detected, usageSupport, itemCount}]` and the namespaced ids.

## 6. What stays cut (v3+)

- Recommendations / auto-fix ("install X to fill this gap") — still reporting-only
- Hosted web version, accounts, **team aggregation** (note: the ORGN adapter is the natural seed for the team version discussed for the paid tier — but v2 keeps it single-user)
- Historical trends over time
- Windows beyond best-effort paths

## 7. Milestones

| # | Feature | Done when |
|---|---|---|
| M5 | Adapter interface v2 + tool-namespaced ids + `detect()`/`--list-tools` + tool badges/filter in renderer | v1 behavior identical through the new interface; fixtures green; `--list-tools` correct on the real machine |
| M6 | Codex adapter (full) + Cursor adapter (inventory-only) | Fixture trees for both; real-machine verification of paths/formats recorded in the fixture README; Codex usage counts match a hand-checked session log |
| M7 | ORGN CDE + vanilla OpenCode adapters (shared `opencode-family` module) | SQLite schema survey doc committed; inventory + session usage render from the real `~/.config/orgn` + `opencode.db`; read-only DB access verified against a running CDE |
| M8 | Gemini CLI + Windsurf adapters + cross-tool diagnostics + per-tool tuning bars | All three cross-tool diagnostic lists render with real numbers; unified map on the real machine shows ≥3 tools |

Sequencing rationale: M5 is pure refactor (riskiest to delay), M6 proves the interface on the two most-requested tools, M7 is the showcase tie-in, M8 is the payoff layer. Each milestone is demo-able — M6 alone yields the "one map, three tools" screenshot that headlines the v2 announcement.

## 8. Risks

| Risk | Mitigation |
|---|---|
| Config paths/formats drift per tool version | Verify-first rule per adapter; fixtures encode the verified format; parsers tolerate unknown fields; degrade to partial inventory rather than crash |
| Usage claims on partial data mislead | `usageSupport` surfaced in UI and README; uniform-size + badge for usage-less tools; never grey without data |
| OpenCode DB schema undocumented / may change between versions | M7 starts with a schema survey against the real DB; queries tolerate missing tables (degrade to inventory-only); DB opened read-only so a schema surprise can never corrupt anything |
| Id migration breaks v1 consumers of `--json` | Version bump to 0.2.0, changelog note, `tool` field additive |
| Scope creep ("support everything") | Roster is fixed for v2; new tools are v2.x point releases, one adapter each |
35 changes: 35 additions & 0 deletions docs/opencode-db-survey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# OpenCode / ORGN CDE — local data survey (2026-07-22)

Surveyed read-only on a real ORGN CDE install (`~/.local/share/orgn/opencode.db`, 102 sessions).

## Config: `~/.config/orgn/opencode.jsonc`
JSONC (comments + trailing commas). Relevant keys: `agent` (record), `mcp` (record),
`command` (record), `provider`/`model` (ignored — not capabilities). **Caution:** naive
`//`-comment stripping corrupts URLs inside strings (`"$schema": "https://…"`) — the
parser must be string-aware.

## DB schema (tables used)
- `session(id, project_id, title, time_created, …)` — `time_created` epoch **ms**.
- `message(id, session_id, time_created, data JSON)` — `data.agent` is the agent name
(e.g. `"build"`), `data.role` user/assistant.
- `part(id, message_id, session_id, time_created, data JSON)` — `data.type`:
`tool | step-start | step-finish | text | reasoning | patch | compaction | file`.
For `type='tool'`: `data.tool` is the tool name.

## Tool naming
- Builtins: `read`, `bash`, `glob`, `skill`, … (not inventory items — not counted).
- MCP tools: `<configMcpKey>_<toolName>`, e.g. `origin-edge-mcp_health_check` for config
server `origin-edge-mcp`. Attribution = longest config-key prefix match on `_`.

## Queries the miner uses (read-only)
```sql
SELECT json_extract(data,'$.tool') AS tool, time_created, session_id
FROM part WHERE json_extract(data,'$.type')='tool' AND time_created >= :cutoffMs;
SELECT json_extract(data,'$.agent') AS agent, time_created, session_id
FROM message WHERE json_extract(data,'$.agent') IS NOT NULL AND time_created >= :cutoffMs;
SELECT COUNT(DISTINCT session_id) FROM part WHERE time_created >= :cutoffMs;
```
Missing table/column ⇒ degrade to inventory-only (`{totalSessions: 0, items: {}}`).
DB opened with `node:sqlite` `DatabaseSync(path, {readOnly: true})`; when unavailable
(Node < 22.5) the adapter degrades the same way. usageSupport: 'partial' (tool parts
cover MCP + agents; skills/commands usage not yet attributable).
Loading
Loading