Skip to main content

F8.1 — CLI / MCP / API surface matrix

The single reference for how every hot workflow maps across the three surfaces — CLI (@driftless-sh/cli), MCP (@driftless/mcp), and the API (@driftless/api) — plus what each read returns by default and how to opt into a heavier payload. Read it to answer: “which command/tool/route do these three things share, what shape comes back, and what is fast by default?” Conventions:
  • Default view is the payload tier a read returns when no view is passed (summary / brief / full — see views.md). full is never a default; a caller opts in.
  • Full-view opt-in is how you ask for the heavy body when you actually need it.
  • The MCP names are the literal tool names in apps/mcp/src/tools/tool-registry.ts; the CLI names are the literal subcommands in apps/cli/src/commands/*; the API rows are the Nest routes under apps/api/src/* (all under /workspaces/:slug).

Topics — read

WorkflowCLIMCP toolAPI endpointDefault viewFull-view opt-inPayload shape
Search by keywordcontext search <q>driftless_context_searchGET /topics/search?q=summary (top 5 CLI/MCP)n/a — search is index-only; context_get the hit{ shown, has_more, hint?, next_action, topics[] }
List a domaincontext list [--area|--tag|--stale]driftless_context_listGET /topicssummary (top 40)view=full{ shown, has_more, hint?, next_action, topics[] }
Get one topiccontext get <slug>driftless_context_getGET /topics/:slugfull (you named it)defaultone CanonicalContext
Topics for filescontext get --files "a.ts,b.ts"driftless_context_get_for_filesGET /topics/match-filesbrief (top 10, drifted first)view:"full"{ shown, has_more, hint?, matches[] }
Topics for local diffcontext get --diff [--mark]driftless_context_get_for_files (pass the diff file list)GET /topics/match-filesbriefview:"full"match-files shape
Unified retrieve (task and/or files)context retrieve "<task>" [--explain] (+ context get --files/--diff for the file-shaped reads)driftless_context_retrievePOST /topics/retrievebriefview:"full"{ view, total_candidates, signals, shown, results[] }
Retrieve is the START-HERE primitive when you have a task but no slug. It composes search + match-files + list filters, ranks them drifted-first, and annotates each hit with match_type / why_matched / confidence / next_action. The unified ranker is exposed on all three surfaces: CLI (context retrieve "<task>", --explain for why_matched), API (POST /topics/retrieve), and MCP (driftless_context_retrieve); context get --files/--diff remain the file/diff-shaped reads.

Topics — write & govern

WorkflowCLIMCP toolAPI endpoint
Create a topic / notecontext add <slug> --area --pattern · note adddriftless_context_create · driftless_note_addPOST /topics
Update (append-safe)context update <slug> --gotcha/--decision/--add-patterndriftless_context_updatePATCH /topics/:slug
Propose → Knowledgecontext propose <slug> · context approve <slug>driftless_context_propose · driftless_context_approvePOST /topics/:slug/propose · …/approve
Suggested editcontext pr <slug> --opendriftless_context_create_proposal · driftless_context_proposalsPOST /topics/:slug/proposals
Relations / graphcontext relations · context graphdriftless_context_relations · driftless_context_graphGET /topics/:slug/relations · …/graph
Sharecontext share <slug>driftless_context_sharePOST /topics/:slug/share
Deletecontext delete <slug>driftless_context_deleteDELETE /topics/:slug
Merge duplicatescontext merge <src> --into <dst>driftless_context_mergePOST /topics/:slug/merge
Coverage / doctor / eventscontext doctordriftless_context_coverage · driftless_context_doctor · driftless_context_eventsGET …/coverage · …/doctor · …/events

Tags & Areas

WorkflowCLIMCP toolAPI endpoint
Tags (list / create / delete)tags [add|rename|rm]driftless_tags (action)GET|POST|DELETE /tags
Areas (list / create / update / delete)area [list|add|rename|rm]driftless_areas (action)GET|POST|PATCH|DELETE /areas

Projects — the agent loop

WorkflowCLIMCP toolAPI endpointDefault viewFull-view opt-in
Projects (list / get / set)project [list|get|add|update]driftless_project (action)GET|POST|PATCH /projectssummary?view=full
Card loop tickproject card next <pid>driftless_project_card action:nextGET /projects/:id/cards/nextbundle by refs→summarysummaries→brief · full→full
Card CRUD / statusproject card add|get|status|move|rmdriftless_project_card (action)…/cards routes
next returns { card, context_bundle, project_done } — one call per loop iteration. The bundle ships the team’s recorded context for the card’s area so the agent doesn’t re-derive it.

Collections — the operational substrate

WorkflowCLIMCP toolAPI endpointDefault view
Collections (list / get / add / update)collection [list|get|add|update]driftless_collection (action)GET|POST|PATCH /collectionssummary
Collection criterion (the seam)driftless_collection action:contextGET /collections/:id/contextcriterion topics
Collection retrieve (records + criterion, one call)driftless_collection action:retrieveGET /collections/:id/retrievebounded records page + criterion
Records (list / get / add / update)collection record [list|get|add|update] · collection recordsdriftless_collection_record (action)…/collections/:id/recordskeyset page
Entities (list / get / upsert)driftless_entity (action)GET|POST /entities
collection retrieve is the operational analogue of topic retrieve: relevant records plus the criterion Knowledge to read before acting, in one GET. Records paginate by keyset ({ records, nextCursor }).

Integrations (SETUP) vs Broker (EXECUTION)

These are deliberately two separate concerns. Setup connects/configures a provider (the privileged connect flow); the broker only operates a connection that already exists. Authoring/deploying a Nango action is a third, human-only lane that neither surface touches (the no-agent-scripting rule).
WorkflowCLIMCP toolAPI endpoint
SETUP — catalogintegration catalog— (setup is human-led)GET /integrations/nango/catalog
SETUP — connectintegration connect <provider>POST /integrations/nango/:provider/connect-session
SETUP — confirmintegration confirm <provider>POST /integrations/nango/:provider/confirm
SETUP — list / disconnectintegration list · integration rm <id>GET /integrations · DELETE /integrations/:id
SETUP — guidancebroker setup(prose; no call)
EXEC — connectionsbroker connectionsdriftless_broker action:connectionsGET …/broker/connections
EXEC — capabilitiesbroker capabilities <provider>driftless_broker action:capabilitiesGET …/broker/connections/:provider/capabilities
EXEC — operationsbroker operations <provider> [--refresh]driftless_broker action:operationsGET …/broker/connections/:provider/operations
EXEC — invokebroker invoke <provider> <op> --inputdriftless_broker action:invokePOST …/broker/connections/:provider/invoke
EXEC — records (synced model)broker records <provider> --modeldriftless_broker action:recordsGET …/broker/connections/:provider/records
EXEC — page/document contentbroker page <id>driftless_broker action:page-contentGET …/broker/connections/notion/pages/:id/content
INDEX — connector document previewbroker index <provider> --dry-rundriftless_broker action:index-previewPOST …/broker/connections/:provider/index/preview
INDEX — connector document executebroker index <provider>driftless_broker action:indexPOST …/broker/connections/:provider/index
EXEC — eventsbroker events [provider]driftless_broker action:eventsGET …/broker/events
EXEC — criterionbroker criterion <provider> [--add|--rm]driftless_broker action:criterionGET|POST|DELETE …/criterion
Operations are served from materialized metadata; --refresh (CLI) / refresh:true re-pulls the live list from Nango. Records mirror a synced model and are delta-aware (--modified-after / cursor). Broker reads and writes both run inline + audited — Driftless is a tooling proxy; the human-in-the-loop is your own agent harness. Connector document indexing is the explicit bridge from external source data to Driftless-owned retrieve substrate. Preview first; execute writes only connector_documents. Default context retrieve stays Topics-only. Connector retrieve is opt-in (sources:["connectors"] / include_external) and returns trust:"external" with citations and freshness. STOP rule: if an agent needs a broker operation that broker operations <provider> does not list, it must report the missing capability — never author or deploy an integration script to fill the gap.

Comments — annotate either plane

WorkflowCLIMCP toolAPI endpoint
Comment (add / list / resolve)context comment [add|list|resolve]driftless_context_comment (action)POST|GET|PATCH /comments
A comment points at a topic / record / card — it carries no governance and resolves into an edit (open → resolved → wont_fix).

What is fast by default

The matrix encodes one rule: the interactive default never ships a heavy body.
  • Lists and search default to summary (an index row) and are bounded (top 5 search, top 40 list).
  • Match-files and retrieve default to brief — the durable why, not the full content — and are bounded drifted-first (top 10).
  • A single context get <slug> defaults to full, because you named the one topic you want.
  • full everywhere else is an explicit opt-in (--full is never the default); pair it with a small limit.
  • Records (collection + broker) paginate by keyset; broker output is hard-capped.
Latency and payload targets per workflow live in budgets.md; the view/pagination vocabulary in views.md; how a perf claim is accepted in gates.md.