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
13 changes: 5 additions & 8 deletions .claude/rules/code-search.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
---
paths:
- 'app/**/*.ts'
- 'app/**/*.tsx'
- 'test/**/*.ts'
- 'test/**/*.tsx'
- '**/*.{ts,tsx,js,jsx,mjs,cjs,py,go,rs,java,rb,php,cs,cpp,cc,c,h,hpp,kt,swift,scala}'
---

# Code Search

For symbol-level queries on TS/TSX files, prefer [Serena](https://github.com/oraios/serena)'s MCP tools over Read+grep. Serena is LSP-backed, canonical, type-resolved answers vs string matches.
For symbol-level queries on code, prefer [Serena](https://github.com/oraios/serena)'s MCP tools over Read+grep, in any language Serena indexes for this project (TypeScript and any other language server the project configures). Serena is LSP-backed, canonical, type-resolved answers vs string matches.

## Prefer Serena

"Where is `X` defined?", "Find references to `X`", "What's the type of `X`?", "What calls `X` / what does `X` call?", "Show me everything in module `Y`."

## Grep is still right

Prose / comments / string literals, files outside `app/**` and `test/**`, generated / gitignored files (not indexed), cross-language searches.
Prose / comments / string literals, non-code files, files in a language Serena isn't indexing for this project, generated / gitignored files (not indexed), cross-language searches.

## Enforcement

A PreToolUse guard (`.claude/hooks/serena-code-search-guard.sh`) catches a bare-identifier symbol search on either search path and points it at Serena's symbol tools. Through the `Grep` tool it blocks a pattern that is a bare identifier (>= 3 chars, no spaces or regex metacharacters) scoped to `app/**` or `test/**` TS/TSX. Through `Bash` it blocks a single `grep`/`rg`/`ag` whose lone pattern is such an identifier and which carries an explicit `app/**` or `test/**` TS/TSX path. The Bash path favors false negatives: a pipeline, a compound or sequenced command, a command substitution, a redirection, a quoted or multi-word or regex pattern, multiple patterns, or any search not explicitly scoped to app/test source passes through, so legitimate shell work is never blocked. Re-running the identical search passes, for the rare string-literal or comment search that is identifier-shaped. The guard no-ops unless Serena is a registered MCP server and the repo has a `tsconfig.json`, so adopters without Serena are unaffected.
The routing guidance above is language-agnostic: it nudges toward Serena's symbol tools for any language Serena indexes for this project. The enforcement guard is deliberately narrower and stays TypeScript-conservative, so a wrong block on a non-TS search can't happen. A PreToolUse guard (`.claude/hooks/serena-code-search-guard.sh`) catches a bare-identifier symbol search on either search path and points it at Serena's symbol tools. Through the `Grep` tool it blocks a pattern that is a bare identifier (>= 3 chars, no spaces or regex metacharacters) scoped to `app/**` or `test/**` TS/TSX. Through `Bash` it blocks a single `grep`/`rg`/`ag` whose lone pattern is such an identifier and which carries an explicit `app/**` or `test/**` TS/TSX path. The Bash path favors false negatives: a pipeline, a compound or sequenced command, a command substitution, a redirection, a quoted or multi-word or regex pattern, multiple patterns, or any search not explicitly scoped to app/test source passes through, so legitimate shell work is never blocked. Re-running the identical search passes, for the rare string-literal or comment search that is identifier-shaped. The guard no-ops unless Serena is a registered MCP server and the repo has a `tsconfig.json`, so adopters without Serena are unaffected.

## Limits

Cold-start tsserver warm-up. Files outside `tsconfig` `include` invisible. Generated files not indexed.
Cold-start language-server warm-up. Files the language server doesn't index (outside its project config) are invisible. Generated files not indexed.

## Reference

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ A release change that requires the adopter to act, run a command or hand-migrate

### Changed

- GAIA's Serena code-search routing guidance is now language-agnostic: the advisory `code-search` rule nudges toward Serena's LSP-backed symbol tools for symbol queries in any language Serena indexes for the project (not only TypeScript, and no longer scoped to `app/`/`test/`), so an adopter who configures another language server gets the same routing. The enforcement guard stays deliberately TypeScript-conservative and tsconfig-gated, since a wrong hard-block on a non-TS search is worse than a miss while the rule only nudges (#533)
- `/gaia-debt` drives its fix PR through the standard PR Merge Workflow to completion instead of stopping after `gh pr create` for a human to merge by hand: it confirms intent (open-only or merge, defaulting to merge), then resolves the marker handshake, the maintainer-only CHANGELOG gate, the merge (`--auto` under branch protection, never `--admin`), and the post-merge verify-and-cleanup itself. The `code-review-audit` marker gate is unchanged, the skill drives the merge and never bypasses, fakes, or pre-empts it (#523)
- `gaia setup finalize` refuses to stamp per-machine setup complete while the mentorship decision artifact `.gaia/local/mentorship.json` is absent, and that refusal holds even under `--force`, so the completion marker can no longer claim success when the opt-in decision was never persisted. It emits a structured error whose `code` is `mentorship_decision_missing`, and `/gaia-init` Step 12 self-heals on that code by re-applying the safe default and retrying finalize once, so an automated init that dropped the opt-in still completes without human input. The gate keys on file existence only, leaving `/setup-gaia`'s recovery net the owner of upgrading a lingering `enabled:null` decision (#520)
- `/gaia-spec`'s closing handoff now prints a single copy-pasteable block: the `/gaia-plan` command and its SPEC argument together, prefaced by a `/clear`-and-paste instruction, instead of a bare argument the user had to prefix with the command by hand (#519)
Expand Down
4 changes: 2 additions & 2 deletions wiki/concepts/Serena Integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
type: concept
status: active
created: 2026-05-04
updated: 2026-07-02
updated: 2026-07-03
tags: [concept, claude, code-search, mcp]
---

Expand Down Expand Up @@ -36,7 +36,7 @@ See `.claude/rules/code-search.md` for the routing rule.

## Enforcement

The rule alone is path-scoped to `app/**`/`test/**` *edits*, so it's absent from context during exploration, exactly when the grep-vs-Serena decision gets made. A PreToolUse guard (`.claude/hooks/serena-code-search-guard.sh`) closes that gap. It fires at the search call itself on both the `Grep` tool and a single `grep`/`rg`/`ag` issued through `Bash`, and blocks a bare identifier (≥ 3 chars, no spaces or regex metacharacters) scoped to `app/**`/`test/**` TS/TSX, pointing it at `find_symbol` / `find_referencing_symbols` / `get_symbols_overview`. The Bash path stays conservative and favors false negatives: a pipeline, a compound or sequenced command, a command substitution, a redirection, a quoted or regex pattern, multiple patterns, or any grep not carrying an explicit `app/**`/`test/**` TS/TSX path passes through untouched, so ordinary shell work is never blocked. Re-running the identical search passes, for the rare string-literal or comment search that's identifier-shaped. It no-ops unless Serena is a registered MCP server and the repo has a `tsconfig.json`, so adopters without Serena never see it. See [[Claude Hooks]].
The routing rule is advisory and language-agnostic: it activates on a broad multi-language source glob and prefers Serena's symbol tools for any language Serena indexes for the project, not TypeScript or `app/`/`test/` alone. A rule is still absent from context during pure exploration (no edit in flight), exactly when the grep-vs-Serena decision gets made, so a PreToolUse guard (`.claude/hooks/serena-code-search-guard.sh`) closes that gap. The guard is deliberately narrower than the rule: it stays TypeScript-conservative and tsconfig-gated, so a hard block never lands on a non-TS search. It fires at the search call itself on both the `Grep` tool and a single `grep`/`rg`/`ag` issued through `Bash`, and blocks a bare identifier (≥ 3 chars, no spaces or regex metacharacters) scoped to `app/**`/`test/**` TS/TSX, pointing it at `find_symbol` / `find_referencing_symbols` / `get_symbols_overview`. The Bash path stays conservative and favors false negatives: a pipeline, a compound or sequenced command, a command substitution, a redirection, a quoted or regex pattern, multiple patterns, or any grep not carrying an explicit `app/**`/`test/**` TS/TSX path passes through untouched, so ordinary shell work is never blocked. Re-running the identical search passes, for the rare string-literal or comment search that's identifier-shaped. It no-ops unless Serena is a registered MCP server and the repo has a `tsconfig.json`, so adopters without Serena never see it. The split is deliberate: the advisory rule nudges broadly across languages at zero false-block risk, while the guard blocks only where a wrong block is impossible. See [[Claude Hooks]].

## Quirks

Expand Down
10 changes: 6 additions & 4 deletions wiki/dependencies/Serena.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ tags: [dependency, mcp, code-search]

# Serena

LSP-backed MCP server. Gives Claude live, always-fresh access to symbol definitions, references, types, and module structure across the project's TS/TSX files.
LSP-backed MCP server. Gives Claude live, always-fresh access to symbol definitions, references, types, and module structure across the project's source files, in any language the project configures a language server for.

## Pin

Expand All @@ -28,18 +28,20 @@ The `claude-code` context exposes Serena's LSP-backed symbol tools and its memor

## When to use

Symbol-level queries on TS/TSX:
Symbol-level queries in any language Serena indexes for the project:

- Definitions: "where is `X`?"
- References: "what calls `Y`?"
- Types: "what's the type of `Z`?"

For prose / string / cross-language search, fall back to Read+grep. Routing rule: `.claude/rules/code-search.md`.

The advisory routing rule is language-agnostic: it activates on a broad multi-language source glob and nudges toward Serena's symbol tools for any language Serena indexes, not TypeScript or `app/`/`test/` alone. The enforcement guard (`.claude/hooks/serena-code-search-guard.sh`) is deliberately narrower, TypeScript-conservative and tsconfig-gated, so a hard block never lands on a non-TS search. See [[Serena Integration]] for the guard detail.

## Limits

- Cold-start cost on first invocation per session (tsserver warm-up).
- Indexes only files reachable from `tsconfig.json`.
- Cold-start cost on first invocation per session (language-server warm-up).
- Indexes only files reachable from the language server's project config (`tsconfig.json` for TypeScript).
- Doesn't see gitignored or generated files.

See [[Serena Integration]].