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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ broader open-source ecosystem, not just model memory or local repo context:
| Code navigation | `search`, `search_status`, `code_files`, `code_grep` | `githits search`, `githits search-status`, `githits code ...` |
| Documentation discovery | `docs_list` | `githits docs list` |
| Read source files or documentation sections | `read` | `githits read <target> [path]` |
| Grep source and hosted documentation together | CLI only (MCP migration pending) | `githits grep <pattern> <targets...>` |
| Package inspection | `pkg_info`, `pkg_vulns`, `pkg_deps`, `pkg_changelog`, `pkg_upgrade_review` | `githits pkg ...` |

Use GitHits when your agent needs to:
Expand Down
6 changes: 6 additions & 0 deletions changes/unified-grep-cli.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"githits": minor
"@githits/mcp": none
---

- **Unified grep CLI** - Add `githits grep` across ordered package, repository and hosted documentation targets, defaulting to regex, case-sensitive matching and zero context, with `-F`, `-i`, rg-style `-s`, exact read actions and explicit partial coverage, including retained unvisited scopes and cursor continuation. Legacy CLI `code grep` and MCP `code_grep` remain available pending the MCP migration.
3 changes: 2 additions & 1 deletion docs/implementation/cli-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Purpose

The CLI exposes setup/auth commands, `doctor`, `example`, top-level indexed `search` / `search-status`, `read`, `list`, and the `code`, `docs`, and `pkg` command groups by default. `resolve` and `code diff` are experimental, host-config-gated commands. MCP-parity commands share business logic with the MCP tools through the same service interfaces and shared utilities. Unified search shares its presentation model and text formatter with MCP; `list` uses the shared request, result, error, and path-only text helpers, while MCP tool registration remains a later increment.
The CLI exposes setup/auth commands, `doctor`, `example`, top-level indexed `search` / `search-status`, `read`, `list`, `grep`, and the `code`, `docs`, and `pkg` command groups by default. `resolve` and `code diff` are experimental, host-config-gated commands. MCP-parity commands share business logic with the MCP tools through the same service interfaces and shared utilities. Unified search shares its presentation model and text formatter with MCP; `list` uses the shared request, result, error, and path-only text helpers, while MCP tool registration remains a later increment.

## Experimental CLI commands

Expand Down Expand Up @@ -58,6 +58,7 @@ envelope when `--json` is requested; terminal output remains human-readable.
| `pkg upgrade-review [spec]` | single package spec with current version plus `--to`, positional package range, OR repeatable `--package` ranges | `--to`, repeatable `--package`, `--no-transitive-security`, `--dependency-issues`, `--min-severity`, `--verbose`, `--json` | Compare current and target versions for upgrade evidence: vulnerabilities, changelog entries, deprecation metadata, peer changes, dependency changes, and transitive security evidence by default. Reports facts only. |
| `docs list <spec>` *(legacy compatibility)* | package spec (optional `@version`) | `--limit`, `--after`, `--verbose`, `--json` | Help points hosted-site browsing to `githits list site:<host[/path]>` and package-local docs to the package target. Existing execution remains unchanged: text emits target-based read commands; JSON retains `docsReadTarget`, stable `pageId`, provenance `sourceUrl`, and exact repo-file metadata when available. |
| `list <target> [paths...]` | package, repository, or `site:<host[/path]>` target; optional literal paths/globs | `-R, --recursive`, `-s, --silent`, repeatable `--file-type`, `--language`, `--intent`, `--limit`, `--after`, `--wait`, `--json` | List one package/repository source inventory, including package-local documentation files, or one explicitly targeted hosted site. Text is one path per line with `/` on directories; the header reuses backend-authored read targets for follow-up, while `--silent` emits only paths for piping. JSON carries exact actions, cursors, and metadata. |
| `grep <pattern> <targets...>` | ordered package, repository and `site:` operands | `-F/--fixed-strings`, `-i/--ignore-case`, `-s/--case-sensitive`, `-A`, `-B`, `-C`, repeatable `--path`, `--path-prefix`, `--glob`, `--corpus`, `--limit`, `--cursor`, `--wait`, `--json` | Regex, case-sensitive and zero-context defaults; all repository files plus independently selected hosted package docs. Global page cap, exact reads and explicit coverage; unvisited scopes remain visible and use the same cursor continuation. See [unified grep](unified-grep.md). Legacy `code grep` remains unchanged. |
| `read <target> [path]` | docs target/page ID, explicit `site:` target with page path, compact `target#symbol`, or package/repo target with exact path or selector | `--selector`, `--lines`, `--start`, `--end`, `--wait`, `--verbose`, `--json`; `--repo-url` and `--git-ref` retain legacy repo addressing | Compact unified read passes the locator unchanged to the backend and presents the returned code, docs, or symbol-resolution type. A `site:` path selects hosted documentation; other exact paths narrow code selection. `--selector` selects a docs heading or indexed code symbol. HTTP(S) URL fragments and emitted repository docs page IDs retain their backend-resolved documentation behavior. The compact path calls `ReadService`/`Query.read` once. `--repo-url` remains the legacy compatibility path without selector. See [unified read](unified-read.md). |
| `docs read <target>` (deprecated alias) | emitted `docsReadTarget` or historical page ID | `--lines`, `--verbose`, `--json` | Read a documentation page by preferred target or compatible page ID. Default output is content-only; `--lines` fetches a bounded range for long pages. |
| `code diff <target> <from>..<to>` *(experimental; config-gated)* | unversioned package/repository target and exact range, or `--repo-url` and range | `--patch`, `--stat`, `--name-only`, `--name-status`, `--max-files`, `--max-patch-bytes`, `--verbose`, `--json`, one glob after `--` | Silently dogfood bounded repository-wide tree diffs resolved from package versions or repository refs; local-only MCP `code_diff` is available when experimental tools are enabled, while public/remote MCP and shared Agent Skill guidance remain unchanged |
Expand Down
2 changes: 1 addition & 1 deletion docs/implementation/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The container (`src/container.ts`) resolves authentication in priority order:
| `/search` | Full access | Full access | Blocked |
| `/functions/v1/settings/me` | Full access | Full access | Blocked |

