Skip to main content
The deterministic Code tools let your agent search indexed packages and repositories, grep source, list files, and read exact lines at a package version or repository ref. For generated implementation examples, use Example. GitHits indexes public repositories on demand. When a search needs indexing, follow the response’s progress or retry guidance. If it includes a searchRef and an active status (PENDING, INDEXING, or SEARCHING), use search_status to follow that search. Some responses also include provisional hits you can use while indexing continues. Supported languages for code indexing: Bash, C#, C++, CSS, Dart, Elixir, Erlang, Go, Java, JavaScript, Kotlin, Lua, Markdown, PHP, Proto, Python, R, Ruby, Rust, Scala, SCSS, Swift, TypeScript, Zig, and more.

Choose a target

Use a package target for that package’s source, a repository target for the whole repository, or an explicit site: target for hosted documentation. Pass a known target directly to the tool. Use target resolution when you only know a dependency’s name. Omit a package version for the latest release or a repository ref for its default branch. Repository refs can be branches, tags, or commits and may contain additional @ characters. Use @ to introduce a ref; # selects a symbol or documentation heading, not a revision. Preserve returned targets, paths, selectors, and line bounds when following a read action. From CLI and MCP 0.32.0, cargo: aliases public crates.io crates: targets. Canonical identities remain crates; the alias does not select alternate Cargo registries.

Repository hosts

GitLab and Codeberg targets are available from CLI and MCP 0.15.0; Launchpad Git targets from 0.33.0. Hosted MCP availability depends on the deployed package version. Full HTTPS repository URLs are also accepted on github.com, codeberg.org, gitlab.com, code.launchpad.net, git.launchpad.net, and public *.googlesource.com hosts. GitLab paths can contain nested subgroups. Use a repository root, not a file, tree, issue, or merge-request URL. Bare owner/repo names and other hosts, including self-hosted GitLab instances, are not supported. GitHub additionally accepts github.com/owner/repo and HTTP URLs.

Launchpad Git targets

Use launchpad: or its case-insensitive lp: alias with one of these paths. The owner, project, distribution, source, and repository names below are placeholders. Append @ref to select a branch, tag, or commit. HTTPS URLs on both Launchpad hosts accept these paths. git://git.launchpad.net requires a complete owner-qualified path. Bazaar branches are unsupported. Default shortcuts can change their owner or repository. GitHits resolves them to canonical launchpad: identities; reuse the returned target and exact ref for follow-ups instead of guessing the owner.

Googlesource targets

From CLI and MCP 0.38.0, search, read, list, grep, and diff accept public *.googlesource.com project URLs. Hosted MCP gets this support after deployment. Googlesource has no compact prefix, so use the full HTTPS project URL. Append @ref to select a branch, tag, or full or short commit SHA.
  • Use HTTPS only. GitHits rejects HTTP and other transports.
  • Omit ports, credentials, query strings, and fragments. GitHits rejects every explicit port, including :443.
  • Use the project root, not a Gitiles web route such as /+/refs/heads/master.
  • Project path case is preserved. Nested project paths are accepted.
  • GitHits removes one trailing .git and one trailing slash, so https://go.googlesource.com/time.git/ and https://go.googlesource.com/time are the same target.
For HTTP requests, see API target inputs.

Code tools

