From baz
Procedure for exploring repositories with Baz's indexed search tools. Use when asked to plan a feature, design a change, scope work, or investigate where to make changes across the org's repos. Applies even when you own one side of a cross-repo contract (API param, schema, event payload) locally, and especially when the relevant repositories are not checked out locally. Baz's MCP tools are how you search code across the org; once you know a file's path, read it however you like.
How this skill is triggered — by the user, by Claude, or both
Slash command
/baz:baz-codebase-explorationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill helps you plan a change across your org's repos using indexed search. It applies whether or not the relevant repos are checked out locally — and **especially when a change crosses a contract boundary between repos**: you edit one side, another repo defines the other. **Baz MCP tools are how you search code across the org.** Once you know a file's path, read it however you like — loca...
This skill helps you plan a change across your org's repos using indexed search. It applies whether or not the relevant repos are checked out locally — and especially when a change crosses a contract boundary between repos: you edit one side, another repo defines the other. Baz MCP tools are how you search code across the org. Once you know a file's path, read it however you like — local Read if the repo is checked out, otherwise your own fetch.
| Job | Tool |
|---|---|
| Find which repos are involved | repo_search (Baz) |
| Find code by symbol / regex inside a repo | remote_grep (Baz) |
| Find files by name / glob inside a repo | remote_file_search (Baz) |
Forbidden — every kind of search goes through a Baz tool, never through your read or shell tool. These are the patterns that cause the most waste:
gh api .../contents/<dir>, gh api .../git/trees/HEAD?recursive=1, ls/find over a checkout). Use remote_file_search.gh search code, grepping fetched files). Use remote_grep.Read, gh api .../contents/<path>, curl, …) for anything except opening one already-known file path. Pointing it at a directory, or firing several to "look around", is a search — route it through remote_file_search / remote_grep. The read tool is the last step, never the exploration.If the user has not told you which repo(s) to look in, call repo_search exactly once with broad keywords:
repo_search(keywords: ["<topic>", "<topic synonym>"], domains?: ["API", "BUSINESS_LOGIC", ...])
Read the returned {repoId, repoName, domain, summary} entries and pick the most likely repos using your own judgement (results are not LLM-ranked). Use that identifier verbatim in later tools — don't guess repository from a local folder or service name (the index may name it differently), and note a service is often indexed as a subdirectory of a larger repo, so prefix path accordingly.
If the result is empty or too large, do not re-call repo_search with rephrased keywords. Instead:
exceeds maximum allowed tokens): re-call once with a domains filter to narrow scope.When you have a symbol / string / regex, grep inside the repo:
remote_grep(repository: "<repo>", pattern: "<regex>", path: "<dir-or-.>")
Results group matches by file with line numbers and ~2 lines of context per match.
When you only have a naming hunch (no symbol yet), use the file-name search:
remote_file_search(repository: "<repo>", pattern: "**/*router*.ts")
The pattern must contain a naming token. Do not call remote_file_search with a bare extension (**/*.ts, **/*.go) — that returns a 50-file slice of an unknown directory and wastes a call. If you don't have a naming hunch, run remote_grep for a symbol instead.
Baz tools accept a repository argument — either the short leaf name (e.g. baz) or the full owner/repo (e.g. org/baz); pass the full form if the short name is ambiguous across the org. They default to the repo's default branch HEAD, and any ref argument accepts a branch name or a 7–40 character hex commit SHA (case-insensitive).
Search budget — strict. Each MCP search call costs ~3s. Two limits, both hard:
(repository, path) pair you MUST open/read at least one matched file — local Read if the repo is checked out, otherwise your own fetch — before issuing a 4th search on that pair. Rephrasing OR-alternations of the same concern (foo|Foo|foo_bar) on the same path is forbidden — the first call already returned everything that matches; if it didn't, the term is wrong (not under-tokenized) and you should pick a different symbol or read a file.(repo, path) pair does not reset this count.Adding one more case to an existing set? — another value in an enum, another implementation of an interface, another branch in a dispatcher (a new type, provider, command, route, event, or handler). The most common planning miss is leaving out a place the new case must be registered. Before finalizing, run ONE repo-wide search for the identifier of an existing peer in that set — grep the name of a sibling value or class already in the codebase. Its hits enumerate every site the set is wired through: the enum / constant list, factory or lookup maps, switch / match arms, dispatch or handler tables, route tables, and config. Your plan must add the new case at each site. This is a single cheap search, not a wide read — it surfaces the registration points that reading only one sibling's own implementation file misses. Skim that sibling's tests too: an existing assertion that your new case is absent or unsupported will need updating. Every site this sweep surfaces must be addressed in the plan as a concrete required change (or explicitly ruled out with a reason) — do not leave a surfaced site as an open question.
Once you have a concrete file path from Step 2, open it — use your local Read if the repo is checked out, otherwise fetch it however you normally would (Baz has no whole-file read tool). Read one known path per call; never point your read/fetch tool at a directory.
If you find yourself wanting to look around (list a directory, walk a tree), stop and go back to Step 2 — that's a search, not a read.
If the change depends on something in another repo — an API, schema, or contract you don't own — verify it from source with Baz before finalizing, rather than assuming it's already in place.
Open questions are only for decisions a person must make — product scope, editable-vs-read-only, which behavior is intended. They are not a place to defer code you found but didn't check. If your peer-enumeration sweep (or any search) surfaces an internal touch-point — a sibling classifier, a walker, a registration site, a config — read it and either include the change as a required step or state concretely why it is not needed. Never park a discovered internal touch-point as a "confirm?" open question; that reads as an omission, not diligence.
The "verify or flag" caution applies only to genuinely external/third-party behavior you cannot read from source — a remote API's semantics, an SDK's data shapes, a file format's rules. Even then, prefer verifying it from source with the indexed-search tools before assuming; only note it as an open question if it is truly unknowable from the code.
Span the stack — is this layer the builder or a proxy? Before you commit to the layer you found, confirm it's the one that actually builds the thing you're changing, not one that merely forwards it. A single feature (an API response, an event, a record) often crosses language/service boundaries within one repo — e.g. a TypeScript BFF endpoint that proxies a response actually constructed by a Rust platform/ crate. If you find a handler that returns or re-exposes data without defining its shape, keep searching upstream (other directories, other language stacks like platform/crates, src/, pkg/) for where the shape is defined. Naming the proxy instead of the builder means the planned change wouldn't actually take effect.
Verify before you assert. Never state that code already does something — already returns a field, already handles a case, already registered, is already wired — based on a name, a type, or a nearby file. Open the definition and read it. Most wrong plans come from an unverified "this is already handled" assumption that a look at the source would have disproved. If you catch yourself inferring behavior instead of confirming it, that's a signal to read the file.
Based on what you found, propose:
repo_search with rephrased keywords. One call, then pick a repo.remote_file_search / remote_grep.Explore agent) — it silently falls back to local Read/Grep and skips Baz. If you spawn a subagent and the work reaches code outside the local checkout (another repo, or the side of a contract you don't own), its prompt must tell it to use the Baz MCP tools (repo_search / remote_grep / remote_file_search) per this skill's routing rules.The baz plugin's SessionStart hook injects your sessionId, the cwd repo (sessionRepository), and the client name (agentVendor, e.g. claude-code, codex, cursor) into your context. You MUST pass all three as arguments on every call to repo_search, remote_grep, and remote_file_search. Without them, baz cannot correlate your tool calls to a session and the calls are dropped from baz's timeline. This is non-negotiable — treat the values as required, not optional, regardless of what the tool schema marks them as.
When you've finished planning and are ready to present the plan to the user, write the final plan to /tmp/.baz-plan-<sessionId>.md (substitute your real sessionId). Your next tool call after writing the file MUST be mcp__baz__update_plan (fully qualified — not update_plan alone, which is not a callable tool name); pass sessionId and content set to the exact plan text you just wrote (verbatim). This tool call is what tells baz to persist this as the final plan and close the planner session. Don't respond to the user or run any other tool in between. Skipping this leaves the session open in baz's timeline forever. Call it exactly once per planning session.
content and (where available) tokensUsed values. Pass those exactly as given — do not substitute your own recollection or estimates.additionalContext from non-MCP-tool hooks). Call mcp__baz__update_plan yourself immediately after the file write, passing sessionId and content set to the exact plan text you just wrote (verbatim). Token counts aren't available client-side and should be omitted.npx claudepluginhub baz-scm/baz-plugin --plugin bazCode-only search across the current repo and connected repos via context_search_code. Use this instead of context_research when you want code results without Slack, Jira, or doc noise mixed in. TRIGGER when: Grep/Glob/Read can't find a referenced class, function, or module (it may live in another connected repo); you need semantic code search rather than a literal pattern match; you want to find how something is implemented or used across repos; the user asks to "find", "locate", or "search for" code. DO NOT TRIGGER when: local Grep/Glob/Read can find what you need; you also need PR history, team decisions, Slack context, or issue tracker data — use context_research instead.
Navigate large or unfamiliar codebases via the basemind MCP server — outlines, symbol search, reference/caller lookups, commit history, blame, and diffs without reading source files. Reach for it whenever the user asks "where is X defined", "what calls Y", "what changed recently in Z", or whenever you're about to grep or open many files to find structural information.
Codebase comprehension via roam-code CLI. Use when exploring codebases, planning modifications, debugging failures, assessing PR risk, or checking architecture health. Triggers on: understanding project structure, pre-change safety checks, finding symbols/files, blast radius analysis, affected tests, health scoring, refactoring guidance, code review. Requires roam-code installed (`pip install roam-code`) and an indexed project (`roam init`).