Package/source access uses the OSS service URL selected by `GITHITS_ENV` unless `GITHITS_CODE_NAV_URL` overrides it. MCP registration for `search`, `search_status`, `docs_*`, `pkg_*`, `code_files`, `read`, and `code_grep` is always on; CLI registration for top-level `search` / `search-status` / `read` / `list` plus the `githits code`, `githits pkg`, and `githits docs` groups is also always on.
Package/source access uses the OSS service URL selected by `GITHITS_ENV` unless `GITHITS_CODE_NAV_URL` overrides it. MCP registration for `search`, `search_status`, `docs_*`, `pkg_*`, `code_files`, `read`, and `code_grep` is always on; CLI registration for top-level `search` / `search-status` / `read` / `list` / `grep` plus the `githits code`, `githits pkg`, and `githits docs` groups is also always on.

## Environment Variables

Expand Down
112 changes: 112 additions & 0 deletions docs/implementation/unified-grep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Unified grep

`githits grep <pattern> <targets...>` searches ordered package, repository and
`site:<host[/path]>` operands through `Query.grep`. MCP still exposes `code_grep`;
replacing it is Phase 2. Legacy `githits code grep` keeps its existing behavior.

```sh
githits grep 'router' npm:express --path lib/express.js
githits grep -Fi 'router' npm:express site:expressjs.com
githits grep 'router' npm:express site:expressjs.com --json
githits grep -F -- '--foo' github:example/repository
```

## Matching and scope

The client explicitly sends RE2 regex mode, case-sensitive matching, zero
context on each side and `ALL` repository corpus. Backend defaults differ.
`-F/--fixed-strings` opts into literal matching; `-i/--ignore-case` uses backend
Unicode folding. `-s/--case-sensitive` follows rg; traditional grep uses `-s`
to suppress errors. The last case flag wins, including short flag clusters.
RE2 and backend anchoring restrictions apply. Invalid or unsupported regexes
fail without a literal retry.

`-A/--after-context`, `-B/--before-context` and `-C/--context` accept 0–10.
An explicit side overrides `-C` regardless of order. Every supplied value is
validated without clamping. `--limit` caps the entire page (1–1,000, backend
default 100), unlike grep/rg's per-file `-m`. `--wait` accepts 0–300,000 ms.
Empty cursors start page one; nonblank cursors remain opaque and unchanged.