search is the primary discovery tool. It searches across code, documentation, and explicit symbols in indexed packages and supported public repositories. Use it when you need to find where something is defined, which files handle a specific concern, or which docs page explains a behavior.Query syntax supports implicit AND, uppercase OR, grouping with parentheses, negation with -, quoted phrases, and semantic qualifiers:Choose a package, repository, or documentation target. In the CLI, pass targets with repeatable --in flags. In MCP, pass target for one target or targets for multiple targets.CLI usage
Key parameters
string
required
Discovery query string. Supports AND (implicit), OR (uppercase), parentheses, - negation, quoted phrases, and semantic qualifiers (kind:, category:, path:, lang:, name:, intent:).
string
Single package, repository, or documentation target, such as npm:react@18.2.0, gitlab:group/subgroup/project, or lp:beautifulsoup. See target syntax.
array
Multiple search targets. Use either target or targets, not both.
string
Restrict results to code, symbol, or docs. Omit to let GitHits choose the best indexed sources. See Documentation for docs-focused search, listing, and reading workflows.
boolean
default:"true"
Returns available hits while other targets or sources prepare, plus a searchRef for continuation. From 0.27.0, defaults to true. Set false to wait for all runnable targets and sources before returning hits; a complete interim result may still be returned during a refresh.
number
Maximum results to return (default 10, max 100).
Provisional resultsWhile a target is still indexing, search can return provisional repository-code results. Provisional hits come from an exact-commit snapshot and are immediately usable, but the session is not finished. The response marks the results as still indexing, reports the exact served identity and PROVISIONAL freshness instead of the ref you requested, and keeps the active searchRef so you can continue with search_status.Text outputSince 0.27.1, search and search_status text starts with a plain outcome headline that counts returned results by kind, such as Found 2 code results and 1 documentation result. Empty responses say No results found., No results available yet., or No results on this page. for an empty continuation page. A Sources: section lists each searched source. Repository rows show the exact served commit and, when known, the UTC commit date and the ref it was indexed from, for example github:owner/repo@aaaaaaaa (committed 2026-09-01, indexed from ref HEAD). A commit date is not an indexing time or a freshness claim. Since 0.36.0, an unconfirmed package-to-source match is noted inline; see package source correspondence. Targets still indexing appear under Preparing: with their estimate. When the backend reports omitted results that nothing else explains, the text adds These results do not cover the full request.The hits follow, then up to three footers in a fixed order:
  • Read: shows one example read call for a returned hit, pinned to the served revision.
  • More results: tells you to repeat the original search with the exact next offset.
  • Follow-up: offers a conditional search_status wait, shown only when waiting could change the results.
JSON output did not change.Semantic matchesRepository code and repository docs hits show the matched source: the enclosing declaration scopes around the match, followed by the exact matched source with its original line numbers:
  • The header carries the read target, path, and matched line range. Package hits pair the registry, package, and version with the package-relative path. Repository hits pair the repository with its exact served commit and the repository-root path.
  • Scope rows list the enclosing declarations outer-to-inner, each with its kind, qualified name, and inclusive declaration line range. Pick your follow-up read range directly from these rows: the header range for the local match context, or an enclosing declaration range for the full definition. No separate per-hit read command is printed.
  • Source lines keep their original numbering, indentation, and boundaries. A > gutter marks lines that contain matches and stays visible without color. Omitted lines, cropped long lines, truncated scope chains, and incompletely highlighted matches carry explicit ASCII notices.
Search text only shows source the backend proved matched:
  • A repository hit without proven matched source renders as a single candidate header line. No source lines, scope rows, or summary appear under it:
    • The line range is the backend’s bounded read window. Use it as a place to inspect with read. It does not prove the match location.
    • For a bare identifier query, visible terms: lists the query fragments (split on camel case and underscores) visible in the title or displayed path when those indexed fields contributed to the hit. If no fragment is visible, the header names the contributing indexed fields instead, for example indexed: path/identifiers. If field provenance is unknown, the header shows only candidate.
    • When a known declaration in the same file contains the window, the header ends with its kind and qualified name, for example - interface AuthSessionStore.
    • visible terms are substrings observed in the returned text. They do not prove a match and do not explain the ranking.
  • Older results without matched source still show Snippet unavailable and keep their locators.
  • Crawled documentation pages use a structural preview of the page with match highlighting instead of source lines.
  • Explicit symbol hits show qualified identity with signature detail, kind, and any differing definition range, without a summary body.
In JSON output, each repository hit’s locator keeps the legacy filePath, startLine, and endLine and adds:
  • commitSha — the exact served revision
  • repositoryFilePath — the repository-root path (as opposed to the target-relative filePath)
  • evidenceRange — the focused match range
  • indexedRange — the originally indexed range
  • symbolContext — the enclosing symbol’s name, optional qualifiedPath and kind, and a normalized lowercase relation: encloses_match (a proven enclosing definition, always with a complete definitionRange) or associated_with_indexed_chunk (associated context, definitionRange optional)
