@gkoreli/ghx 2.1.16 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +412 -82
  2. package/package.json +8 -7
package/README.md CHANGED
@@ -1,10 +1,254 @@
1
- # ghx — GitHub Code Exploration for AI Agents
1
+ # ghx — the code-reconnaissance sidecar for AI agents
2
+
3
+ **Expensive main agents shouldn't burn frontier tokens on tree/grep/read loops.**
4
+ ghx is a cheap, specialized **sidecar agent** that a main agent delegates code
5
+ reconnaissance to. Ask it a repo question in plain English; it explores GitHub
6
+ under the hood and hands back a **schema-validated evidence report** — claims
7
+ with citations, the commands it ran, and what it could not confirm — while every
8
+ artifact of the investigation lands on disk under `~/.ghx/sessions/` for you or
9
+ the parent agent to inspect.
10
+
11
+ This is the first public cut of the **Agent Sidecar Framework**: a main agent
12
+ delegates a whole competence domain to a proficient specialist instead of loading
13
+ that domain's tools and doctrine into its own context. ghx is the proof — the
14
+ code-reconnaissance sidecar — and, underneath it, a sharp standalone GitHub
15
+ exploration CLI. The durable vision lives in
16
+ [docs/NORTH_STAR.md](docs/NORTH_STAR.md).
17
+
18
+ > ghx is two products in one binary: a **sidecar brain** you delegate to (this
19
+ > README's lead), and the **classic exploration CLI** it drives under the hood
20
+ > (documented in full further down). Use whichever fits; they share one core.
21
+
22
+ ## Why a sidecar
23
+
24
+ When a main agent stops mid-task to explore code, the real cost is not the API
25
+ calls — it is the context. Exploration output floods the window, the agent loses
26
+ the thread of the engineering work, and the ~400 lines of tool doctrine it needs
27
+ to explore well are dead weight it re-pays every session. Frontier-model tokens
28
+ spent on map/grep/read loops are pure waste when a cheap specialist can do the
29
+ same reconnaissance better.
30
+
31
+ Delegating to a sidecar removes all of it from the main agent's context. The main
32
+ agent gets measurably better at *its own* objective **and** receives better
33
+ exploration answers than it would have produced itself — both, not one. The
34
+ sidecar owns the CLI grammar, the search gotchas, the map-before-read discipline,
35
+ and the backend escalation; the outside world learns one sentence: *ask ghx repo
36
+ questions in English, get evidence reports back.*
37
+
38
+ ## What comes back: an evidence contract, not a string
39
+
40
+ The sidecar's answer is a validated report, not free text. The report schema is
41
+ enforced at submission time — the sidecar agent cannot finish a turn until it has
42
+ produced a schema-valid report, and it sees the exact validation error if it
43
+ fails (see [ADR-0021](docs/adr/0021-report-contract-enforcement.md)). Fields:
44
+
45
+ - **answer** — the direct answer to your question.
46
+ - **verified** — claims the sidecar backed with evidence it actually read.
47
+ - **relevantFiles / evidence** — where to look, and what each source showed.
48
+ - **uncertainty / nextReads** — what it could not confirm, and what to read next.
49
+ - **commandsRun** — the exact ghx commands behind the claims.
50
+
51
+ Because the trace is visible, the sidecar can be opinionated: every claim is
52
+ auditable against the commands and files it cites.
53
+
54
+ ### Full visibility under `~/.ghx`
55
+
56
+ `~/.ghx` is the product's root storage. Every question leaves a durable,
57
+ inspectable trail in its session directory — no framework, no service, just files
58
+ you can `ls` and `jq`:
2
59
 
3
- One command does what takes 3-5 API calls. Batch file reads, code maps, search — all via `gh` CLI. Write JS programs that compose operations in one round-trip.
60
+ ```
61
+ ~/.ghx/
62
+ config.json
63
+ sessions/<owner-repo>/
64
+ meta.json # session identity
65
+ ledger # evidence accumulated across questions
66
+ reports/<turn>-<ts>.json # the accepted report of every question
67
+ traces.jsonl # OTel spans: session → turn → each tool call
68
+ logs.jsonl # GenAI-convention message-content records
69
+ metrics.jsonl # duration, token, report-size metrics
70
+ ```
71
+
72
+ Sessions persist, so follow-up questions on the same repo are cheaper and
73
+ context-aware. The traces are **official OpenTelemetry** (OTLP/JSON, GenAI
74
+ semantic conventions) — any industry tool consumes them in seconds, and
75
+ `ghx sidecar view` (below) spawns a local trace UI over a session with one
76
+ command. The runtime and the eval harness emit the *same* artifacts from the
77
+ *same* code, so a real question and a benchmark episode are inspected the same
78
+ way (see [ADR-0022](docs/adr/0022-shared-visibility-runtime.md)).
79
+
80
+ Every ask response — human output, `--json`, or the MCP recon tool — ends with
81
+ an `artifacts:` pointer naming this session directory and the ask's root trace
82
+ ID, so the calling agent never has to guess where the audit trail lives.
83
+
84
+ ## How this differs from other delegation
85
+
86
+ Delegation between agents is now common; auditable delegation is not. We surveyed
87
+ the field with the sidecar itself — six real investigations, one per framework,
88
+ each with a committed report and OTel trail (see
89
+ [ADR-0026](docs/adr/0026-prior-art-landscape.md)). The finding, stated carefully:
90
+
91
+ > Across the frameworks examined, **delegation returns strings or transcripts;
92
+ > none returns a schema-validated evidence contract** (claims with citations,
93
+ > commands, uncertainty), and none gives the parent agent artifact-level
94
+ > visibility it can read without the framework, an OTel audit trail of the
95
+ > delegate, or persistent cross-question session memory it can inspect. Each
96
+ > element exists somewhere in embryo; the *combination* — auditable, steerable,
97
+ > persistent, evidence-bearing delegation as a product — had no found occupant.
98
+
99
+ This claim is deliberately scoped: it is based on six repositories examined on one
100
+ evening, the landscape moves monthly, and it is re-scanned on that cadence. We
101
+ credit the prior art we learned from and, where useful, plan to absorb it (see
102
+ the ADR's steal list and attributions).
103
+
104
+ ## How we know it works: pre-registered evals
105
+
106
+ Quality is measured, not asserted. The methodology lives in `docs/evals/`:
107
+
108
+ - **Pre-registered gates.** Correctness, evidence, compression, memory, and
109
+ safety thresholds are decided *before* a run; an under-sampled run self-labels
110
+ PRELIMINARY and cannot feed a go/no-go decision.
111
+ - **Deterministic scoring.** Every score recomputes from committed episode
112
+ artifacts — no hidden state, no live model in the loop at scoring time.
113
+ - **Independent cross-family audit.** A different model family (OpenAI Codex, run
114
+ read-only) adversarially recomputed **all 90 episode scores of the confirmatory
115
+ run exactly** and independently confirmed the gate outcomes — and logged the
116
+ provenance defects it found, which are tracked in the open. See
117
+ [the audit report](docs/evals/audit-2026-07-05-independent/REPORT.md).
118
+
119
+ The committed verdict for the confirmatory run is **THESIS SUPPORTED**
120
+ ([verdict](docs/evals/gate-run-2026-07-05-confirmatory/verdict.md),
121
+ [run dir](docs/evals/gate-run-2026-07-05-confirmatory/)). We link the verdicts
122
+ rather than headline numbers; the numbers are read as a conservative floor and
123
+ the artifacts are the proof either way. The honest negative that drove the fixes
124
+ is kept alongside it at
125
+ [docs/evals/gate-run-2026-07/](docs/evals/gate-run-2026-07/).
126
+
127
+ ## Sidecar quickstart
128
+
129
+ ### 1. Install
130
+
131
+ ```bash
132
+ # Zero install — just run it
133
+ npx @gkoreli/ghx sidecar doctor
134
+
135
+ # Homebrew
136
+ brew install gkoreli/tap/ghx
137
+
138
+ # npm (global)
139
+ npm install -g @gkoreli/ghx
140
+
141
+ # Go
142
+ go install github.com/gkoreli/ghx/v2/cmd/ghx@latest
143
+ ```
144
+
145
+ The sidecar drives an ACP-capable agent under the hood, and it reads GitHub
146
+ through the authenticated [gh CLI](https://cli.github.com/) (`gh auth login`).
147
+
148
+ ### 2. Configure the agent
149
+
150
+ The sidecar speaks [Agent Client Protocol (ACP)](https://agentclientprotocol.com)
151
+ to its underlying model. One command writes a working config using the
152
+ [claude-agent-acp](https://www.npmjs.com/package/@agentclientprotocol/claude-agent-acp)
153
+ adapter:
154
+
155
+ ```bash
156
+ ghx sidecar config init --claude-acp # writes ~/.ghx/config.json with the ACP adapter
157
+ ```
158
+
159
+ > Setup is the hardest step, so this is designed to be one command. Without
160
+ > `--claude-acp`, `config init` auto-detects any ACP-capable agent already on
161
+ > your PATH; a bare `claude` binary does **not** speak ACP on stdio and is
162
+ > rejected on purpose (it would hang every turn — see
163
+ > [ADR-0019](docs/adr/0019-sidecar-adoption-zero-cli-surface.md) D4).
164
+
165
+ Re-running `config init --claude-acp` against an existing config shows a field
166
+ diff and refuses to overwrite without `--force`.
167
+
168
+ ### 3. Verify
169
+
170
+ ```bash
171
+ ghx sidecar doctor # checks token, network, ghx binary, and the ACP handshake
172
+ ```
4
173
 
5
- ## Why
174
+ `doctor` fails fast with an actionable message if the configured agent cannot
175
+ complete the ACP handshake, and it prints where session artifacts live and how to
176
+ replay them. It also verifies that the binary serving the report-sink MCP server
177
+ matches the running ghx version — a stale sink binary would silently degrade
178
+ structured reports to a text fallback, so doctor fails loudly with fix-it text
179
+ instead.
6
180
 
7
- An agent wants to understand `packages/shadcn/src/utils/` in [shadcn-ui/ui](https://github.com/shadcn-ui/ui):
181
+ ### 4. Ask
182
+
183
+ ```bash
184
+ ghx sidecar ask --repo hono/hono "How does Hono implement middleware chaining, and which files define it?"
185
+ ```
186
+
187
+ - `--repo owner/repo` is optional scope. With it: repo-scoped reconnaissance.
188
+ Without it: **discovery** — "which repos/libraries do X" — the sidecar sweeps
189
+ GitHub for candidates and reads into the top ones before claiming anything
190
+ (see [ADR-0019.1](docs/adr/0019.1-discovery-tier.md)).
191
+ - `--session <name>` is optional (defaults to a repo slug like `hono-hono`, or a
192
+ question-derived slug for discovery asks — printed so you can resume it); use
193
+ it to keep parallel investigation threads apart.
194
+ - `--json` prints an envelope — `{"report": {...}, "artifacts": {"sessionDir":
195
+ "...", "traceId": "..."}}` — the validated report plus a pointer to the
196
+ session's audit trail. Without it you get the answer plus compact verified /
197
+ relevant-files / uncertainty sections, ending with the same pointer as a
198
+ footer line: `artifacts: <session dir> (trace <root trace id>)`.
199
+ - `--depth cheap|normal|deep` sets the command budget for deeper repos.
200
+
201
+ Ask by stating the goal, not the steps. Follow-ups on the same repo reuse the
202
+ session automatically and answer faster. A fresh question takes tens of seconds.
203
+
204
+ ### 5. Inspect
205
+
206
+ ```bash
207
+ ghx sidecar sessions list # all sessions
208
+ ghx sidecar sessions show <session> # details + report history
209
+ ghx sidecar sessions ledger <session> # the accumulated evidence ledger
210
+ ghx sidecar view [session] # spawn a local trace UI over the session's artifacts
211
+ ghx sidecar view --list # sessions with turn/report counts
212
+ ghx sidecar view --port 9000 # viewer UI port (default 8000)
213
+ ```
214
+
215
+ `ghx sidecar view` absorbs the
216
+ [otel-desktop-viewer](https://github.com/CtrlSpice/otel-desktop-viewer) replay
217
+ recipe into one command: it starts the viewer and loads the session's
218
+ `traces.jsonl` (plus logs/metrics when present) for you — no argument means the
219
+ most recent session. Everything it shows is the same file you can read by hand.
220
+ Requires the viewer on PATH:
221
+ `go install github.com/CtrlSpice/otel-desktop-viewer@latest`.
222
+
223
+ ### Delegating from a main agent (MCP)
224
+
225
+ A main agent talks to the sidecar through a single MCP tool — one tool it cannot
226
+ be tempted into step-driving:
227
+
228
+ ```bash
229
+ ghx serve --recon # exposes exactly one MCP tool: recon(question, repo, session?)
230
+ ```
231
+
232
+ The recommended skill for agents is the concise recon skill (`ghx skill --recon`,
233
+ ≤ 30 lines: what the service is, how to phrase questions, what the report fields
234
+ mean). The main agent needs **zero** knowledge of the ghx CLI grammar — that is
235
+ the whole point ([ADR-0019](docs/adr/0019-sidecar-adoption-zero-cli-surface.md)).
236
+
237
+ ---
238
+
239
+ # The classic ghx CLI (the tool layer)
240
+
241
+ Under the sidecar brain is a sharp, standalone GitHub exploration CLI — the #1
242
+ direct tool for reconnaissance, and the eval baseline the sidecar is measured
243
+ against. Use it directly when you want to drive exploration yourself. **One
244
+ command does what takes 3–5 API calls.** Batch file reads, structural code maps,
245
+ and search — all via the `gh` CLI, or composed in a single round-trip with
246
+ codemode.
247
+
248
+ ### Why it's faster than raw `gh`
249
+
250
+ An agent wants to understand `packages/shadcn/src/utils/` in
251
+ [shadcn-ui/ui](https://github.com/shadcn-ui/ui):
8
252
 
9
253
  **With `gh` CLI** — 4 turns, 4 API calls, reads 3 full files (3,761 tokens), sees 3 of 34 files:
10
254
  ```
@@ -20,7 +264,10 @@ ghx read shadcn-ui/ui packages/shadcn/src/utils → director
20
264
  ghx read shadcn-ui/ui "packages/shadcn/src/utils/*.ts" --map → signatures of 10 files (2,859 tokens)
21
265
  ```
22
266
 
23
- Same token budget. The `gh` agent read 3 full files. The ghx agent saw the structure of 10 — imports, exports, function signatures — and knows which ones to drill into. Pass a file, get content. Pass a directory, get a listing. Pass a glob, get matching files. Same command, always useful output.
267
+ Same token budget. The `gh` agent read 3 full files; the ghx agent saw the
268
+ structure of 10 — imports, exports, signatures — and knows which to drill into.
269
+ Pass a file, get content. Pass a directory, get a listing. Pass a glob, get
270
+ matching files. Same command, always useful output.
24
271
 
25
272
  | Tool | Files per call | Matching context | Programmable | Dependencies |
26
273
  |------|---------------|-----------------|-------------|-------------|
@@ -28,48 +275,15 @@ Same token budget. The `gh` agent read 3 full files. The ghx agent saw the struc
28
275
  | `gh` CLI | 1 | No | No (exact phrase, base64, no README) | `gh` |
29
276
  | **ghx** | **1-10 (batch)** | **Yes** | **Yes (codemode)** | **`gh`** |
30
277
 
31
- ## Install
278
+ ### Commands
32
279
 
33
280
  ```bash
34
- # Zero install just run it
35
- npx @gkoreli/ghx explore vercel/next.js
36
-
37
- # Homebrew
38
- brew install gkoreli/tap/ghx
39
-
40
- # npm (global)
41
- npm install -g @gkoreli/ghx
42
-
43
- # Go
44
- go install github.com/gkoreli/ghx/v2@latest
45
-
46
- # Build from source
47
- cd v2 && go build -o ghx .
48
- ```
49
-
50
- Requires: [gh CLI](https://cli.github.com/) authenticated (`gh auth login`).
51
-
52
- ### MCP Config (Claude Desktop, Cursor)
53
-
54
- ```json
55
- {
56
- "mcpServers": {
57
- "ghx": {
58
- "command": "npx",
59
- "args": ["@gkoreli/ghx", "serve"]
60
- }
61
- }
62
- }
63
- ```
64
-
65
- No install step — npx downloads and caches the binary on first run.
66
-
67
- ## Commands
68
-
69
- ```bash
70
- ghx explore <owner/repo> # Branch + tree + README in 1 API call
71
- ghx explore <owner/repo> <path> # Subdirectory listing
72
- ghx read <owner/repo> <f1> [f2] [f3] # Read 1-10 files (GraphQL batching)
281
+ ghx --version # Health check / installed version
282
+ ghx explore <owner/repo> # Compact branch + tree + README orientation
283
+ ghx explore <owner/repo> --full # Complete legacy explore output
284
+ ghx explore <owner/repo> <path> # Compact subdirectory listing
285
+ ghx explore <owner/repo> --budget 20000 # Raise the compact output budget
286
+ ghx read <owner/repo> <f1> [f2] [f3] # Read 1-10 files (large files map first)
73
287
  ghx read <owner/repo> <dir> # Directory path → returns file listing
74
288
  ghx read <owner/repo> "src/**/*.ts" --map # Glob patterns with structural map
75
289
  ghx read <owner/repo> --map <f1> [f2] # Parser-backed structural map (~92% token reduction)
@@ -77,16 +291,63 @@ ghx read <owner/repo> --map --kind func <f> # Map only functions/methods
77
291
  ghx read <owner/repo> --map --kind type <f> # Map only types/structs/interfaces
78
292
  ghx read <owner/repo> --map --level minimal <f> # Symbol names only (e.g. UserService.GetUser)
79
293
  ghx read <owner/repo> --grep "pat" <f> # Matching lines only (ERE regex, 2 lines context)
80
- ghx read <owner/repo> --lines 42-80 <f> # Specific line range
81
- ghx search "<query>" # Code search with matching lines
294
+ ghx read <owner/repo> --lines 42-80 <f> # Canonical line range
295
+ ghx read <owner/repo> <f> --full # Force complete content past the budget
296
+ ghx search <owner/repo> "func main" # Repo-first code search, auto-quotes the query
297
+ ghx search <owner/repo> "router" --lang go # Narrow by language
298
+ ghx search <owner/repo> "router" --glob "**/*.go" # Narrow by path glob
299
+ ghx search "repo:gkoreli/ghx cobra.Command" # Advanced raw GitHub code-search query
300
+ ghx grep <owner/repo> "func main" # Grep-like repo search
301
+ ghx grep <owner/repo> "RunE" --path internal/cli --limit 10
82
302
  ghx repos "<query>" # Repo search with README preview
83
303
  ghx tree <owner/repo> [path] # Full recursive tree
84
304
  ghx tree <owner/repo> [path] --depth N # Tree limited to N levels
305
+ ghx tier2 codemap <owner/repo> # Tier-2 cross-file structure as JSON (local snapshot)
306
+ ghx tier2 codemap <owner/repo> --context # Agent-ready JSON context envelope (--compact to shrink)
307
+ ghx tier2 codemap <owner/repo> --importers <file> # Who imports a file (fan-in; needs ast-grep)
308
+ ghx tier2 codemap <owner/repo> --deps # Dependency flow / import chains (needs ast-grep)
309
+ ghx tier2 codemap <owner/repo> --ref v1.2.3 --sparse src # Pin a ref, materialize only candidate paths
310
+ ghx tier2 astgrep <owner/repo> --pattern 'compose($$$A)' --lang ts # Structural AST pattern search (JSON matches)
311
+ ghx tier2 astgrep <owner/repo> --pattern 'errors.Is($E, $T)' --lang go src # Scope the search to paths
312
+ ghx tier2 repomap <owner/repo> # Rank the files that matter (graph centrality, token budget)
313
+ ghx tier2 repomap <owner/repo> --query route --budget 512 # Bias ranking to the question, cap output tokens
85
314
  ```
86
315
 
87
- ## Codemode
88
-
89
- Write JS programs that compose multiple operations in one round-trip. All `codemode.*` calls are synchronous — no `await`. Full TypeScript type stubs with return types are injected into the sandbox.
316
+ `read` documents one range spelling, `--lines START-END`, but accepts hidden
317
+ agent-guess aliases: `--start N --end M` and `--offset N --limit M`. They work
318
+ for frictionless retries and stay out of help so examples converge on one form.
319
+
320
+ Output-heavy commands share `--budget CHARS` and `--full`: defaults are bounded,
321
+ and truncation text names the exact flag to lift or narrow the result.
322
+
323
+ Exit codes are semantic: `0` ok, `1` no results, `2` bad invocation, `3`
324
+ upstream/API failure.
325
+
326
+ `tier2` commands are the deliberate, visible escalation beyond remote evidence
327
+ ([ADR-0024.1](docs/adr/0024.1-escalation-tiers-decision.md)): the repo/ref is
328
+ resolved to a commit SHA and materialized as a shallow, blobless, read-only
329
+ snapshot cached by SHA under `~/.ghx/cache/tier2` (`$GHX_HOME` respected;
330
+ 5 GiB budget, 30-day LRU/TTL eviction). Snapshot provenance — repo, ref,
331
+ resolved SHA, clone strategy, cache hit — prints to stderr before any tool
332
+ output, and structural tools run as absorbed backends under canonical IDs:
333
+ `local:codemap` (subprocess, via
334
+ [codemap](https://github.com/JordanCoin/codemap), MIT), `local:ast-grep`
335
+ (subprocess, via [ast-grep](https://github.com/ast-grep/ast-grep), MIT — also
336
+ the binary codemap needs for `--importers`/`--deps`), and `local:repomap`
337
+ (built in: the budgeted definition/reference/import-graph PageRank ranking
338
+ stolen with attribution from
339
+ [aider's repo map](https://github.com/Aider-AI/aider), Apache-2.0 — an
340
+ algorithm, not a dependency; deterministic given the same snapshot and
341
+ query). If a tool binary is missing, ghx prints the install hint and exits
342
+ before any clone; answers fall back to remote Tier-1 evidence — never a
343
+ silent or faked Tier-2 result. `astgrep` follows grep parity: exit `1` with
344
+ `[]` means the search ran and found nothing.
345
+
346
+ ### Codemode
347
+
348
+ Write JS programs that compose multiple operations in one round-trip. All
349
+ `codemode.*` calls are synchronous — no `await`. Full TypeScript type stubs with
350
+ return types are injected into the sandbox.
90
351
 
91
352
  ```bash
92
353
  # What branch is this repo on?
@@ -112,56 +373,125 @@ declare const codemode: {
112
373
  }
113
374
  ```
114
375
 
115
- ## MCP Server
376
+ ### MCP server (direct tools)
116
377
 
117
378
  ```bash
118
379
  ghx serve # stdio (for Claude, Cursor, etc.)
119
- ghx serve --http :8080 # HTTP transport
380
+ ghx serve --http :8080 # HTTP transport
381
+ ghx serve --recon # single-tool sidecar mode (see above)
120
382
  ```
121
383
 
122
- 7 tools: `explore`, `read`, `search`, `repos`, `tree`, `code` (meta-tool), `search_tools`.
123
-
124
- ## Agent Integration
384
+ Default mode exposes 7 tools: `explore`, `read`, `search`, `repos`, `tree`,
385
+ `code` (meta-tool), `search_tools`.
125
386
 
126
- ```bash
127
- ghx skill # CLI skill (for SKILL.md injection)
128
- ghx skill --mcp # MCP skill
387
+ ```json
388
+ {
389
+ "mcpServers": {
390
+ "ghx": {
391
+ "command": "npx",
392
+ "args": ["@gkoreli/ghx", "serve"]
393
+ }
394
+ }
395
+ }
129
396
  ```
130
397
 
131
- Designed for eager context injection via spawn hooks the agent always has the latest ghx knowledge without loading it mid-conversation.
132
-
133
- ## How It Was Built
134
-
135
- 23 agent sessions, 2,500+ conversation turns, 3 rewrites, 12 ADRs. The full story: **[Build the GitHub Exploration Tool, No Mistakes](https://gkoreli.com/how-ghx-was-born)**
398
+ No install stepnpx downloads and caches the binary on first run.
136
399
 
137
- ## How It Works
400
+ ### Agent skills
138
401
 
139
- Wraps `gh` CLI with GraphQL batching. `repos` and `explore` batch search + metadata + README into 1 call. `read` uses GraphQL aliases to fetch up to 10 files in 1 call — and if a path is a directory, returns its file listing instead of "not found" (via `... on Tree` inline fragments in the same query, zero extra API calls). Glob patterns (`src/**/*.ts`) auto-expand via tree fetch + [doublestar](https://github.com/bmatcuk/doublestar) matching in 2 API calls. `--grep` uses ERE regex with BRE normalization (agents trained on `grep` write `\|` for alternation — both styles work). `search` hits REST `/search/code` with `text_matches` for matching context and 200-char token protection.
402
+ ```bash
403
+ ghx skill # classic CLI skill (power-user path)
404
+ ghx skill --mcp # classic MCP skill
405
+ ghx skill --recon # concise recon skill (recommended for agents)
406
+ ```
140
407
 
141
- `--map` runs a dedicated parser engine on the fetched content — no extra API calls. Engine selection is automatic: **Go** uses `go/ast` (top-level declarations only, full multi-line signatures, generics preserved), **TypeScript, JavaScript, Python, Rust** use [gotreesitter](https://github.com/odvcencio/gotreesitter) (captures class/impl methods that regex cannot reach), everything else falls back to regex. Methods carry a parent reference (`UserService.GetUser`) visible at `--level minimal`. `--map-engine regex` forces the fallback for any file.
408
+ ```bash
409
+ npx skills add gkoreli/ghx -g -a claude-code --skill ghx -y
410
+ npx skills add gkoreli/ghx -g -a claude-code --skill ghx-mcp -y
411
+ ```
142
412
 
143
- Codemode runs JS in a [goja](https://github.com/nicholasgasior/goja) sandbox with esbuild TypeScript transpilation. Tools are injected as synchronous functions on a `codemode` global object. Max 20 tool calls per execution, 64KB code size limit.
413
+ ## How it works
414
+
415
+ The classic CLI wraps `gh` with GraphQL batching. `repos` and `explore` batch
416
+ search + metadata + README into 1 call. `read` uses GraphQL aliases to fetch up
417
+ to 10 files in 1 call — and if a path is a directory, returns its listing instead
418
+ of "not found" (via `... on Tree` inline fragments, zero extra API calls). Glob
419
+ patterns (`src/**/*.ts`) auto-expand via tree fetch +
420
+ [doublestar](https://github.com/bmatcuk/doublestar) matching in 2 API calls.
421
+ `--grep` uses ERE regex with BRE normalization. `search` hits REST
422
+ `/search/code` with `text_matches` for matching context.
423
+
424
+ `--map` runs a dedicated parser engine on the fetched content — no extra API
425
+ calls. Engine selection is automatic: **Go** uses `go/ast`; **TypeScript,
426
+ JavaScript, Python, Rust** use tree-sitter (via
427
+ [gotreesitter](https://github.com/odvcencio/gotreesitter), capturing class/impl
428
+ methods regex cannot reach); everything else falls back to regex. Codemode runs
429
+ JS in a [goja](https://github.com/nicholasgasior/goja) sandbox with esbuild
430
+ TypeScript transpilation (max 20 tool calls, 64 KB code limit).
431
+
432
+ The **sidecar** wraps that same core behind an ACP agent that owns the
433
+ exploration doctrine, validates its own evidence report before finishing
434
+ ([ADR-0021](docs/adr/0021-report-contract-enforcement.md)), and emits OTel
435
+ artifacts to `~/.ghx/sessions/`
436
+ ([ADR-0022](docs/adr/0022-shared-visibility-runtime.md)).
144
437
 
145
438
  ## Architecture
146
439
 
147
440
  ```
148
- v2/
149
- ├── internal/mapengine/ parser-backed map engine (GoAST, TreeSitter, Regex, engine routing)
150
- ├── pkg/ghx/ — core library (Explore, Read, Search, Repos, Tree, Glob)
151
- ├── pkg/codemode/ — JS executor (goja sandbox, TS transpilation, type generation)
152
- └── cmd/ CLI frontend (cobra) + MCP server (mcp-go)
441
+ cmd/ghx/ — binary entrypoint
442
+ internal/cli/ CLI frontend (cobra) + MCP + sidecar commands
443
+ internal/ghx/ — core library (Explore, Read, Search, Repos, Tree, Glob)
444
+ internal/codemode/ — JS executor (goja sandbox, TS transpilation, type generation)
445
+ internal/mapengine/ parser-backed map engine (GoAST, TreeSitter, Regex, routing)
446
+ internal/sidecar/ — sidecar runtime, sessions, report contract, ACP integration
447
+ internal/sidecar/telemetry/ — shared OTel emission (runtime + evals, one capability)
448
+ skills/ — CLI, MCP, and recon agent skills, embedded via go:embed
153
449
  ```
154
450
 
155
- See [docs/adr/](docs/adr/) for architectural decisions.
156
-
157
- ## v1 (bash)
158
-
159
- The original bash implementation is in [`v1/`](v1/). Zero dependencies beyond `gh` and `jq` — useful if you just want a shell script you can drop anywhere without compiling Go.
160
-
161
- ```bash
162
- npm install -g @gkoreli/ghx # npm
163
- cp v1/ghx /usr/local/bin/ghx # manual
164
- ```
451
+ Core capabilities live in `internal/ghx`; every frontend — CLI, MCP, codemode,
452
+ sidecar — wraps the same core. See [docs/adr/](docs/adr/) for the full decision
453
+ record and [docs/NORTH_STAR.md](docs/NORTH_STAR.md) for direction.
454
+
455
+ ## Built on open source, openly
456
+
457
+ ghx exists because exploring open source for ideas is where good products come
458
+ from "good artists copy, great artists steal," and we steal in the Picasso
459
+ sense: openly, with attribution, and with stewardship for future generations. The
460
+ rule we build by: **use official standards and existing open-source tools,
461
+ libraries, and ideas first; hand-roll a framework or format only when nothing
462
+ existing serves the need or the vision.**
463
+
464
+ - Agent traces are **official OpenTelemetry** (OTLP/JSON) following the
465
+ [OTel GenAI semantic conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/),
466
+ so any industry tool — Jaeger, the collector,
467
+ [otel-desktop-viewer](https://github.com/CtrlSpice/otel-desktop-viewer) — reads
468
+ them in seconds.
469
+ - The sidecar speaks the [Agent Client Protocol (ACP)](https://agentclientprotocol.com)
470
+ via the
471
+ [claude-agent-acp](https://www.npmjs.com/package/@agentclientprotocol/claude-agent-acp)
472
+ adapter — an adopted boundary, never a bespoke wire protocol.
473
+ - Parsing rides on [gotreesitter](https://github.com/odvcencio/gotreesitter) and
474
+ `go/ast`; globbing on [doublestar](https://github.com/bmatcuk/doublestar);
475
+ codemode on [goja](https://github.com/nicholasgasior/goja); GitHub access on
476
+ the [gh CLI](https://cli.github.com/).
477
+
478
+ Where we do build new — ghx and the Agent Sidecar Framework — it is because the
479
+ thing did not exist, and it is inspired loudly by what does. Tools like
480
+ [codemap](https://github.com/JordanCoin/codemap) and
481
+ [ast-grep](https://github.com/ast-grep/ast-grep) shape the sidecar's internal
482
+ toolbox: `ghx tier2 codemap` and `ghx tier2 astgrep` absorb them as internal
483
+ subprocess backends (`local:codemap`, `local:ast-grep`, ADR-0024.1) rather
484
+ than competing on CLI surface (see
485
+ [ADR-0026](docs/adr/0026-prior-art-landscape.md)), and `ghx tier2 repomap`
486
+ steals the budgeted graph-ranking algorithm behind
487
+ [aider's repo map](https://github.com/Aider-AI/aider) without the dependency.
488
+ MIT in, MIT out.
489
+
490
+ ## How it was built
491
+
492
+ 23 agent sessions, 2,500+ conversation turns, 3 rewrites, and a growing ADR
493
+ record. The origin story:
494
+ **[Build the GitHub Exploration Tool, No Mistakes](https://gkoreli.com/how-ghx-was-born)**
165
495
 
166
496
  ## License
167
497
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gkoreli/ghx",
3
- "version": "2.1.16",
3
+ "version": "2.3.1",
4
4
  "description": "Agent-first GitHub code exploration. GraphQL batching, code maps, codemode TypeScript sandbox, MCP server.",
5
5
  "bin": {
6
6
  "ghx": "npm/bin/ghx"
@@ -18,6 +18,7 @@
18
18
  "type": "git",
19
19
  "url": "git+https://github.com/gkoreli/ghx.git"
20
20
  },
21
+ "packageManager": "pnpm@10.22.0",
21
22
  "files": [
22
23
  "npm/bin/ghx",
23
24
  "README.md",
@@ -27,11 +28,11 @@
27
28
  "node": ">=16"
28
29
  },
29
30
  "optionalDependencies": {
30
- "@gkoreli/ghx-darwin-arm64": "2.1.16",
31
- "@gkoreli/ghx-darwin-x64": "2.1.16",
32
- "@gkoreli/ghx-linux-arm64": "2.1.16",
33
- "@gkoreli/ghx-linux-x64": "2.1.16",
34
- "@gkoreli/ghx-win32-arm64": "2.1.16",
35
- "@gkoreli/ghx-win32-x64": "2.1.16"
31
+ "@gkoreli/ghx-darwin-arm64": "2.3.1",
32
+ "@gkoreli/ghx-darwin-x64": "2.3.1",
33
+ "@gkoreli/ghx-linux-arm64": "2.3.1",
34
+ "@gkoreli/ghx-linux-x64": "2.3.1",
35
+ "@gkoreli/ghx-win32-arm64": "2.3.1",
36
+ "@gkoreli/ghx-win32-x64": "2.3.1"
36
37
  }
37
38
  }