Skip to content

Add doc search command (JSON documentation search)#7770

Merged
isaacroldan merged 7 commits into
mainfrom
search-vector-store-json
Jun 23, 2026
Merged

Add doc search command (JSON documentation search)#7770
isaacroldan merged 7 commits into
mainfrom
search-vector-store-json

Conversation

@nelsonwittwer

@nelsonwittwer nelsonwittwer commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

What

Adds shopify doc search --query <query>, which queries the shopify.dev vector store and prints the most relevant documentation chunks as JSON to stdout.

This is the "discovery" half of the new doc namespace; the "full document" half is doc fetch (#7766). It no longer repurposes the top-level search command — that stays as the human, browser-based command (and is deprecated separately in #7778).

Why

Gives agents (and scripts) a way to discover relevant documentation across shopify.dev as structured JSON, without a browser. Paired with doc fetch, an agent can find the right docs and pull them in full, entirely through the CLI.

Details

  • shopify doc search --query "<query>" — required query; prints the raw JSON response.
  • --api-name (e.g. admin, storefront, hydrogen, functions; unknown values ignored).
  • --api-version (e.g. 2025-10, latest, current).
  • Non-ok responses surface the server's {error} message (e.g. an invalid version lists the valid ones).
shopify doc search --query "subscribe to webhooks"
shopify doc search --query "create a product" --api-name admin --api-version latest

🎩 Testing instructions

doc search hits a public endpoint on shopify.dev (/assistant/search) — no auth, no app, no login required. It just needs network access and prints JSON to stdout.

# 1. Check out this branch and build (dev.js runs the prebuilt bundle, so a build is required)
cd <your cli checkout>
git checkout search-vector-store-json && git pull
pnpm nx build cli

Run commands from the repo root via node packages/cli/bin/dev.js …:

1. Basic query → well-formed JSON

node packages/cli/bin/dev.js doc search --query "subscribe to webhooks" | jq 'length'
#   → a number (count of chunks), with no jq parse error

2. API/version filters are forwarded

node packages/cli/bin/dev.js doc search --query "create a product" --api-name admin --api-version latest | jq '.[0]'
#   → the first result object

3. Invalid version (with an api-name) surfaces the helpful error

node packages/cli/bin/dev.js doc search --query "create a product" --api-name admin --api-version 1999-01
#   → "Search failed: Invalid api_version '1999-01' for api_name 'admin'. Available versions: …"  (exit non-zero)

Note: the endpoint only validates the version in the context of an --api-name. A bad --api-version on its own is silently ignored and still returns results.

4. Required arg + help

node packages/cli/bin/dev.js doc search          # → "Missing required flag query"
node packages/cli/bin/dev.js doc search --help   # → usage, description, examples, --api-name / --api-version flags

Inspecting the Monorail analytics payload

This branch is rebased on the app-context telemetry PR (#7771), so every command emits a command-analytics event. To see exactly what would be sent to Monorail — without sending it — set two env vars:

  • SHOPIFY_CLI_NO_ANALYTICS=1 — dump the payload via debug logging instead of POSTing it.
  • SHOPIFY_FLAG_VERBOSE=1 — raise the log level so the debug line prints.
SHOPIFY_CLI_NO_ANALYTICS=1 SHOPIFY_FLAG_VERBOSE=1 \
  node packages/cli/bin/dev.js doc search --query "webhooks" 2>&1 \
  | grep "Skipping command analytics"
#   → a "Skipping command analytics, payload: {…}" line with "command": "doc search"

To confirm the inherited app-context hook, run the same command from inside an app directory while logged in — the payload then also carries app-level identifiers (api_key, project_type, app_*). Run it from a non-app directory and those fields are absent.

Screenshot 2026-06-22 at 2 35 22 PM

I saw the APP metrics broadcast via monorail when executing in the path of an app.

When not in the path of an app (in this case in the path of the CLI that I pulled down) - I did not broadcast app context.
Screenshot 2026-06-22 at 2 36 53 PM

Related

🤖 Generated with Claude Code

@nelsonwittwer nelsonwittwer requested review from a team as code owners June 9, 2026 18:21
@nelsonwittwer nelsonwittwer marked this pull request as draft June 9, 2026 18:22
@github-actions github-actions Bot added the Area: @shopify/cli @shopify/cli package issues label Jun 9, 2026
*/
export interface search {
/**
* Limit results to a specific API (for example: admin, storefront, hydrogen, functions). Unrecognized values are ignored.

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.

❤️

Comment thread packages/cli/README.md Outdated
Starts a search on shopify.dev.
Query the shopify.dev vector store and print the most relevant documentation chunks as JSON. Best for programmatic
discovery — surfacing the relevant pieces of documentation for a topic, rather than retrieving a whole document. To
download a full document verbatim, use `fetch-doc`.

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.

Should discuss this contract with @nickwesselman . I'd assume that shopify search could just have a --fetch-doc param rather than a whole separate command for that case.

Copy link
Copy Markdown
Contributor

Having second thoughts about using shopify search for this.

I'm sure use of shopify search is near-zero, but should we stick to our SemVer committment, and create a new command? We could fix the existing command or just deprecate it.

This would also give us an opportunity to apply our CLI design guidelines to a new command. e.g. The shopify search use of positional arguments is against those guidelines.

@nelsonwittwer nelsonwittwer force-pushed the search-vector-store-json branch from 2f4b95a to b8d45bd Compare June 9, 2026 20:01
@nelsonwittwer nelsonwittwer changed the base branch from main to telemetry-app-context-everywhere June 9, 2026 20:04
@nelsonwittwer nelsonwittwer changed the title Refactor shopify search to query the dev-assistant vector store as JSON Add doc search command (JSON documentation search) Jun 10, 2026
@nelsonwittwer nelsonwittwer force-pushed the search-vector-store-json branch from f0656f4 to 848fa45 Compare June 22, 2026 17:08
@nelsonwittwer nelsonwittwer marked this pull request as ready for review June 22, 2026 18:38
static description =
'Query the shopify.dev vector store and print the most relevant documentation chunks as JSON. Best for programmatic discovery — surfacing the relevant pieces of documentation for a topic, rather than retrieving a whole document. To download a full document verbatim, use `doc fetch`.'

static usage = `doc search [query]`

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.

nit: doc search since query is required

if (apiName) params.append('api_name', apiName)
if (apiVersion) params.append('api_version', apiVersion)

const response = await fetch(`${SEARCH_URL}?${params.toString()}`, {

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.

use shopifyFetch?

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.

also need to handle network errors gracefully

@kaylarobinson077

Copy link
Copy Markdown

Looking through the existing cli monorail schema, nothing stands out to me as a pre-existing fit for capturing doc search results. My suggestion would be that we add a new monorail field cmd_doc_search_result where we put the json result, then when we extend to validate and other commands, add in related fields like cmd_validate_passes.

Additionally, currently the args monorail field is flagged as PII, so anything we are passing in there (e.g. the search query) is redacted after 30 days. The pattern followed here for cases where we want to retain the flags for longer duration is to additionally log them in a separate field, so we might consider also adding a field like cmd_doc_search_query to explicitly log the search query and not flag it as PII to retain. Not directly related to this PR, but this also is impacting any vars we are saving through the agent env vars, as they're subject to the same PII policy.

So, if this sounds reasonable, I can update the monorail schema to include cmd_doc_search_query and cmd_doc_search_result. For doc fetch, maybe I'll also add in cmd_doc_fetch_query (but skip result there, since it's just the docs content for the requested link?)

@nelsonwittwer

Copy link
Copy Markdown
Contributor Author

@kaylarobinson077 - I think the cleaner solution for tracking search would be on the search handler. That one hanbdler is where all search traffic goes already

nelsonwittwer and others added 5 commits June 22, 2026 16:22
…JSON

The `search` command opened a browser at shopify.dev?search=<query>, which
now redirects to the docs SPA and silently drops the query — so it has been
broken for users while still being invoked ~70-100x/month.

Repurpose it as an agent-facing JSON tool: it queries the dev-assistant
vector store (GET https://shopify.dev/assistant/search) and prints the
matching documentation chunks as JSON to stdout. No browser. This complements
`fetch-doc` (verbatim full-document retrieval) as the "chunked discovery" half.

- `query` is now required.
- Adds `--api-name` and `--api-version` filters, passed through to the server.
- 400 responses surface the server's error message (e.g. valid api_version list).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per the doc-namespace plan, the JSON vector-store search lives at
`doc search` instead of repurposing the top-level `search` command:

- Add commands/doc/search.ts (class DocSearch), services/commands/doc/search.ts
  (docSearchService), and the colocated test; register as `doc:search`.
- Add a `doc` topic description.
- Revert the breaking change to top-level `search` — it goes back to the
  original browser behavior (handled/deprecated separately in #7778).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Identifies the CLI as the calling surface to shopify.dev so traffic
originating from the CLI can be attributed as such.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- usage now reads `doc search <query>` since the arg is required
- use shopifyFetch (proper TLS + automatic retries for a Shopify service)
- handle network failures gracefully with a friendly AbortError
- regenerate oclif manifest + README for the usage change

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per the CLI design guidelines: flags make intent explicit, don't rely
on order, and are easier to evolve. Regenerated manifest + README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nelsonwittwer nelsonwittwer force-pushed the search-vector-store-json branch from ba8ac8e to 550fbb3 Compare June 22, 2026 20:24
@nelsonwittwer nelsonwittwer changed the base branch from telemetry-app-context-everywhere to main June 22, 2026 20:25
@github-actions

Copy link
Copy Markdown
Contributor

Differences in type declarations

We detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

We found no new type declarations in this PR

Existing type declarations

packages/cli-kit/dist/public/node/session.d.ts
@@ -47,6 +47,22 @@ export declare function isUserAccount(account: AccountInfo): account is UserAcco
  * @returns True if the account is a ServiceAccount.
  */
 export declare function isServiceAccount(account: AccountInfo): account is ServiceAccountInfo;
+/**
+ * Reports whether the CLI already has stored credentials, without prompting the
+ * user, opening a browser, or making any network request.
+ *
+ * This is a passive, side-effect-free check: it reads the local session store and
+ * returns  when at least one valid session is present. Unlike the
+ *  functions, it never triggers a login flow and never logs
+ * the user out. Because it does not contact the network, it cannot tell whether the
+ * stored token is currently valid/unexpired — only that credentials exist locally.
+ *
+ * Intended for best-effort, opportunistic behaviour (for example, enriching
+ * telemetry only for users who are already logged in).
+ *
+ * @returns True if local credentials exist, false otherwise.
+ */
+export declare function sessionExists(): Promise<boolean>;
 /**
  * Ensure that we have a valid session with no particular scopes.
  *

Copy link
Copy Markdown

@kaylarobinson077 - I think the cleaner solution for tracking search would be on the search handler. That one hanbdler is where all search traffic goes already

​Is the search handler something that lives within this command, or is it something outside of CLI? My home is that we can track the query and result in the regular CLI monorail event, so everything lives together in one place in terms of where the data lands.

Assisted-By: devx/214c76e8-6ac0-48f1-bff5-0ef68c95d938
Assisted-By: devx/214c76e8-6ac0-48f1-bff5-0ef68c95d938
@isaacroldan isaacroldan added this pull request to the merge queue Jun 23, 2026
Merged via the queue into main with commit b5f0db2 Jun 23, 2026
28 checks passed
@isaacroldan isaacroldan deleted the search-vector-store-json branch June 23, 2026 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: @shopify/cli @shopify/cli package issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants