Skip to content

feat(cli + widgets): lift CLI to first-class docs surface + cooldown picker for cli-install + ship working snippets across all widgets#6

Merged
tony merged 16 commits into
masterfrom
feat/cli-section
May 19, 2026
Merged

feat(cli + widgets): lift CLI to first-class docs surface + cooldown picker for cli-install + ship working snippets across all widgets#6
tony merged 16 commits into
masterfrom
feat/cli-section

Conversation

@tony
Copy link
Copy Markdown
Owner

@tony tony commented May 19, 2026

Summary

  • Lift the agentgrep CLI to a first-class documentation surface: new /cli/ section in the sidebar, per-subcommand reference pages auto-generated via gp-sphinx's sphinx-autodoc-argparse, --json / --ndjson scripting docs on every subcommand page, README reordered so CLI leads.
  • Port the {mcp-install} widget's "Configure cooldowns" picker to the new {cli-install} widget so both surfaces share the cooldown UX and persisted-state shape.
  • Modernize {library-install} to PEP 723 / uv add / pip install (the previous uvx / pipx run flavors were tool-runners, not library-install patterns).
  • Fix the unresolvable-cooldown bug that bit every install widget's days-mode snippets: uvx + uv add panels now carry --exclude-newer-package <pkg>=2099-01-01; pipx + pip panels fall back to the bare command with a redirect note to the uvx tab. Verified against pip 26.1.1 source (_internal/cli/cmdoptions.py:463) that pip's --uploaded-prior-to has no per-package override, and against pipx 1.8.0's commands/run_uv.py::_UV_TRANSLATABLE_VALUE_FLAGS that pipx's uv-backend whitelist doesn't forward --exclude-newer or --uploaded-prior-to.
  • Flatten the docs sidebar so every section caption (CLI / Library / MCP / Reference) shows its sub-pages directly under it, with the section landing labelled "Overview" — no more nested dropdown tier.

Test plan

  • uv run ruff check . --fix --show-fixes clean
  • uv run ruff format . clean
  • uv run ty check clean
  • uv run py.test --reruns 0 -vvv — 214 passed
  • just build-docs succeeds with no warnings
  • Live verified uvx --exclude-newer P7D --exclude-newer-package agentgrep=2099-01-01 --from agentgrep agentgrep-mcp starts the server
  • Live verified pipx run agentgrep --help works as the bare-command fallback
  • Spot-checked rendered HTML: /cli/index and homepage both carry {cli-install} (compact on homepage), all 12 (method × cooldown) panels render, settings sub-view + cooldown control + redirect notes all present, every section sidebar reads flat with "Overview" as the first entry

Companion change

The same cooldown-snippet fix shipped to libtmux-mcp's mcp-install widget on tmux-python/libtmux-mcp#58 — both repos share the same git-pull workspace widget design and had the same bug.

tony added 14 commits May 18, 2026 17:21
why: The new /cli/ docs section auto-generates per-subcommand option lists from the live argparse tree using gp-sphinx's sphinx-autodoc-argparse extension. Pinning it alongside the other gp-sphinx packages keeps the doc toolchain consistent.

what:
- Add sphinx-autodoc-argparse==0.0.1a20 to the dev and docs dependency groups in pyproject.toml.
- Refresh uv.lock with the new transitive dependencies.
why: sphinx-autodoc-argparse expects :func: to point at a zero-arg callable returning argparse.ArgumentParser, but create_parser requires a ColorMode argument and returns a ParserBundle. A thin adapter bridges the shape without changing any runtime call sites.

what:
- Add build_docs_parser() returning create_parser("never").parser for docs autogen consumption.
- Cover the adapter with test_build_docs_parser_returns_root_parser asserting it yields an ArgumentParser with prog="agentgrep".
- Extend the AgentGrepModule structural type so ty recognises the new attribute on the loaded module.
why: With the dependency pinned and an argparse-shaped factory available, Sphinx needs the extension loaded to resolve the .. argparse:: directive used by the upcoming /cli/ pages.

what:
- Append "sphinx_autodoc_argparse" to extra_extensions in docs/conf.py, slotted alphabetically between sphinx_autodoc_api_style and sphinx_autodoc_fastmcp.
why: uvx and pipx run are tool-runners, not library-install patterns — they execute agentgrep as a CLI without making the package importable, so they made no sense on the library landing page. The library widget should demonstrate ways to consume agentgrep as a Python dependency: a self-contained PEP 723 script, an in-project install via uv add, or a traditional pip install. The same pass aligns the widget's outer chrome with the mcp-install proportions so all three install widgets share one visual rhythm.