Repeatable `--path`, `--path-prefix` and `--glob` selectors are OR-ed within
each source operand. `--corpus source|documentation|all` controls repository
files. Global CLI source controls apply uniformly to source operands. Sites
receive only their target; source flags with only site operands fail.
Packages can also expand to selected hosted docs independently of repository
corpus and paths. `--corpus source` therefore does not exclude hosted docs.

The backend owns resolution, expansion/deduplication, package boundaries, site
authority, selector matching and continuation. The client accepts 1–20 caller
targets and up to 1,000 selectors per source target. It sends `allowUnscoped:
true` for sources without weakening explicit selectors. Native expanded limits
remain eight repositories and eight sites.

## Ownership and selection

Core `services/grep-service.ts` owns transport-neutral types, the query,
allowlisting/validation and typed failures, reusing shared HTTP, headers,
diagnostics and token refresh. Root composition owns configuration discovery.
MCP `shared/grep-{request,response,error-map,text}.ts` owns frontend normalization,
projection, failure classification and presentation. Projection reuses the
core wire schema rather than maintaining another allowlist. The root command
owns Commander syntax, auth gating, spinners, diagnostics and exits. Shared
helpers remain workspace-internal in Phase 1; no public MCP tool/service is added.

Compact text selects complete line/context slices, exact reads, scope
provenance/statuses, scan/skip counts, issue summaries, omissions, page count,
traversal and cursor. JSON additionally selects duplicate `lineContent`, hit
repository identities, display/physical byte coordinates, safety modifications,
issue byte details and full scope identities. Those fields use conditional
`@include(if: $includeDetailedFields)` selections. Missing selected fields or
unknown hit branches fail. Selected nulls stay null; excluded details stay
absent. JSON keeps camelCase fields without `hasMore` or an invented global total.

## Results and recovery

`totalMatches` counts this page. Physical scope `targetIndex` differs from
caller attribution in `requestedInputIndices`; producer order is retained.
Only consecutive compatible hits group together. Overlapping context merges,
match/context lines are numbered, and omitted line bytes are marked. Prose
wraps to caller width; source and executable actions remain intact. Terminal
controls and locator backslashes are escaped; backend Unicode is preserved.

Read actions are backend-authored. Display paths can be package-relative while
read paths are repository-root paths at an exact commit. Hosted actions use
persisted URLs and read latest active content, which can change after search.
The client never hydrates hits or guesses paths.

`UNSPECIFIED` readiness means this page stopped before visiting that scope.
The scope stays in `targets`, retains its input attribution, and reports
`RESUMABLE_LIMIT` traversal. Continue with `nextCursor` and identical ordered
operands/controls to inspect it. Readiness has not yet been observed; this
status does not indicate target failure or unavailable content. Text explains
the unvisited scope, while JSON preserves the backend enum and full status.

Stale/failed scopes, skips, issues, omitted issue counts, safety normalization
and unavailable targets stay visible on zero-hit pages. `No matches.` is
exhaustive only for complete traversal without coverage gaps. Other empty
pages report incomplete coverage. Cursors and terminal omissions can coexist;
both are shown. Continue with identical ordered operands and controls.
`CURSOR_EXPIRED` is a successful result requiring explicit restart; retained
sibling hits and omissions remain visible.

Complete/partial pages exit zero, including zero hits. Failures exit nonzero;
JSON errors go to stderr with clean stdout. Preparation errors map to `INDEXING`
and preserve up to 20 public `targetIssues` with backend keys and per-input
recovery data. Retryable preparation errors include CLI `--wait <ms>` recovery
guidance. Invalid cursors map to `INVALID_ARGUMENT` with distinct
`graphqlCode`. Protocol, transport, auth, terms, update, deadline and HTTP
failures retain mapped categories. There is no legacy fallback or automatic
preparation retry/cursor restart.

Focused tests cover query variables/selections, union validation, ordered
mixed hits, exact reads, coverage, context precedence, case flags, errors and
refresh. CLI smoke covers registration, unauthenticated errors and source
grep. Fresh mixed-site, pagination, read replay, case and corpus conformance
is checked against dev before Phase 1 signoff.

Dev and production support package/mixed `--limit 1` pages, including retained
unvisited scopes. Production client replay on 2026-09-29 verified the exact
source repro, mixed two-page CLI continuation and compact/detailed service
pages: both scopes and input attribution are retained, with a source hit on
page one and a hosted-doc hit on page two. Unknown readiness values and other
malformed output still fail validation.
Loading
Loading