JSON hits additionally carry the structured results behind the text rendering:
  • repositoryEvidence.semanticContext — the enclosing declaration scopes (outer-to-inner, with kind, qualified path, inclusive declaration ranges, parameter names, and return type) and a preferredRead locator with exact attributed read coordinates
  • repositoryEvidence.matchedSource — the proven numbered source: inclusive line bounds, match anchor, range kind, per-line text with grapheme-offset highlights, and crop/omission flags
  • repositoryEvidence.bm25MatchFields — the indexed fields that contributed matches (SYMBOL_NAME, FILE_PATH, DOCUMENTATION, SOURCE_IDENTIFIER). A known list is complete and ordered; null means the breakdown is unknown, not that nothing matched.
  • documentationPreview — the structural preview text and highlight ranges for crawled documentation hits
Since 0.23.0, search and search_status no longer emit summary, highlights.summary, hit contentSafety, or repositoryEvidence.focusedSource. JSON consumers must use matchedSource, indexed-field provenance, semantic context, and documentationPreview as appropriate. A candidate header is a navigation aid; inspect its bounded window before treating it as a source match.Repository hits also provide a followUp read command. Prefer this emitted action so the target, path, and bounds stay consistent. Package-attributed repository code and docs use the served package target and target-relative path; repository targets retain the served revision and repository-root path. JSON keeps snapshot provenance. When a preferred range exceeds the 300-line MCP read cap, the generated command requests a bounded window while the structured ranges remain unchanged.Search text does not print a read command under each hit. The Read: footer shows one example. Use the target and location from each hit header for other direct reads. For the exact backend-selected section, request JSON and replay the complete followUp, including its target, path, selector, and bounds.Follow-up toolsEach hit’s type field tells you which follow-up tool to use:
  • repository_code or repository_symbol → read with the compact target and exact path. In text output, build the call from the hit header and scope rows. In JSON, prefer the hit’s followUp command, which reads the preferred range at the exact served revision.
  • Repository documentation hits → use the emitted followUp, or the target, path, and range in the text header. These reads return indexed file content.
  • Hosted documentation hits → read with the result’s docsReadTarget as target (and no path), or its pageId when no target is emitted.
search_status lets you follow up on a search response that returned a searchRef instead of hits. This happens when indexing is still running. Pass the searchRef from the prior search response to check progress, fetch partial hits, or retrieve final results.Session statesEvery search and search_status response reports a session status. The status set is open: the backend can introduce new values, and clients preserve them instead of rejecting the response.DEFERRED is terminal on both the initial search response and search_status progress. It means background lifecycle work continues outside the session, so the searchRef no longer advances. Any hits already disclosed remain usable.CLI usage
Parameters
string
required
The searchRef value from a prior search response. Pass it through unchanged (the response field uses camelCase; this parameter uses snake_case).
number
Maximum time to wait for progress, 0–120,000 milliseconds (default 30,000). Pass 0 to return immediately. The 120-second ceiling matches the upstream HTTP deadline; GitHits picks a longer wait automatically when the response carries indexing-time estimates.
string
default:"text"
text (default) for compact output, or json for the structured result. The former text-v1 value is no longer accepted; omit the parameter or pass text instead.
With the default allow_partial_results: true, the search_status response may include hits from sources that have finished so far, with pagination support via nextOffset.
grep searches ordered package, repository, and hosted documentation targets for a known pattern. Use search for topics, list to find paths, and read for more context.Since @githits/mcp 0.25.0, grep replaces code_grep. Refresh local MCP tool discovery and migrate the arguments; this is not just a rename. Hosted availability depends on the deployed server version. CLI githits grep was added in 0.24.0; legacy githits code grep remains available with its older flags and defaults.The defaults are RE2 regex, case-sensitive matching, zero context lines, and all indexed repository files. To preserve the old literal, case-insensitive behavior, set pattern_type: "literal" and ignore_case: true explicitly.MCP example
Package targets also include their selected hosted documentation. corpus and path_selectors filter repository files only; they do not exclude a package’s hosted docs. Site entries accept only target.CLI usage
See the grep CLI reference for all flags.From CLI 0.38.0, grep and legacy code grep cap context requests above 10 lines per side and report the adjustment. MCP still requires context values within 0–10. Use read for a larger range.From CLI and MCP 0.33.0, text output distinguishes a complete search with no matches from sources that are preparing, unavailable, or only partly covered. Check coverage before treating an empty result as absence. Follow the response’s named retry targets, cursor, and wait controls; do not assume an unchanged retry will help when retryability is unknown or unsupported.Parameters
array
required
One to 20 ordered objects. Each contains target, plus optional corpus (source, documentation, or all) and path_selectors for package or repository targets. Each path selector has kind (exact, prefix, or glob) and value; selectors form a union relative to that target’s root. Omit both controls for site: targets.
string
required
Pattern of 1–200 UTF-8 bytes. RE2 regex does not support lookaround or backreferences. foo|bar matches either alternative; foo\|bar matches a literal pipe. Content-index searches require literal text; a single exact-file route accepts anchorless regex, but a path selector alone does not guarantee that route. Unsupported patterns fail explicitly.
string
default:"regex"
regex or literal substring matching.
boolean
default:"false"
Set to true for case-insensitive matching with Unicode folding.
number
default:"0"
Lines before each match, 0–10.
number
default:"0"
Lines after each match, 0–10.
number
default:"100"
Maximum occurrences across all scopes on this page, 1–1000. This is a global cap, not a per-file limit.
string
Opaque continuation cursor. Reuse the same ordered targets, pattern, and matching controls. Empty starts the first page. Restart without a cursor if it expires.
number
default:"30000"
First-page preparation wait in milliseconds, 0–300,000. Pass 0 to return immediately. Continuation pages never wait.
string
default:"text"
text for grouped matches, read locators, coverage, and continuation guidance. Use json for detailed hit and scope fields, read actions, and byte coordinates.
Since 0.27.1, text starts with a plain outcome headline that counts matches, distinct lines, and files or pages on this page, such as Found 4 matches on 3 lines in 2 files. An empty page says No matches found., No matches on this page. when a cursor remains, or No matches available yet. when only indexing targets were omitted. A Sources: section names the searched scopes, followed by Preparing: for targets still indexing and Omitted: for other skipped targets. Text then groups matches under numbered file or page headers. Each header starts with the read locator. After the matches, a footer lists Read: templates for files and pages, More results: with the cursor, and Follow-up: with a retry for omitted targets, in that order. Use the emitted read locator and line numbers for more context. Match rows use : after the line number; context rows use -. Coverage and counts describe this page only. A small match cap can leave scopes unvisited; follow the returned cursor to continue. Hosted pages may change between grep and read.Package-path warningsSince CLI and MCP 0.36.0, grep flags path selectors that wrongly include a package’s path inside its repository. Package target paths are relative to the package root. For example, drizzle-orm/src/pg-core on npm:drizzle-orm repeats the package path. Text output then shows one compact line per distinct correction:
The warning is advisory. Matches, failures, pending targets, and cursors are unchanged, and the client does not retry automatically. Rerun with the suggested path when you meant the package-relative location.JSON output adds a pathWarnings array containing the same strings. The array is empty when there are no warnings, so JSON callers can always read it. Custom grep providers injected into the client must also supply pathWarnings.Package source correspondence notices also apply to grep. See package source correspondence.
list lists the files and documentation paths in one known package, repository, or hosted documentation site. Use it to discover paths before calling read, to scope a grep, or to explore the structure of an unfamiliar package. Use search instead when your agent knows the topic.Since @githits/mcp 0.24.0, list replaces the retired code_files and docs_list MCP tools. If you upgrade an existing MCP client, refresh its tool catalog so it discovers list. The hosted MCP server exposes list once GitHits deploys @githits/mcp 0.24.0 to it.A package target covers that package’s own source tree. A repository target covers the whole snapshot. Both include source and documentation files. Hosted documentation is a separate inventory that requires an explicit site: target. See Documentation for site inventories.Select entries with paths. Each entry is a target-relative literal path or glob, and multiple entries form a union. Selected directories show their immediate children unless recursive is true. Glob depth is independent of recursion.Since 0.27.0, source text output starts with a Sources: section naming the served source. Repository rows show the exact commit and, when known, its UTC commit date and the ref it was indexed from. Since 0.36.0, the output also notes when a package-to-source match is unconfirmed; see package source correspondence. A Read files: line follows with the read template for the listed paths, then one path per line. Directory entries end in /. An empty inventory starts with No files., or No files available yet. while the source is still indexing. Indexing sources also get a Preparing: section and a retry hint. When more entries exist, a More results: footer shows the after cursor to pass on the next call. Reuse the same target, paths, and options with that cursor, and treat it as opaque.
CLI usage
npx githits@latest code files is deprecated but keeps its existing behavior for compatibility. See the list command for all CLI flags.Parameters
string
required
Package such as npm:express@5.2.1, repository such as github:expressjs/express, or hosted docs site such as site:expressjs.com.
array
Target-relative literal paths or globs, such as ["lib/", "lib/**/*.js"]. Entries form a union. Omit or pass [] to browse the root.
boolean
Expand selected directories to all descendant files. Without it, selected directories show immediate children.
array
Source inventories only. Case-insensitive classifications such as source or doc. Use paths globs for extensions.
array
Source inventories only. Case-insensitive language names such as javascript or typescript.
array
Source inventories only. File intents: PRODUCTION, TEST, BENCHMARK, EXAMPLE, GENERATED, FIXTURE, BUILD, or VENDOR.
number
Maximum entries to return (1–500).
string
Opaque nextCursor from a prior list response. Reuse the same target, paths, filters, recursion, and limit.
number
Maximum wait for source indexing in milliseconds, 0–300,000 (default 30,000). Pass 0 to return immediately.
string
text (default) or json. Use json for exact entry kinds (FILE, PAGE, or DIRECTORY), read and browse actions, lifecycle metadata, and nextCursor.
read is the one advertised reader on the MCP surface. Pass a package or repository target and exact path to read a file, including repository documentation. For hosted documentation, pass a page locator alone or, since 0.23.0, an emitted site: target plus its target-relative page path. The resolved result determines code or documentation presentation. See Documentation for hosted page reads.Use the read locator from search, grep, or list to target a file, then set start_line and end_line to fetch only the window you need. Repository search hits supply read coordinates directly: the hit header and scope rows in text output, or the ready-made followUp read command in JSON, both pinned to the exact served revision.Since 0.36.0, code reads note when GitHits cannot confirm that the package version matches the served revision. See package source correspondence.Since githits and @githits/mcp 0.22.0, you can pass selector to read an indexed code symbol, such as a function or class name, without knowing its line range. A symbol read returns the symbol’s indexed definition range by default. Add path to restrict the lookup to that exact file, or omit it to search the whole code target. path always means an exact target-relative file. Either explicit bound overrides the definition range. The hosted MCP server exposes selector once GitHits deploys @githits/mcp 0.22.0 to it.When a symbol selection returns no source, the response carries a typed status with recovery guidance:
  • AMBIGUOUS: several indexed symbols match. The response lists up to 10 candidates. Retry with one candidate’s exact path.
  • NOT_FOUND: no indexed symbol matches. The response lists up to 10 suggestions. Retry with a suggestion, or locate the symbol with search.
  • SNAPSHOT_UNSUPPORTED: the indexed snapshot does not support symbol selection. Find the definition with search or grep, then read the exact path with start_line and end_line.