what:
- Replace uvx-run and pipx-run methods with a single uv-script method whose panel shows a runnable PEP 723 inline-metadata script and a $ uv run example.py invocation.
- Generalise Panel to carry per-block Pygments languages (code_a_lang / code_b_lang) so PEP 723's python-then-console ordering and uv add / pip's console-then-python ordering share one template.
- Drop the ag-library-install__install-block / __quickstart-block wrapper divs and rewrite widget.css to mirror mcp-install's overflow-hidden card, flush tabs with bottom-border active marker, and body padding.
- Update widget.css panel-visibility selectors to the new method ids and bump the localStorage key to agentgrep.library-install.method.v2 in widget.js and the prehydrate snippet so stale uvx-run / pipx-run state falls back to the default instead of hiding every panel.
why: The terminal CLI needs its own install picker so the homepage and /cli/index can show install + first-run commands per package manager. Mirrors the existing library-install / mcp-install widgets so all three surfaces share one visual rhythm and one prehydrate-driven first-paint contract.

what:
- Add docs/_ext/widgets/cli_install.py with four methods (uvx run, pipx run, uv add, pip install). Each panel pairs the per-method install (or transient-run) command with three CLI invocations carrying the right wrapper prefix — uvx agentgrep ... for the transient methods, uv run agentgrep ... for uv-add, bare agentgrep ... for pip. Each command renders as its own copyable code block per CLAUDE.md conventions.
- Add docs/_widgets/cli-install/{widget.html,widget.css,widget.js} sharing the mcp-install proportions: overflow-hidden card, flush tabs with bottom-border active marker, body padding instead of outer padding, no wrapper divs around .highlight.
- Support a :variant: option (full | compact) so compact-mode embeds can sit next to {mcp-install} :variant: compact on the homepage without size mismatch.
- Register the flash-of-wrong-panel prehydrate hook by adding inject_cli_install_prehydrate to docs/_ext/widgets/__init__.py and the matching snippet to _prehydrate.py.
why: Until now the docs site treated the terminal CLI as incidental — there was no per-subcommand page, no documented --json / --ndjson contract, and no scripting affordance writeup for agents that don't speak MCP. Lifting the CLI to a first-class /cli/ section makes the terminal surface as discoverable as the library and MCP surfaces.

what:
- Add docs/cli/index.md with the {cli-install} widget, a card grid linking to the subcommand pages, a "Use from another agent" section describing --json / --ndjson, and the root parser argparse autodoc.
- Add docs/cli/search.md and docs/cli/find.md modelling vcspull's per-subcommand shape: anchor + intro + Examples (one command per code block) + Command (eval-rst .. argparse:: :path: ... :nodescription:) + JSON output / NDJSON output sections cross-linking the SearchRecord / FindRecord schemas. The search page also covers --ui (Textual TUI) and --agent filtering.
- Use :nodescription: on every argparse block so the auto-rendered "examples:" lines from build_description() don't collapse into a definition-list paragraph. The page's own Examples section, with one console block per command, is the canonical surface.
why: With the {cli-install} widget shipped and /cli/index live, the homepage needs to surface the CLI alongside MCP so terminal-first users see their entry point on first paint. The left sidebar gains a CLI caption between Get started and Library.

what:
- Add a {cli-install} :variant: compact block above the existing {mcp-install} :variant: compact so both pickers share proportions and CLI users see their install snippet first.
- Add a CLI grid-item-card between Quickstart and MCP that links to /cli/index with a one-liner about the --json / --ndjson scripting affordance.
- Insert a CLI toctree caption between the Get started and Library captions, listing /cli/index.
why: The storage catalogue is reference material that describes which on-disk stores agentgrep knows about — it isn't a getting-started step a new user needs before their first search. Grouping it under Project alongside the changelog matches its actual role.

what:
- Remove storage-catalog from the Get started toctree in docs/index.md.
- Add storage-catalog to the Project toctree above history and the GitHub external link.
why: The README currently reads MCP-first, with the CLI only mentioned in the install section. Now that /cli/ is a first-class doc surface, the README should lead with CLI usage so terminal-first readers (PyPI, GitHub landing) see how to drive agentgrep without setting up an MCP client.

what:
- Add a ## CLI quickstart section showing agentgrep search, agentgrep find --json, and agentgrep search --ui in three separate single-command code blocks, with a one-line note that --json / --ndjson make every command pipe-friendly for agents that don't speak MCP.
- Reframe ## Install around the CLI entry point and point readers to https://agentgrep.org/cli/ for the full picker.
- Demote the existing MCP setup and Library quickstart sections below CLI quickstart so the README matches the new sidebar order (CLI > MCP > Library).
why: Record the CLI documentation lift and the library widget overhaul under the 0.1.0a4 placeholder block so the unreleased entry reflects what's actually staged for the next release.

