@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.
- package/README.md +412 -82
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -1,10 +1,254 @@
|
|
|
1
|
-
# ghx —
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
278
|
+
### Commands
|
|
32
279
|
|
|
33
280
|
```bash
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
|
|
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> #
|
|
81
|
-
ghx
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
376
|
+
### MCP server (direct tools)
|
|
116
377
|
|
|
117
378
|
```bash
|
|
118
379
|
ghx serve # stdio (for Claude, Cursor, etc.)
|
|
119
|
-
ghx serve --http :8080
|
|
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`,
|
|
123
|
-
|
|
124
|
-
## Agent Integration
|
|
384
|
+
Default mode exposes 7 tools: `explore`, `read`, `search`, `repos`, `tree`,
|
|
385
|
+
`code` (meta-tool), `search_tools`.
|
|
125
386
|
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
|
|
387
|
+
```json
|
|
388
|
+
{
|
|
389
|
+
"mcpServers": {
|
|
390
|
+
"ghx": {
|
|
391
|
+
"command": "npx",
|
|
392
|
+
"args": ["@gkoreli/ghx", "serve"]
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
129
396
|
```
|
|
130
397
|
|
|
131
|
-
|
|
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 step — npx downloads and caches the binary on first run.
|
|
136
399
|
|
|
137
|
-
|
|
400
|
+
### Agent skills
|
|
138
401
|
|
|
139
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
|
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
|
|
31
|
-
"@gkoreli/ghx-darwin-x64": "2.1
|
|
32
|
-
"@gkoreli/ghx-linux-arm64": "2.1
|
|
33
|
-
"@gkoreli/ghx-linux-x64": "2.1
|
|
34
|
-
"@gkoreli/ghx-win32-arm64": "2.1
|
|
35
|
-
"@gkoreli/ghx-win32-x64": "2.1
|
|
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
|
}
|