npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gkoreli/ghx

v2.10.1

Published

Agent-first GitHub code exploration. GraphQL batching, code maps, codemode TypeScript sandbox, MCP server.

Readme

ghx — the code-reconnaissance sidecar for AI agents

Expensive main agents shouldn't burn frontier tokens on tree/grep/read loops. ghx is a cheap, specialized sidecar agent that a main agent delegates code reconnaissance to. Ask it a repo question in plain English; it explores GitHub under the hood and hands back a schema-validated evidence report — claims with citations, the commands it ran, and what it could not confirm — while every artifact of the investigation lands on disk under ~/.ghx/sessions/ for you or the parent agent to inspect.

This is the first public cut of the Agent Sidecar Framework: a main agent delegates a whole competence domain to a proficient specialist instead of loading that domain's tools and doctrine into its own context. ghx is the proof — the code-reconnaissance sidecar — and, underneath it, a sharp standalone GitHub exploration CLI. The durable vision lives in docs/NORTH_STAR.md.

ghx is two products in one binary: a sidecar brain you delegate to (this README's lead), and the classic exploration CLI it drives under the hood (documented in full further down). Use whichever fits; they share one core.

Engineering record

ghx has been developed in public through a sequence of maintainer field notes:

These are engineering records, including doubts and failed paths — not product documentation or independent reviews.

Why a sidecar

When a main agent stops mid-task to explore code, the real cost is not the API calls — it is the context. Exploration output floods the window, the agent loses the thread of the engineering work, and the ~400 lines of tool doctrine it needs to explore well are dead weight it re-pays every session. Frontier-model tokens spent on map/grep/read loops are pure waste when a cheap specialist can do the same reconnaissance better.

Delegating to a sidecar removes all of it from the main agent's context. The main agent gets measurably better at its own objective and receives better exploration answers than it would have produced itself — both, not one. The sidecar owns the CLI grammar, the search gotchas, the map-before-read discipline, and the backend escalation; the outside world learns one sentence: ask ghx repo questions in English, get evidence reports back.

What comes back: an evidence contract, not a string

The sidecar's answer is a validated report, not free text. The report schema is enforced at submission time — the sidecar agent cannot finish a turn until it has produced a schema-valid report, and it sees the exact validation error if it fails (see ADR-0021). Fields:

  • answer — the direct answer to your question.
  • verified — claims the sidecar backed with evidence it actually read.
  • relevantFiles / evidence — where to look, and what each source showed.
  • uncertainty / nextReads — what it could not confirm, and what to read next.
  • commandsRun — the exact ghx commands behind the claims.

Because the trace is visible, the sidecar can be opinionated: every claim is auditable against the commands and files it cites.

Full visibility under ~/.ghx

~/.ghx is the product's root storage. Every question leaves a durable, inspectable trail in its session directory — no framework, no service, just files you can ls and jq:

~/.ghx/
  config.json
  sessions/<owner-repo>/
    meta.json                 # session identity
    ledger                    # evidence accumulated across questions
    reports/<turn>-<ts>.json  # the accepted report of every question
    traces.jsonl              # OTel spans: session → turn → each tool call
    logs.jsonl                # GenAI-convention message-content records
    metrics.jsonl             # duration, token, report-size metrics
    tier-decisions.jsonl      # escalation policy evaluation per turn (which tier, why)
    live.jsonl                # realtime turn activity, appended as it happens

The OTLP artifacts are written when a question completes; live.jsonl streams turn activity in realtime — turn start/end, text and thought chunks, every tool call and update as the agent works — so tail -f ~/.ghx/sessions/<name>/live.jsonl watches a running question instead of waiting minutes for the final report (see ADR-0022.1). ghx sidecar tail --follow renders that stream as one human-readable line per event, so you rarely need the raw tail -f.

Sessions persist, so follow-up questions on the same repo are cheaper and context-aware. The traces are official OpenTelemetry (OTLP/JSON, GenAI semantic conventions) — any industry tool consumes them in seconds, and ghx sidecar view (below) spawns a local trace UI over a session with one command. The runtime and the eval harness emit the same artifacts from the same code, so a real question and a benchmark episode are inspected the same way (see ADR-0022).

Every ask response — human output, --json, or the MCP recon tool — ends with an artifacts: pointer naming this session directory and the ask's root trace ID, so the calling agent never has to guess where the audit trail lives.

How this differs from other delegation

Delegation between agents is now common; auditable delegation is not. We surveyed the field with the sidecar itself — six real investigations, one per framework, each with a committed report and OTel trail (see ADR-0026). The finding, stated carefully:

Across the frameworks examined, delegation returns strings or transcripts; none returns a schema-validated evidence contract (claims with citations, commands, uncertainty), and none gives the parent agent artifact-level visibility it can read without the framework, an OTel audit trail of the delegate, or persistent cross-question session memory it can inspect. Each element exists somewhere in embryo; the combination — auditable, steerable, persistent, evidence-bearing delegation as a product — had no found occupant.

This claim is deliberately scoped: it is based on six repositories examined on one evening, the landscape moves monthly, and it is re-scanned on that cadence. We credit the prior art we learned from and, where useful, plan to absorb it (see the ADR's steal list and attributions).

How we know it works: pre-registered evals

Quality is measured, not asserted. The methodology lives in docs/evals/:

  • Pre-registered gates. Correctness, evidence, compression, memory, and safety thresholds are decided before a run; an under-sampled run self-labels PRELIMINARY and cannot feed a go/no-go decision.
  • Deterministic scoring. Every score recomputes from committed episode artifacts — no hidden state, no live model in the loop at scoring time.
  • Independent cross-family audit. A different model family (OpenAI Codex, run read-only) adversarially recomputed all 90 episode scores of the confirmatory run exactly and independently confirmed the gate outcomes — and logged the provenance defects it found, which are tracked in the open. See the audit report.

The committed verdict for the confirmatory run is THESIS SUPPORTED (verdict, run dir). We link the verdicts rather than headline numbers; the numbers are read as a conservative floor and the artifacts are the proof either way. The honest negative that drove the fixes is kept alongside it at docs/evals/gate-run-2026-07/.

Sidecar quickstart

1. Install

# Zero install — just run it
npx @gkoreli/ghx sidecar doctor

# Homebrew
brew install gkoreli/tap/ghx

# npm (global)
npm install -g @gkoreli/ghx

# Go
go install github.com/gkoreli/ghx/v2/cmd/ghx@latest

The sidecar drives an ACP-capable agent under the hood, and it reads GitHub through the authenticated gh CLI (gh auth login).

2. Configure the agent (optional — zero-config works)

The sidecar speaks Agent Client Protocol (ACP) to its underlying model. With no config at all, the pinned claude-agent-acp adapter is the default — if you have Node/npx and are logged into Claude Code, ghx sidecar ask works out of the box. Write an explicit config only to pin a different agent or model:

ghx sidecar config init --claude-acp    # writes ~/.ghx/config.json with the ACP adapter

Without --claude-acp, config init auto-detects any ACP-capable agent already on your PATH; a bare claude binary does not speak ACP on stdio and is rejected on purpose (it would hang every turn — see ADR-0019 D4).

Re-running config init --claude-acp against an existing config shows a field diff and refuses to overwrite without --force.

Using your installed Claude Code (toolbox / wrapper builds). The adapter's SDK ships its own bundled Claude Code binary and its own credential store — by default your claude on PATH (and its ~/.claude/settings.json, credential hooks, model aliases) is not what runs. If your organization installs a wrapped claude that carries work credentials, point the adapter at it with CLAUDE_CODE_EXECUTABLE (honored by claude-agent-acp ≥ 0.55):

{
  "agent": "env CLAUDE_CODE_EXECUTABLE=/path/to/your/claude npx -y @agentclientprotocol/[email protected]"
}

ghx sidecar config init --claude-exe /path/to/your/claude writes exactly this config for you (--claude-exe auto resolves claude from your PATH; the same diff-and---force rules apply).

Known upstream issue (enterprise wrapper builds): when CLAUDE_CODE_EXECUTABLE points at a wrapper script/binary (e.g. a corporate toolbox claude that resolves credentials itself), the adapter can hang indefinitely at prompt time: ghx legitimately sends ACP settingSources: [] for session isolation, and some wrappers stall instead of erroring when settings loading is suppressed (isolated 2026-07-06: settingSources: [] alone reproduces the hang; strictMcpConfig and tools do not; mechanism: the native binary resolves Bedrock modelOverrides from ~/.claude/settings.json and stalls instead of erroring when that read is suppressed). The fix is one config line:

{
  "agent": "env CLAUDE_CODE_EXECUTABLE=/path/to/your/claude npx -y @agentclientprotocol/[email protected]",
  "agentSettingSources": ["user"]
}

agentSettingSources opts the spawned agent into loading your user settings (~/.claude/settings.json) so the wrapper's model aliases and credential hooks work. It deliberately weakens session isolation — host user settings apply to sidecar sessions — which is why it is opt-in and off by default (ADR-0033.2). Wrapping the adapter in a script that exports auth env itself remains a valid alternative.

Embedding env VAR=... in the agent command makes the setting travel with the command itself, so it works no matter which process (CLI or resident daemon) spawns the agent. Exporting CLAUDE_CODE_EXECUTABLE in your shell also works: every ask forwards auth-relevant env to the agent (ADR-0033.1), and the same applies to Bedrock/Vertex/gateway env (CLAUDE_CODE_USE_BEDROCK, AWS_*, ANTHROPIC_BASE_URL, ...). ghx sidecar doctor shows exactly which names your shell would forward.

3. Verify

ghx sidecar doctor           # token, network, ghx binary, ACP handshake, report sink
ghx sidecar doctor --live    # also run a REAL one-prompt turn through the agent

doctor fails fast with an actionable message if the configured agent cannot complete the ACP handshake, and it prints where session artifacts live and how to replay them. It also verifies that the binary serving the report-sink MCP server matches the running ghx version — a stale sink binary would silently degrade structured reports to a text fallback, so doctor fails loudly with fix-it text instead.

--live goes one step further: the plain handshake stops at ACP initialize, which passes even on setups where a real turn then fails (auth typically resolves lazily at prompt time). --live runs a full session/new + one tiny prompt turn through the configured agent and, on failure, prints the failing stage and the agent's stderr tail — the deterministic way to diagnose a machine where ask produces nothing (see ADR-0033).

4. Ask

ghx sidecar ask --repo hono/hono "How does Hono implement middleware chaining, and which files define it?"
  • --repo owner/repo is optional scope. With it: repo-scoped reconnaissance. Without it: discovery — "which repos/libraries do X" — the sidecar sweeps GitHub for candidates and reads into the top ones before claiming anything (see ADR-0019.1).
  • --session <name> is advanced: pin a specific session; normally omit — ghx routes each question to the right session for you (ADR-0030.1). With --repo the repo-slug session (like hono-hono) still stands; with neither flag the daemon runs a deterministic cascade (explicit → repo mention in the question → warm continuation → ledger overlap → new session) and reports the route it chose: session: hono-hono (routed: overlap 0.62, next 0.21).
  • --json prints an envelope — {"report": {...}, "artifacts": {"sessionDir": "...", "traceId": "..."}} — the validated report plus a pointer to the session's audit trail. Without it you get the answer plus compact verified / relevant-files / uncertainty sections, ending with the same pointer as a footer line: artifacts: <session dir> (trace <root trace id>).
  • --depth cheap|normal|deep sets the command budget for deeper repos.

Ask by stating the goal, not the steps. Follow-ups on the same repo reuse the session automatically and answer faster. A fresh question takes tens of seconds.

5. Inspect

ghx sidecar sessions list                 # all sessions
ghx sidecar sessions show <session>       # details + report history
ghx sidecar sessions ledger <session>     # the accumulated evidence ledger
ghx sidecar sessions reroute <s> <turn> <dest>  # move a mis-routed turn; both ledgers rebuilt by replay
ghx sidecar tail [session] --follow       # human-readable live view of a running question
ghx sidecar view [session]                # spawn a local trace UI over the session's artifacts
ghx sidecar view --list                   # sessions with turn/report counts
ghx sidecar view --port 9000              # viewer UI port (default 8000)

ghx sidecar view absorbs the otel-desktop-viewer replay recipe into one command: it starts the viewer and loads the session's traces.jsonl (plus logs/metrics when present) for you — no argument means the most recent session. Everything it shows is the same file you can read by hand. Requires the viewer on PATH: go install github.com/CtrlSpice/otel-desktop-viewer@latest.

Troubleshooting

If an ask returns nothing useful, the failure is recorded, not lost (ADR-0033):

  • Per-session agent stderr. The spawned agent's stderr is captured to ~/.ghx/sessions/<session>/agent-stderr.log. Under the always-on daemon it no longer disappears into the daemon's own log. A failed turn also splices the tail of that log — and its path — into the error the CLI prints.
  • Reproduce it deterministically. ghx sidecar doctor --live runs a real prompt turn and prints the failing stage plus the agent's stderr, even when the plain handshake passes.
  • this workspace has not been trusted. ghx already runs the agent in a neutral, ghx-owned session directory (outside any git repo, no .claude settings), so this warning should not appear. If it still does, the agent picked up a git-repo workspace: trust it once (run the agent interactively there and accept the dialog) or set projects["<dir>"].hasTrustDialogAccepted: true in ~/.claude.json. ghx will never write that file for you.
  • "works from shell A, fails from shell B". The daemon auto-spawns from the first caller's environment, so a missing auth/proxy env var is a common cause. ghx sidecar sessions show <session> lists the agent command, the session's spawn cwd, and the names (never values) of the agent-relevant environment variables present when it was created. If the wrong env was inherited, ghx sidecar daemon --stop and re-run ask from a shell that has the right variables.

Delegating from a main agent (MCP)

A main agent talks to the sidecar through a single MCP tool — one tool it cannot be tempted into step-driving. Bare ghx serve is that surface:

ghx serve             # default: exactly one MCP tool — recon(question, repo?, session?, depth?)
ghx serve --direct    # the seven direct ghx tools + code meta-tool (the pre-2.11 default)

Every answer is a machine-parseable JSON object: { report, route, artifacts } — the evidence contract plus route provenance and audit-trail pointers inside the payload, never appended as prose (ADR-0019.3).

Install rails — paste this block into your client's MCP config (or run ghx serve --print-mcp-config to print it):

{
  "mcpServers": {
    "ghx": { "command": "npx", "args": ["-y", "@gkoreli/ghx", "serve"] }
  }
}

Then verify wiring before first use — auth/env failures are the real tax, and doctor surfaces them with remediation instead of a mid-question hang:

npx @gkoreli/ghx sidecar doctor

The recommended skill for agents is the concise recon skill (ghx skill --recon, ≤ 30 body lines: what the service is, how to phrase questions, what the report fields mean). The main agent needs zero knowledge of the ghx CLI grammar — that is the whole point (ADR-0019).


The classic ghx CLI (the tool layer)

Under the sidecar brain is a sharp, standalone GitHub exploration CLI — the #1 direct tool for reconnaissance, and the eval baseline the sidecar is measured against. Use it directly when you want to drive exploration yourself. One command does what takes 3–5 API calls. Batch file reads, structural code maps, and search — all via the gh CLI, or composed in a single round-trip with codemode.

Why it's faster than raw gh

An agent wants to understand packages/shadcn/src/utils/ in shadcn-ui/ui:

With gh CLI — 4 turns, 4 API calls, reads 3 full files (3,761 tokens), sees 3 of 34 files:

gh api /repos/shadcn-ui/ui/contents/packages/shadcn/src/utils       → JSON with shas, urls, links (480 tokens for a file list)
gh api /repos/.../get-config.ts --jq '.content' | base64 -d         → full file (1,981 tokens — agent only needed exports)
gh api /repos/.../registries.ts --jq '.content' | base64 -d         → full file (676 tokens)
gh api /repos/.../frameworks.ts --jq '.content' | base64 -d         → full file (624 tokens)

With ghx — 2 turns, 2 API calls, maps 10 files (3,058 tokens), sees signatures of all 10:

ghx read shadcn-ui/ui packages/shadcn/src/utils                     → directory listing (199 tokens)
ghx read shadcn-ui/ui "packages/shadcn/src/utils/*.ts" --map        → signatures of 10 files (2,859 tokens)

Same token budget. The gh agent read 3 full files; the ghx agent saw the structure of 10 — imports, exports, signatures — and knows which 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.

| Tool | Files per call | Matching context | Programmable | Dependencies | |------|---------------|-----------------|-------------|-------------| | GitHub MCP | 1 | No | No (~10K token schemas) | Go binary | | gh CLI | 1 | No | No (exact phrase, base64, no README) | gh | | ghx | 1-10 (batch) | Yes | Yes (codemode) | gh |

Commands

ghx --version                               # Health check / installed version (also: ghx version)
ghx explore <owner/repo>                    # Compact branch + tree + README orientation
ghx explore <owner/repo> --full             # Complete legacy explore output
ghx explore <owner/repo> <path>             # Compact subdirectory listing
ghx explore <owner/repo> --budget 20000     # Raise the compact output budget
ghx read <owner/repo> <f1> [f2] [f3]        # Read 1-10 files (large files map first)
ghx read <owner/repo> <dir>                 # Directory path → returns file listing
ghx read <owner/repo> "src/**/*.ts" --map   # Glob patterns with structural map
ghx read <owner/repo> --map <f1> [f2]       # Parser-backed structural map (~92% token reduction)
ghx read <owner/repo> --map --kind func <f> # Map only functions/methods
ghx read <owner/repo> --map --kind type <f> # Map only types/structs/interfaces
ghx read <owner/repo> --map --level minimal <f> # Symbol names only (e.g. UserService.GetUser)
ghx read <owner/repo> --grep "pat" <f>      # Matching lines only (ERE regex, 2 lines context)
ghx read <owner/repo> --lines 42-80 <f>     # Canonical line range
ghx read <owner/repo> <f> --full            # Force complete content past the budget
ghx search <owner/repo> "func main"         # Repo-first code search, auto-quotes the query
ghx search <owner/repo> "router" --lang go  # Narrow by language
ghx search <owner/repo> "router" --glob "**/*.go" # Narrow by path glob
ghx search "repo:gkoreli/ghx cobra.Command" # Advanced raw GitHub code-search query
ghx inspect <owner/repo> "routing middleware" # Concern-driven search + ranked files, maps, snippets
ghx grep <owner/repo> "func main"           # Grep-like repo search
ghx grep <owner/repo> "RunE" --path internal/cli --limit 10
ghx repos "<query>"                         # Repo search with README preview
ghx tree <owner/repo> [path]                # Full recursive tree
ghx tree <owner/repo> [path] --depth N      # Tree limited to N levels
ghx code "<js>"                             # Execute JS with access to all ghx tools
ghx code --list                             # List available tools with type stubs
ghx serve                                   # Start the direct-tools MCP server (stdio)
ghx serve --http :8080                      # Serve MCP over streamable HTTP
ghx serve --recon                           # Start the single-tool recon MCP service
ghx skill                                   # Print the classic CLI skill
ghx skill --mcp                             # Print the classic MCP skill
ghx skill --recon                           # Print the concise recon skill
ghx sidecar config init --claude-acp        # Write ~/.ghx/config.json for Claude ACP
ghx sidecar config show                     # Show resolved sidecar config
ghx sidecar doctor                          # Verify token, network, ghx binary, ACP, report sink
ghx sidecar doctor --live                   # Run a real one-prompt ACP turn for diagnosis
ghx sidecar ask --repo <owner/repo> "<q>"   # Delegate one repo question to the sidecar
ghx sidecar ask "<q>"                       # Discovery question across GitHub
ghx sidecar ask --repo <o/r> --local "<q>"  # Also allow tier-2 local analysis (codemap/ast-grep/repomap)
ghx sidecar daemon --status                 # Inspect the warm sidecar daemon
ghx sidecar daemon --stop                   # Stop the warm sidecar daemon
ghx sidecar sessions list                   # List persisted sidecar sessions
ghx sidecar sessions show <session>         # Metadata + report history
ghx sidecar sessions ledger <session>       # Accumulated evidence ledger JSON
ghx sidecar sessions reroute <s> <turn> <dest> # Move a mis-routed turn and rebuild ledgers
ghx sidecar tail [session] --follow         # Human-readable live view of turn activity (live.jsonl)
ghx sidecar view [session]                  # Local OTel viewer over session artifacts
ghx sidecar evals export --format sft --run <dir> --out <file> # Export committed eval episodes
ghx sidecar report-sink --out <path>        # Internal report-sink MCP server used by ACP turns
ghx tier2 codemap <owner/repo>              # Tier-2 cross-file structure as JSON (local snapshot)
ghx tier2 codemap <owner/repo> --context    # Agent-ready JSON context envelope (--compact to shrink)
ghx tier2 codemap <owner/repo> --importers <file>  # Who imports a file (fan-in; needs ast-grep)
ghx tier2 codemap <owner/repo> --deps       # Dependency flow / import chains (needs ast-grep)
ghx tier2 codemap <owner/repo> --ref v1.2.3 --sparse src  # Pin a ref, materialize only candidate paths
ghx tier2 astgrep <owner/repo> --pattern 'compose($$$A)' --lang ts  # Structural AST pattern search (JSON matches)
ghx tier2 astgrep <owner/repo> --pattern 'errors.Is($E, $T)' --lang go src  # Scope the search to paths
ghx tier2 repomap <owner/repo>              # Rank the files that matter (graph centrality, token budget)
ghx tier2 repomap <owner/repo> --query route --budget 512  # Bias ranking to the question, cap output tokens

read documents one range spelling, --lines START-END, but accepts hidden agent-guess aliases: --start N --end M and --offset N --limit M. They work for frictionless retries and stay out of help so examples converge on one form.

Output-heavy commands share --budget CHARS and --full: defaults are bounded, and truncation text names the exact flag to lift or narrow the result.

Exit codes are semantic: 0 ok, 1 no results, 2 bad invocation, 3 upstream/API failure.

tier2 commands are the deliberate, visible escalation beyond remote evidence (ADR-0024.1): the repo/ref is resolved to a commit SHA and materialized as a shallow, blobless, read-only snapshot cached by SHA under ~/.ghx/cache/tier2 ($GHX_HOME respected; 5 GiB budget, 30-day LRU/TTL eviction). Snapshot provenance — repo, ref, resolved SHA, clone strategy, cache hit — prints to stderr before any tool output, and structural tools run as absorbed backends under canonical IDs: local:codemap (subprocess, via codemap, MIT), local:ast-grep (subprocess, via ast-grep, MIT — also the binary codemap needs for --importers/--deps), and local:repomap (built in: the budgeted definition/reference/import-graph PageRank ranking stolen with attribution from aider's repo map, Apache-2.0 — an algorithm, not a dependency; deterministic given the same snapshot and query). Only local:repomap works with zero extra installs; codemap and ast-grep are optional external binaries, and ghx sidecar doctor reports which tier-2 backends resolve on your machine with install hints for the missing ones. If a tool binary is missing, ghx prints the install hint and exits before any clone; answers fall back to remote Tier-1 evidence — never a silent or faked Tier-2 result. astgrep follows grep parity: exit 1 with [] means the search ran and found nothing.

When the sidecar answers a question, escalation is never vibes: every turn gets a declarative policy evaluation (ADR-0024.2) over named observables (question shape, exhausted searches, low-confidence remote-only reports), recorded as a ghx.tier.decision span in traces.jsonl, a line in the session's tier-decisions.jsonl, and tierUsed provenance on the report — so "which tier answered and why" is always recomputable from the artifacts.

Codemode

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.

# What branch is this repo on?
ghx code 'var r = codemode.explore({repo: "vercel/next.js"}); return r.branch;'

# Search + read composition
ghx code 'var hits = codemode.search({query: "useState repo:vercel/next.js", limit: 3});
var first = codemode.read({repo: "vercel/next.js", files: [hits.matches[0].path]});
return {file: hits.matches[0].path, lines: first[0].content.split("\n").length};'

# See what tools and types are available
ghx code --list

Type stubs tell the LLM exactly what fields exist — no guessing:

declare const codemode: {
  explore: (input: ExploreInput) => { description: string; branch: string; files: { name: string; type: string }[]; readme: string };
  search: (input: SearchInput) => { total: number; incomplete: boolean; matches: { repo: string; path: string; fragment: string }[] };
  tree: (input: TreeInput) => string[];
  // ...
}

MCP server (direct tools)

ghx serve                                   # stdio (for Claude, Cursor, etc.)
ghx serve --http :8080                      # HTTP transport
ghx serve --recon                           # single-tool sidecar mode (see above)

Default mode exposes 7 tools: explore, read, search, repos, tree, code (meta-tool), search_tools.

{
  "mcpServers": {
    "ghx": {
      "command": "npx",
      "args": ["@gkoreli/ghx", "serve"]
    }
  }
}

No install step — npx downloads and caches the binary on first run.

Agent skills

ghx skill                                   # classic CLI skill (power-user path)
ghx skill --mcp                             # classic MCP skill
ghx skill --recon                           # concise recon skill (recommended for agents)
npx skills add gkoreli/ghx -g -a claude-code --skill ghx -y
npx skills add gkoreli/ghx -g -a claude-code --skill ghx-mcp -y

How it works

The classic CLI wraps gh 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 listing instead of "not found" (via ... on Tree inline fragments, zero extra API calls). Glob patterns (src/**/*.ts) auto-expand via tree fetch + doublestar matching in 2 API calls. --grep uses ERE regex with BRE normalization. search hits REST /search/code with text_matches for matching context.

--map runs a dedicated parser engine on the fetched content — no extra API calls. Engine selection is automatic: Go uses go/ast; TypeScript, JavaScript, Python, Rust use tree-sitter (via gotreesitter, capturing class/impl methods regex cannot reach); everything else falls back to regex. Codemode runs JS in a goja sandbox with esbuild TypeScript transpilation (max 20 tool calls, 64 KB code limit).

The sidecar wraps that same core behind an ACP agent that owns the exploration doctrine, validates its own evidence report before finishing (ADR-0021), and emits OTel artifacts to ~/.ghx/sessions/ (ADR-0022).

Architecture

cmd/ghx/             — binary entrypoint
internal/cli/        — CLI frontend (cobra) + MCP + sidecar commands
internal/ghx/        — core library (Explore, Read, Search, Repos, Tree, Glob)
internal/codemode/   — JS executor (goja sandbox, TS transpilation, type generation)
internal/mapengine/  — parser-backed map engine (GoAST, TreeSitter, Regex, routing)
internal/sidecar/    — sidecar runtime, sessions, report contract, ACP integration
internal/sidecar/telemetry/ — shared OTel emission (runtime + evals, one capability)
skills/              — CLI, MCP, and recon agent skills, embedded via go:embed

Core capabilities live in internal/ghx; every frontend — CLI, MCP, codemode, sidecar — wraps the same core. See docs/adr/ for the full decision record and docs/NORTH_STAR.md for direction.

Built on open source, openly

ghx exists because exploring open source for ideas is where good products come from — "good artists copy, great artists steal," and we steal in the Picasso sense: openly, with attribution, and with stewardship for future generations. The rule we build by: use official standards and existing open-source tools, libraries, and ideas first; hand-roll a framework or format only when nothing existing serves the need or the vision.

Where we do build new — ghx and the Agent Sidecar Framework — it is because the thing did not exist, and it is inspired loudly by what does. Tools like codemap and ast-grep shape the sidecar's internal toolbox: ghx tier2 codemap and ghx tier2 astgrep absorb them as internal subprocess backends (local:codemap, local:ast-grep, ADR-0024.1) rather than competing on CLI surface (see ADR-0026), and ghx tier2 repomap steals the budgeted graph-ranking algorithm behind aider's repo map without the dependency. MIT in, MIT out.

How it was built

23 agent sessions, 2,500+ conversation turns, 3 rewrites, and a growing ADR record. The origin story: Build the GitHub Exploration Tool, No Mistakes

License

MIT