what:
- Add a lead paragraph describing the CLI as a first-class documentation surface.
- Add #### CLI reference site and #### CLI install widget deliverables under ### What's new with prose describing the /cli/ section, the {cli-install} widget, and the cross-references to SearchRecord / FindRecord.
- Add a ### Development note recording the sphinx-autodoc-argparse dependency floor.
why: The cooldown-days span emitted by ``make_cooldown_days_slot_filter`` had an mcp-prefixed class hardcoded into the filter, blocking the cli-install widget (about to gain the same cooldown UX) from reusing the same sentinel mechanism. Renaming to a shared, widget-agnostic class makes the filter output valid in both install widgets without duplicating the helper.

what:
- Update _base.py::make_cooldown_days_slot_filter to emit class="ag-cooldown-days" on both the duration and date span sentinels instead of the mcp-prefixed variant.
- Rename the matching .ag-mcp-install__cooldown-days selector in mcp-install/widget.css to .ag-cooldown-days; the rule carries no own styling (the wrapping Pygments span supplies the color) so the visual is byte-identical.
why: The cli-install widget had no dependency-cooldown story while the sibling mcp-install widget has carried a polished picker since 0.1.0a3. A security-conscious terminal user copying snippets off /cli/ had no way to ask for --exclude-newer or --uploaded-prior-to flags on the install command. Bringing the same picker to the CLI surface closes the gap so both install widgets share one cooldown UX, one persisted state shape, and one prehydrate-driven first-paint contract.

what:
- Extend cli_install.py with a (method, cooldown) panel matrix: 4 methods x 3 cooldown modes (off / days / bypass) = 12 panels. Import the shared Cooldown dataclass + DEFAULT_COOLDOWN_* + COOLDOWNS tuple from mcp_install rather than re-declaring.
- Wire per-cell install / usage prefixes for each cooldown mode: uvx and uv-add days panels carry --exclude-newer <DURATION>, uvx and uv-add bypass panels carry --no-config, pipx days panels carry --pip-args=--uploaded-prior-to=<DATE>, pip days panels carry --uploaded-prior-to <DURATION>, off panels carry nothing. Transient runners (uvx, pipx) propagate the cooldown flag onto every usage invocation since nothing lands on PATH; uv-add and pip apply the flag only on the install step.
- uv-flavored days panels add --exclude-newer-package agentgrep=2099-01-01 alongside the global cutoff so a recently-released agentgrep stays inside the resolver (uv would otherwise filter the target package out and the snippet would fail with "no versions of agentgrep"). pipx and pip lack a per-package override flag, so their days panels surface a caveat note pointing users at the uv-flavored snippets.
- Add the cooldown control row (toggle + label + ? help) to widget.html alongside the methods tab list, plus a settings sub-view body with back button, days input, bypass radio, and an explainer linking to cooldowns.dev / Datadog Security Labs.
- Mirror mcp-install's cooldown styling in widget.css: control row, label/help buttons, cooldown-note caveat, settings sub-view swap keyed on html[data-cli-install-view="settings"], back/title/help/explainer/days input/radio modes. Add compact-variant overrides so the homepage embed proportions match mcp-install's compact variant.
- Replace the minimal _cli_install_snippet in _prehydrate.py with a real script-plus-style block: mirror four localStorage axes (method, cooldown.enabled/type/days) onto <html data-cli-install-*> before first paint; emit @layer cli-install-prehydrate {...} carrying tab deactivate / active rules, the panel hide rule, the 12-selector (method x cooldown) panel-active matrix, and the checkbox styling that paints the ✓ before any JS runs.
- Rewrite cli-install/widget.js as a full state machine modelled on mcp-install: document-level event delegation, broadcast-event cross-widget sync, applyCooldownToWidget + updateAllCooldownSlots (live duration/date textContent update on every keystroke), readCooldown* helpers backed by localStorage, transient install/settings view toggle that resets on gp-sphinx SPA nav.
- Add a smoke test asserting build_panels emits one panel per (method, cooldown) cell, the default cell is (uvx-run, off), uv-flavored days panels carry the --exclude-newer-package exempt, and pipx/pip days/bypass cells surface the right caveat notes.
why: The 0.1.0a4 release notes need to call out the cooldown picker port + the agentgrep-self-exempt detail, so readers see the security feature and have a heads-up about the pip-flavored caveat.

what:
- Add a #### CLI cooldowns deliverable under ### What's new describing the off / days / bypass variants, the live duration / date sentinel update, and the cross-widget broadcast that keeps the homepage embed and /cli/index in sync.
- Add a paragraph explaining the agentgrep=2099-01-01 exempt on uv-flavored days panels and the pip-flavored caveat note (no per-package override flag).
- Note under ### Development that make_cooldown_days_slot_filter now emits the shared ag-cooldown-days class so cli-install can reuse the same sentinel mechanism without duplicating the helper.
… days panels

why: The mcp-install widget's uvx-flavored days-mode snippets emitted ``uvx --exclude-newer P7D --from agentgrep agentgrep-mcp`` without a per-package override, so a fresh release of agentgrep (newer than the cooldown cutoff) made the install unresolvable — ``no versions of agentgrep`` from uv's resolver. uv's hint points at ``--exclude-newer-package <pkg>=<date>`` as the per-package override; setting it to a far-future date exempts the target package while keeping the cooldown applied to transitive deps. Mirrors the same fix that landed for {cli-install} in this release.

what:
- Insert ``--exclude-newer-package agentgrep=2099-01-01`` after ``--exclude-newer <DURATION>`` in the uvx + days branches of _tool_command, _json_body, and _toml_body, so every uvx + days panel (CLI, JSON, TOML body shapes) carries the exemption.
- Extend _cooldown_note to surface a caveat for (pipx, days) and (pip, days) panels — pip's ``--uploaded-prior-to`` is a global cutoff with no per-package override, so when the cooldown filters out a recent agentgrep release the snippet stays unresolvable. The caveat points readers at the uvx snippet, which carries the exemption.
- No changes to bypass / off panels — bypass already skips any global uv cooldown, off has no cutoff, both stay resolvable.
tony added 2 commits May 18, 2026 21:06
…mands

why: ``pipx run --pip-args=--uploaded-prior-to=<DATE> agentgrep`` failed live with ``ERROR: Could not find a version that satisfies the requirement agentgrep`` whenever the cutoff filtered fresh agentgrep releases. Direct source verification confirmed there's no fix: pip 26.1.1's ``_internal/cli/cmdoptions.py:463`` defines ``--uploaded-prior-to`` as a single global cutoff with no per-package override flag, and pipx's ``commands/run_uv.py::_UV_TRANSLATABLE_VALUE_FLAGS`` only forwards a narrow whitelist of pip args to its uv backend (no ``--exclude-newer`` / ``--uploaded-prior-to``). pip issue #13674 (relative cooldown) landed but no per-package issue is even open; uv issue #18386 is the closest tracker. The previous attempt added a caveat note but kept the broken snippet — users still hit the failure when they copied the command. The honest fix is to drop the cooldown flag for pipx + pip and surface the limitation in the note.

what:
- mcp_install.py + cli_install.py: ``_tool_command`` / ``_install_command`` / ``_usage_prefix`` / ``_pip_prereq_for`` / ``_json_body`` / ``_toml_body`` all return the bare command for (pipx, *) and (pip, *) — no ``--pip-args=--uploaded-prior-to`` or ``--uploaded-prior-to`` flag emitted. The uvx and uv add days panels keep ``--exclude-newer P7D --exclude-newer-package agentgrep=2099-01-01`` since uv has both flags.
- ``_cooldown_note`` for (pipx | pip, days | bypass) now returns a single redirect note: "pip has no per-package cooldown override, so this snippet runs without cooldown enforcement. Switch to the uvx tab — it applies the cooldown to transitive deps via ``--exclude-newer`` while exempting agentgrep itself via ``--exclude-newer-package``." Drops the old separate (pipx, bypass) and (pip, bypass) notes that were about ``pipx[uv]`` and uv-backed parent commands respectively.
- Remove the now-unused ``_DATE_SENTINEL`` constant and ``PIP_PREREQ_DAYS`` constant from mcp_install.py; remove the ``_DATE_SENTINEL`` placeholder from cli_install.py.
- Update test_cli_install_panel_matrix to assert pipx-run / pip days panels emit the same bare command as off / bypass.
why: Each section caption (CLI / Library / MCP / Reference) listed one entry — the section's index.md — which carried its own hidden toctree listing the sub-pages. Sphinx renders that two-toctree shape as a nested ``Caption > Section landing > {subpage, subpage}`` collapsible group in the furo sidebar. Pulling the sub-pages into the parent toctree alongside the landing flattens the structure to a single tier, so every section reads ``Caption > {Overview, subpage, subpage, …}`` with no dropdown.

what:
- Promote the sub-pages of /cli/, /library/, /mcp/, and /reference/api/ into docs/index.md's per-caption toctrees, and label each section's index.md as ``Overview <section/index>`` so the sidebar entry reads "Overview" instead of repeating the caption text.
- Drop the now-redundant hidden toctrees from docs/{cli,library,mcp,reference/api}/index.md — listing the same docs in two toctrees would otherwise leave the sidebar pulling the inner one and re-introducing the nested shape.
- Section landing pages keep their URLs (``/cli/``, ``/library/``, ``/mcp/``, ``/reference/api/``) and their in-page grid cards / cross-refs, so the homepage grid card links and any external links to a section landing still resolve.
@tony tony force-pushed the feat/cli-section branch from f490e86 to 3afb45a Compare May 19, 2026 02:06
@tony tony merged commit e6a30ba into master May 19, 2026
3 checks passed
@tony tony deleted the feat/cli-section branch May 19, 2026 02:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant