Skip to content

cli: add code search via peregrine (ENT-993, ENT-994)#1615

Closed
evisdren wants to merge 2 commits into
mainfrom
evis/ent-990-cross-region-code-search-cli-peregrine-us-first-then-eu
Closed

cli: add code search via peregrine (ENT-993, ENT-994)#1615
evisdren wants to merge 2 commits into
mainfrom
evis/ent-990-cross-region-code-search-cli-peregrine-us-first-then-eu

Conversation

@evisdren

@evisdren evisdren commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

https://entire.io/gh/entireio/cli/trails/739

Summary

  • Adds entire search --code <query> to search code content through peregrine via entire-api cells
  • New codesearch package with client for peregrine's /search/api/search endpoint
  • Gated behind ENTIRE_CODE_SEARCH=1 — returns a clear error otherwise, keeping it dark until launch
  • Auth via NewEntireAPICellClient (jurisdictional identity tokens), same pattern as entire api --to cell

Details

  • Output modes: grep-style repo:path:line: context (terminal) or structured JSON (--json / piped)
  • Flags: --code, --case-sensitive, --repo, --limit — incompatible flags (--page, --all-repos, --case-sensitive without --code) are rejected with clear errors
  • Response overflow detection: 8 MiB cap with explicit error instead of silent truncation
  • Timeout: 30s scoped to the search POST only, not auth resolution
  • V1 scope: Single-region (home cell). Multi-region fan-out is ENT-995 (future)

Linear tickets

  • ENT-993: CLI code search client package
  • ENT-994: Wire code search into search command UX
  • Parent: ENT-990: Cross-Region Code Search

Test plan

  • Unit tests for codesearch.Search() (success, API error, non-JSON error, response overflow)
  • Unit tests for env gate (ENTIRE_CODE_SEARCH on/off/falsy values)
  • Unit tests for flag validation (--code without gate, without query, --case-sensitive without --code, --all-repos with --code, --page with --code)
  • Unit tests for text and JSON output rendering (including empty results)
  • mise run check passes (fmt + lint + all tests)

🤖 Generated with Claude Code


Note

Medium Risk
Adds authenticated calls to a new cell API surface with jurisdictional routing; impact is limited by the ENTIRE_CODE_SEARCH=1 preview gate and bounded response handling.

Overview
Adds preview code content search to the hidden entire search command via --code, calling peregrine through entire-api at POST /search/api/search. A new codesearch package defines request/response types and Search(), including an 8 MiB response cap and structured api.HTTPError handling on failures.

The --code path is gated on ENTIRE_CODE_SEARCH=1; otherwise users get a clear “not yet available” error. It authenticates with NewEntireAPICellClient, applies a 30s timeout only around the search POST, and supports --repo / inline repo: (with repo:* / --all-repos treated as no repo filter), --limit, and --case-sensitive (rejected unless --code). Results render as grep-style repo:path:line: on a TTY or JSON when --json or stdout is piped.

Unit tests cover the client (success, API/non-JSON errors, oversized body), env gating, flag validation, and text/JSON output.

Reviewed by Cursor Bugbot for commit 55ceb6e. Configure here.

Add `entire search --code <query>` to search code content through
peregrine via entire-api cells. Gated behind ENTIRE_CODE_SEARCH=1
env var so it stays dark until launch.

- New `codesearch` package: client for peregrine's /search/api/search
  endpoint with request/response types matching the peregrine API
- Auth via NewEntireAPICellClient (jurisdictional identity tokens),
  same pattern as `entire api --to cell`
- Output modes: grep-style text (terminal) or JSON (--json / piped)
- Flags: --code, --case-sensitive, --repo, --limit
- Rejects incompatible flags (--page, --all-repos, --case-sensitive
  without --code) with clear error messages
- Response overflow detection (8 MiB cap with explicit error)
- Timeout scoped to the search call only (30s), not auth resolution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@evisdren evisdren requested a review from a team as a code owner July 2, 2026 19:58
Copilot AI review requested due to automatic review settings July 2, 2026 19:58
Comment thread cmd/entire/cli/search_cmd.go Outdated
Comment thread cmd/entire/cli/search_cmd.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an env-gated (ENTIRE_CODE_SEARCH=1) code-content search mode to the existing entire search command, backed by a new codesearch client that calls peregrine via the authenticated entire-api cell.

