# Search CLI vs UI Audit — Differences Found

### 1. **Types requested: CLI only searches `checkpoints`, UI searches everything**

**CLI** (`search.go:255`): Hardcodes `types=checkpoints` in the query string:
```go
q.Set("types", "checkpoints")
```

**UI** (`api.ts:10`): Passes `types` from params, which defaults to all types (checkpoints, commits, sessions, repos, prs). The search page doesn't pass `types` at all in `useGlobalSearchQuery`, so the API defaults to `[
"repos",
"checkpoints",
"commits",
"prs",
"sessions"
]`.

**Impact**: The CLI only ever gets checkpoint results. The UI gets checkpoints, commits, sessions, PRs, and repos — then filters client-side by type tabs. This means the same query will return different results and different totals.

### 2. **Search mode: CLI uses hybrid (default), UI uses hybrid (default) — same**

Both omit the `mode` parameter, so the server defaults to hybrid. This is consistent.

### 3. **Limit: CLI requests 200, UI requests 100**

**CLI** (`search_cmd.go:156`): Always overrides limit to `MaxLimit = 200` before calling the API.

**UI** (`search.tsx:138`): Passes `limit: 100`.

**Impact**: CLI fetches up to 200 results, UI fetches up to 100. This can cause different result ordering because the server's tier pipeline and Cohere reranking operates on different sized result sets.

### 4. **Missing parameters: CLI doesn't send `mode` or `filter_type`**

**UI** (`api.ts:17-18`): Can send `mode` and `filter_type` params.

**CLI** (`search.go`): Never sends `mode` or `filter_type`. The `Config` struct has no fields for these.

**Impact**: The UI's type-tab filtering (`filterType`) happens server-side before pagination, so the UI gets correctly paginated type-filtered results. The CLI gets everything mixed together (checkpoints only due to issue #1, but still).

### 5. **Response fields: CLI drops several fields from the response**

**CLI** (`search.go:30-65`): The `CheckpointResult` struct is missing:
- `commitSubject` — present in API response, not in CLI struct
- `summary` — present in `SearchMeta` on the API side

The CLI `Meta` struct (`search.go:31-35`) has `matchType`, `score`, and `snippet` but is missing:
- `tier`
- `matchedFields`
- `bm25Score`, `annScore`, `bm25Rank`, `annRank`

The CLI `Response` struct (`search.go:60-65`) is missing:
- `timing`
- `reranked`
- `counts`

**Impact**: The CLI can't display type counts, timing info, or use tier/ranking data for display. The missing `commitSubject` means the CLI shows raw commit messages where the UI shows parsed subjects.

### 6. **Repo scoping: CLI auto-scopes to current repo, UI doesn't scope by default**

**CLI** (`search_cmd.go:99-101`): Parses the git remote to get `owner/repo` and always sends it as the `repo` param (unless `repo:*` is used).

**UI** (`search.tsx:101-105`): Only sends `repo` if the user explicitly selects a repo filter.

**Impact**: CLI searches within the current repo only. UI searches across all accessible repos. This is probably the **biggest source of result differences** — the same query in the CLI is repo-scoped while the UI is org-wide.

### 7. **Client-side type filtering: UI hides repos and PRs, CLI only gets checkpoints**

**UI** (`search.tsx:35`): `HIDDEN_SEARCH_RESULT_TYPES = new Set(["repo", "pr"])` — filters out repo and PR results from display, then further filters by the selected type tab.

**CLI**: Only requests checkpoints so this isn't relevant, but it means commits and sessions are never shown.

---

## Summary of Root Causes for Result Differences

| Issue                | CLI                                                | UI                                         | Impact                                                          |
|----------------------|---------------------------------------------------|-------------------------------------------|-----------------------------------------------------------------|
| **Repo scoping**     | Always scoped to current repo                     | All repos by default                      | Biggest difference — CLI misses cross-repo results               |
| **Types filter**     | `types=checkpoints` only                          | All types (checkpoints, commits, sessions, prs, repos)         | CLI misses commits, sessions                                     |
| **Result limit**     | 200                                               | 100                                       | Different reranking due to different candidate pool sizes         |
| **Missing response fields** | No `commitSubject`, `tier`, `counts`, `timing` | Full response                             | Display differences, missing commit subjects                      |

### Recommended Fixes

1. **Remove `types=checkpoints` hardcoding** — let the CLI request all types like the UI does, and filter client-side or add a `--type` flag
2. **Add a `--all-repos` or make repo scoping opt-in** — or at minimum document that CLI is repo-scoped while UI is not
3. **Align the limit** — use the same default (100) or make it configurable
4. **Update the CLI `CheckpointResult` struct** to include `commitSubject` and update `Meta`/`Response` to match the full API response shape