The MCP surface returns 150 lines by default and allows explicit ranges up to 300 lines per call. When you omit end_line, the read returns 150 lines from your start point. When you pass an explicit start_line/end_line range, the read honors it up to 300 lines. Broader ranges truncate and include a hint describing what was returned versus requested, with the continuation start_line for the next call. The CLI command npx githits@latest read has no line cap for piping.CLI usage
With --repo-url and --selector, pass at most one positional path. The CLI rejects an extra path argument.CLI 0.22.1 and MCP 0.22.0 also support compact target#symbol reads, with an optional exact path. Do not combine a compact fragment with selector.The npx githits@latest code read and npx githits@latest docs read commands remain available as deprecated commands with their existing flags. Use top-level read for site paths, compact symbol targets, and --selector.Parameters
string
required
With path: a compact package or repository target, or an emitted site: target for hosted documentation. Without path: a documentation locator, a compact target#symbol, or a code target with selector. Pass emitted locators through unchanged.
string
Exact package- or repository-relative file path from discovery results, or a target-relative page path for an explicit site: target. Omit when passing a complete documentation locator; an empty string counts as omitted. Use list to discover source paths.
string
Indexed code symbol name, or a logical documentation heading ID. With a code path, searches only that exact file; with a site path, selects a hosted heading. Without a code path, searches the whole code target. Selected code returns its definition range unless you set a bound. Do not combine with a URL fragment or compact target#symbol.
number
Starting line (1-indexed). For code reads, omit to start at line 1. For documentation pages, either bound replaces a URL fragment with a page-relative range.
number
Ending line (inclusive). Must be ≥ start_line when both are set. Text output returns 150 lines without an end, up to 300 with one. Code JSON is also bounded; documentation JSON preserves the backend selection.
number
Code indexing wait, 0–60,000 ms (default 30,000). Validated for documentation reads but not forwarded, because the docs backend has no indexing wait.
Read only the lines you need — a focused window around the symbol or grep match you are investigating. The 150-line default keeps reads focused; use an explicit range up to 300 lines when you know the required bounds, such as reading a modest whole file without pagination. Each retry costs additional context budget, so aim for one well-sized read per location.
Response fields for code reads: {path, language, totalLines, startLine, endLine, content, isBinary, hint?}. Binary files set isBinary: true and omit content. Documentation reads keep their existing docs-side response shape.
Available by default in CLI and MCP 0.26.0. Hosted availability depends on the deployed MCP version.code_diff compares repository trees resolved from two package versions or two public repository refs, left-to-right. Use it to inspect changes between exact versions when you want git-shaped output. For upgrade review — vulnerabilities, changelog entries, deprecation, peer/dependency changes — call pkg_upgrade_review instead; raw diffs do not prove API compatibility or upgrade safety.Pass an unversioned target with separate MCP from and to values. The CLI uses a required <from>..<to> range; three-dot merge-base syntax and --git-ref are rejected.Scope is always repository-wide. Package addressing resolves package, repository, version, and exact-commit identity, but every raw diff is repository-wide. code_diff does not discover or filter to a package directory. Sibling package paths may appear in a monorepo, and a bounded relevance-ranked result may contain no files from the addressed package. That absence does not prove the package is unchanged.MCP path_glob or a CLI glob after -- narrows repository paths without changing the scope.Launchpad targets are accepted, but comparisons between different commits currently return nonretryable RAW_DIFF_UNAVAILABLE. If both refs resolve to the same commit, the result is an empty inventory.MCP defaults to name-status; the CLI defaults to --patch. Use stat for change counts or a scoped patch for content. File bounds apply after relevance ranking; patch-byte bounds apply only to patches.MCP text previews each patch at 320 UTF-8 bytes. Use format: "json" for the full returned patch, still subject to byte limits and content coverage. Check truncation and content-safety warnings before using a patch; incomplete, filtered, byte-escaped, or omitted content is not safely applicable.MCP parametersPass --verbose to show exact version or ref resolution and effective repository-scope diagnostics in text output.CLI usage
The selected Git-like view goes to stdout. Truncation, content-safety, display-only path warnings, and From source: or To source: correspondence notices go to stderr. Empty authoritative diffs exit 0. Caller-selected --max-files and --max-patch-bytes bounds may intentionally produce partial patches and still exit 0 with warnings. Unexpectedly incomplete or non-applicable plain patches are suppressed and exit 1; the --stat, --name-only, --name-status, and JSON views preserve their structured partial results.

Package source correspondence

Since CLI and MCP 0.36.0, search, search_status, grep, list, read, and code_diff disclose when GitHits cannot confirm that a package version matches the source revision it serves. The notice appears inline beside the exact source revision:
The label depends on the source’s role: The notice wording describes the assessment:
  • match to <package>@<version> unconfirmed means GitHits could not confirm that the revision corresponds to that version.
  • version tag, match to <package>@<version> unconfirmed means GitHits selected the revision from a version tag without further confirmation.
  • listed revision for <package>@<version> unavailable; another revision selected means the revision the package lists could not be served, so GitHits selected a different one.
An unconfirmed match is not a claim about the published binary. It means only that GitHits could not confirm the correspondence. Results remain usable. When exact correspondence matters, check the published artifact yourself before relying on the source. These notices are independent of index freshness. JSON output keeps the backend source assessments in the target resolution and diff side data, so JSON callers can apply their own policy.

Output formats

Every format-selectable MCP tool accepts a format parameter with exactly two values: text (the default) and json. Use text for reading and tool follow-ups; it is token-efficient, and you can pass returned paths, IDs, and line ranges directly to subsequent tools. Use json only to parse responses in code or to obtain fields absent from text. The former text-v1 value is rejected as of CLI and @githits/mcp 0.13.0; callers that passed it explicitly should omit format or send text. Rendering and JSON payloads are unchanged.

MCP tool reference

For target discovery, use resolve_target.