Changes:

  • Adds entire search --code <query> with --case-sensitive, --repo, and --limit, plus validation to reject incompatible checkpoint-search flags.
  • Introduces cmd/entire/cli/codesearch package to POST to /search/api/search with an 8 MiB response cap and typed request/response structs.
  • Adds unit tests covering the env gate, flag validation, output rendering, and codesearch.Search() behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
cmd/entire/cli/search_cmd.go Wires --code path into entire search, including env gate, flag validation, request mapping, and text/JSON rendering.
cmd/entire/cli/search_cmd_test.go Adds tests for env gating, flag incompatibilities, and output helpers for the new code-search mode.
cmd/entire/cli/codesearch/codesearch.go Implements peregrine code search client with response size limiting and error handling.
cmd/entire/cli/codesearch/codesearch_test.go Adds unit tests for success/error/oversize response handling in the codesearch client.

Comment on lines +330 to +345
if opts.repoFilter != "" {
if err := search.ValidateRepoFilters([]string{opts.repoFilter}); err != nil {
return fmt.Errorf("validating repo filter: %w", err)
}
}

req := codesearch.SearchRequest{
Query: opts.query,
CaseSensitive: opts.caseSensitive,
}
if opts.limit > 0 {
req.MaxResults = opts.limit
}
if opts.repoFilter != "" {
req.Repos = []string{opts.repoFilter}
}
Comment thread cmd/entire/cli/search_cmd.go Outdated
cmd.Flags().BoolVar(&jsonOutput, "json", false, "Output as JSON")
cmd.Flags().BoolVar(&codeFlag, "code", false, "Search code content via peregrine (requires ENTIRE_CODE_SEARCH=1)")
cmd.Flags().BoolVar(&caseSensitive, "case-sensitive", false, "Case-sensitive code search (only with --code)")
cmd.Flags().IntVar(&limitFlag, "limit", resultsPerPage, "Maximum number of results per page")
Comment thread cmd/entire/cli/codesearch/codesearch.go Outdated
Comment on lines +77 to +84
if resp.StatusCode != http.StatusOK {
var errResp struct {
Error string `json:"error"`
}
if json.Unmarshal(body, &errResp) == nil && errResp.Error != "" {
return nil, fmt.Errorf("code search error (%d): %s", resp.StatusCode, errResp.Error)
}
return nil, fmt.Errorf("code search returned %d: %s", resp.StatusCode, string(body))
- Parse inline repo: filters for --code path (was passing them as
  literal query text to peregrine)
- Handle repo:* and --all-repos with --code as "no filter" instead
  of passing literal "*" to the API
- Use api.ErrorResponse/HTTPError for error parsing instead of
  inline struct (supports both legacy and newer error envelopes)
- Fix --limit help text to clarify behavior differs for --code
- Drop --page/--all-repos rejection (silently ignored is less
  disruptive than breaking shared scripts)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@evisdren

evisdren commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 55ceb6e. Configure here.

caseSensitive: caseSensitive,
jsonOutput: jsonOutput,
insecureHTTP: insecureHTTPAuth,
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Page flag ignored for code

Medium Severity

The --code branch returns before checkpoint search runs and never checks --page, so entire search --code --page 2 … still returns the first result set with no error. Code search has no pagination, so the flag should be rejected like --case-sensitive without --code.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 55ceb6e. Configure here.

codeRepo := repoFlag
if codeRepo == "" && len(parsed.Repos) > 0 {
codeRepo = parsed.Repos[0]
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple repo filters silently ignored

Medium Severity

For --code, inline repo: filters are parsed into parsed.Repos, but only parsed.Repos[0] is used and search.ValidateRepoFilters is never run on the full list. Queries like repo:a/b repo:c/d term or repo:a/b,c/d term search one repo without the error checkpoint search returns for multiple repo filters.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 55ceb6e. Configure here.

@evisdren

evisdren commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #1616 (client package) and #1617 (command wiring) — split into two PRs per request.

@evisdren evisdren closed this Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants