CLI parity with the MCP surface, a CLI-driven skill, and a context-budget receipt#133
Merged
Conversation
…catalog The valid analyze kinds were duplicated in three drifting places: the dispatch switch in handleAnalyze, the kind param's schema description, and two error strings. Extract analyzeKinds as the single source of truth; the schema description and both error strings now derive from it, and an AST-based test pins the slice to the switch cases bidirectionally so they can never drift again. Add ToolDescriptor and Server.ToolDescriptors(), which join the previously-disjoint tool metadata sources (functional category, mutating-vs-read, builtin-preset membership, and a one-line summary) into one per-tool record built from the live registry so it can never under-report a tool. Surface it in the tool_profile response and cover it with a completeness test. This is the metadata the forthcoming CLI tool surface reads over the socket.
gortex call <tool> invokes any registered tool by name over the daemon, so every tool is reachable from the shell without mounting the MCP surface. Arguments lower from a --json/--json-file/stdin base object overlaid by repeatable --arg key=value pairs with deterministic coercion (bool/number/null/JSON, key:=raw to force a raw-JSON string, key= for empty); --format forwards json/gcx/toon/text; --dry prints the lowered call without a daemon. Unknown names are validated best-effort against the live catalog with nearest-match suggestions, and mutating tools print a write-note. gortex tools list|search|describe is the CLI analogue of tool_profile and tools_search: list renders the descriptor catalog (category, read/write, preset membership) with client-side filters, search ranks the deferred surface, describe prints a tool's schema. Discovery never promotes or mutates the daemon's live tool set.
Thirteen subcommands shell the edit-safety tools the mandatory workflow relies on — context, verify, plan, preview, simulate, batch, apply, symbol, rename, guards, tests, contract, and safe-delete — so an agent can run the whole verify/edit/guard/test loop from the shell without mounting the MCP surface. A shared readStructuredArg helper resolves JSON arguments from an inline value, a file, or stdin; --change 'id=newsig' is sugar that builds the verify_change array; safe-delete defaults to a dry run and only writes under --apply, and boolean flags whose daemon default is true are omitted unless their --no- form is passed.
…emory Six subcommands shell the session-note and durable-memory tools — note, notes, distill, store, recall, surface — so the mandatory save/recall/surface workflow runs from the shell without the MCP surface. Each flag is forwarded only when the user set it, so the daemon's own defaults hold for everything left unspecified, and numeric flag types are matched to how each handler reads them.
gortex analyze --kind dispatches the whole analysis surface from one verb, with the kind validated client-side against the shared analyze-kinds source of truth and kind-specific parameters carried by --arg using the same coercion as gortex call; gortex analyze kinds lists the valid kinds without a daemon. flow and taint trace dataflow and taint paths, clones surfaces near-duplicate code, and feedback record|query closes the context-quality loop the workflow documents. find_clones' repo-prefix filter is exposed as --repo-filter because --repo is already the universal repo-path alias.
A single user-level, plain-markdown skill installed alongside the existing ones by gortex install, scoped to Bash(gortex:*). It frames the gortex CLI as a flexible toolkit plus a reference safety workflow — orient, assemble context, surface prior decisions, verify a change, apply a batch, check guards and tests, then record feedback and durable memory — every step a real gortex shell command, with a pointer to gortex tools search and gortex call for the long tail. It loads on demand and mounts no MCP surface, so an agent can run the documented workflow with zero baseline tool-schema context. The agents-render drift fence covers it across all 17 adapters.
gortex tools receipt emits a context-budget receipt that makes the consumption posture inspectable: the transport, the tool surface a connecting MCP client would advertise versus what is deferred, and that the CLI path mounts zero tool schemas. It reads the daemon's tool_profile for the live and deferred counts and the active preset; with no daemon reachable it still emits a receipt (transport cli_only, nothing mounted) rather than failing. yaml by default, json on request. This is the transport-and-counts half of the receipt; a per-session record of which verbs and safety steps actually ran follows separately.
…fety steps ran The receipt's cli_verbs_used and safety_steps_run cannot come from telemetry, which is consent-gated off by default and keeps only daily counts with no session dimension. Add a consent-free cli_events table to the sidecar, modeled on savings_events, that records one row per CLI verb when GORTEX_SESSION_ID is set — and does nothing (opens no database) when it is not, so the default interactive path pays no cost. gortex tools receipt then reads the session's verbs and derives safety_steps_run from a fixed verb-to-safety-tool map, so a CLI path that silently skips verify, guards, or tests is visible in the artifact rather than merely asserted to be equivalent.
…t doors docs/cli.md gains a full reference for the new verbs (call, tools, edit, memory, analyze, flow, taint, clones, feedback), the shared structured-input convention, the --arg coercion rules, and a trade-off table comparing the MCP-install and skill-plus-CLI consumption paths. docs/skills.md adds the gortex-cli skill as a first-class zero-schema path. docs/mcp.md notes that the same handlers back both front doors and that the daemon dispatches tool calls by name, so the CLI reaches the full surface — including deferred tools — even under the core preset. CLAUDE.md is softened so the mandatory workflow reads as reachable via MCP or the equivalent gortex CLI verbs, not MCP alone.
Resolve the analyze-kind conflict in handleAnalyze by keeping the single-source-of-truth error strings (built from analyzeKindsCSV) over the merged-in hardcoded lists, and add the new doc_staleness kind to analyzeKinds so the dispatcher, its error strings, the schema description, and the AST drift test stay in sync with the switch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #108.
What this does
Gives the
gortexCLI parity with the MCP tool surface and ships a plain-markdown skill that drives the documented workflow through CLI verbs — so an agent can use Gortex's edit-safety and memory tools without mounting the MCP surface and paying its per-turn tool-schema context cost.The enabling fact: the CLI already reaches the daemon over the same socket the MCP server uses, and the daemon dispatches tool calls by name regardless of which tools are eagerly published. So every tool is already reachable; this is a CLI presentation layer plus a skill, a receipt, and docs — no handler changes.
Layers
Single source of truth.
AnalyzeKinds()replaces three drifting copies of the analyze-kind list (the dispatch switch, the schema description, two error strings), pinned by an AST test.ToolDescriptor/ToolDescriptors()joins the previously-disjoint tool metadata (category, mutating-vs-read, preset membership, summary) into one record, surfaced intool_profile.Generic passthrough + discovery.
gortex call <tool>invokes any registered tool by name, with httpie-style--arg key=valuecoercion (key:=rawforces raw JSON), a--json/--json-file/ stdin base object,--format, and--dry.gortex tools list|search|describe|receiptis the CLI analogue oftool_profile/tools_search.Curated verb groups.
gortex edit— context, verify, plan, preview, simulate, batch, apply, symbol, rename, guards, tests, contract, safe-delete. A shared structured-input helper accepts inline / file / stdin JSON;--change 'id=sig'is sugar for verify; safe-delete is a dry run unless--apply.gortex memory— note, notes, distill, store, recall, surface.gortex analyze --kind <k>(+analyze kinds),gortex flow,gortex taint,gortex clones,gortex feedback record|query.The
gortex-cliskill. A single user-level, plain-markdown skill installed bygortex install, scoped toBash(gortex:*), that walks the workflow throughgortexshell verbs with no MCP transport mounted. Covered by the agents-render drift fence across all 17 adapters.Context-budget receipt.
gortex tools receiptemits an inspectable artifact: the transport, the advertised-versus-deferred tool counts,registered_tool_schemas: 0on the CLI path, and — whenGORTEX_SESSION_IDis set — the session'scli_verbs_usedand a derivedsafety_steps_run, so a CLI path that silently skips verify / guards / tests is visible rather than merely asserted to be equivalent. Backed by a new consent-freecli_eventssidecar table that opens no database on the default interactive path.Tests
Each verb group has stub-seam lowering tests (flags → exact tool + args) that run without a live daemon. Also covered: the analyze-kinds AST drift test, the tool-catalog completeness test, the structured-input parser, the receipt (both daemon-reachable and no-daemon), the
cli_eventsround-trip, and the verb→safety-step derivation. Full build,go test -raceon the touched packages,go vet, golangci-lint, the wire-contract golden, andagents render --check(17 adapters) all pass. Binary smoke:analyze kinds→ 73,call --drylowers correctly,tools receiptemits a real receipt.Docs
docs/cli.mdgains the full verb reference, the structured-input convention, and a consumption-path trade-off table;docs/skills.mdadds the skill as a zero-schema path;docs/mcp.mdnotes the two front doors over one set of handlers;CLAUDE.mdis softened so the mandatory workflow reads as reachable via MCP or the equivalentgortexCLI verbs.