-
Notifications
You must be signed in to change notification settings - Fork 0
Command Model
contractVersion: 1.0.1
How commands dispatch. UI-agnostic. Acts on the main session only. Orthogonal to the attached SM.
The Command contract (shape, cardinality, registration) lives in contracts/Commands. This page is the dispatch model.
A command is a named, parameterized action issued by the user (or by another extension through the Host API) and handled by a registered handler.
Examples that ship bundled (see Bundled commands): /model, /provider, /params, /save, /resume, /reload, /tools.
Commands are issued through any UI — TUI, web, scripts, CI invocation. The shape of the command does not depend on which UI raised it.
sequenceDiagram
autonumber
actor User
participant UI
participant Core as Command bus
participant Handler
participant Bus as Event bus
User->>UI: types /model gpt-5
UI->>Core: "dispatch('model', ['gpt-5'])"
Core->>Handler: invoke(args, sessionAccessor)
Handler-->>Core: result
Core->>Bus: CommandDispatched + CommandResulted
Core-->>UI: result
UI->>User: render
Core resolves the command name through the command registry, invokes the handler with a Host API context, and publishes CommandDispatched and CommandResulted events.
If the command returns a result, the UI renders it. If it triggers an interaction (for example, a disambiguation Select), the request fans out through active interactors via the Interaction Protocol.
A command sees the main session — the session the user is currently in. It does not see another session; it does not see an SM's private state; it does not see another extension's state slot directly (it uses the Host API, which mediates).
Practical consequences:
- A command that mutates session state acquires a session-accessor lease. Leases serialize mutations so two concurrent commands cannot corrupt state.
- A command does not trigger a turn. Turns run the message loop; commands do not. A command that needs an LLM response does so by invoking a dedicated command-facing API — it does not hijack the turn.
- A command can run concurrently with a turn. It must not block the event loop. Long-running commands should yield via the Host API cancellation token.
This is an invariant.
- Commands do not gate the SM. Issuing a command does not transition the SM, change its approval posture, or force a workflow fork.
-
The SM does not gate commands. The SM cannot deny
/modelor/savebecause the SM does not decide what the user can do outside the turn.
An SM that wants to constrain commands does so by cooperating with the UI extension (e.g., hiding commands in its theme) — not by vetoing through core.
Rationale: commands are user escape hatches. If the SM could lock the user out of /save or /resume, stud-cli would be an unusable cage. The SM owns the turn; the user owns the session.
See Extensibility Boundary and the locked decision in the plan's Architectural decisions table.
Commands do not bypass the security stack.
- A command that runs a tool passes through the normal Tool Approvals path: SM → mode gate → interactor.
- A command that reads env values uses the env provider — it does not have bulk-read access. See LLM Context Isolation.
- A command that switches provider or model passes through the Capability Negotiation fail-fast.
/model foorejects iffoolacks a capability the current session depends on. - Destructive commands (e.g.,
/forget, if added) request aConfirminteraction unless an SM is attached.
Commands are themselves extensions. They load through the normal validation pipeline with per-command severity defaulting to warn (a missing non-critical command degrades the session; it does not kill it). Critical commands may opt into hard-fail; this is documented per-command in contracts/Commands.
Commands have flat names. The project scope can override or disable a command with the same name as a global or bundled command. Name collisions across scopes resolve by Configuration Scopes rules — later layer wins.
Shadowing is the user's responsibility. The /commands inspection command (if bundled) reveals origin. See also the tool-shadowing risk for the analogous tool case.
Commands emit:
-
CommandDispatched{name, args, correlationId, origin}before invocation. -
CommandResulted{name, outcome, correlationId}after.
These rides the event bus as projection. Interested UIs re-render; loggers log; audit records the invocation. Nothing controls flow by subscribing to these events.
Some commands emit additional kind-specific events to advertise their effect:
-
/paramsemitsParamsChanged{paramPath, sourceLayer, redactedDelta, correlationId}after the override lands. Payload is a redacted delta (path + shape-marker), never a raw value. Mutation profile: writes session-runtime params bag; does not write the manifest. See contracts/Commands § /params mutation profile. -
/model,/provider,/sm attach,/sm detachemit their own kind-specific events documented on each command's bundled page.
| Place | What it covers |
|---|---|
| contracts/Commands | The Command contract shape, cardinality, state slot, validation severity |
| Bundled commands | Bundled commands: /model, /save, /resume, /reload, /provider, /tools, … |
| flows/Hot Model Switch |
/model mid-session with capability check |
| flows/Capability Mismatch Switch |
/model or /provider that fails fast |
- UI-agnostic command dispatch model. Commands act on the main session only and are orthogonal to the attached SM. Mutation profile: each command declares its session-state effect; the dispatcher serializes commands FIFO per session.
- Two events on every dispatch:
CommandDispatched(pre-invocation) andCommandResulted(post-invocation). Both are projection events on the bus; control flow does not ride them. - Identity and shadowing: flat names; project-scope shadowing legal; collisions within a single layer are validation errors.
- Security posture: commands do not bypass tool approvals, env-isolation, or capability negotiation; destructive commands request confirmation interactions when no SM is attached.
- Bundled-commands example list adds
/params. Mutation profile documented on contracts/Commands § /params mutation profile: writes session-runtime params bag, does not write the manifest, refused while a stage is mid-Act. - New "Mutation events" subsection: documents
ParamsChanged{paramPath, sourceLayer, redactedDelta, correlationId}emitted by/paramsand--paraminvocations. Payload is a redacted delta — never raw values — per the Audit Trail redaction pipeline. - No changes to dispatch ordering, security posture, or shadowing semantics.
- Execution Model
- Message Loop
- Concurrency and Cancellation
- Error Model
- Event and Command Ordering
- Event Bus
- Command Model
- Interaction Protocol
- Hook Taxonomy
- Host API
- Extension Lifecycle
- Env Provider
- Prompt Registry
- Resource Registry
- Session Lifecycle
- Session Manifest
- Persistence and Recovery
- Stage Executions
- Subagent Sessions
- Contract Pattern
- Versioning and Compatibility
- Deprecation Policy
- Capability Negotiation
- Dependency Resolution
- Validation Pipeline
- Cardinality and Activation
- Extension State
- Conformance and Testing
- Providers
- Provider Params
- Tools
- Hooks
- UI
- Loggers
- State Machines
- SM Stage Lifecycle
- Stage Definitions
- Commands
- Session Store
- Context Providers
- Settings Shape
- Trust Model
- Project Trust
- Extension Isolation
- Extension Integrity
- LLM Context Isolation
- Secrets Hygiene
- Security Modes
- Tool Approvals
- MCP Trust
- Sandboxing
- Configuration Scopes
- Project Root
- Extension Discovery
- Extension Installation
- Extension Reloading
- Headless and Interactor
- Determinism and Ordering
- Launch Arguments
- Network Policy
- Platform Integration
Tools
UI
Session Stores
Loggers
Providers
Hooks
Context Providers
Commands
- First Run
- Default Chat
- Tool Call Cycle
- Hook Interception
- Guard Deny Reproposal
- State Machine Workflow
- SM Stage Retry
- Hot Model Switch
- Capability Mismatch Switch
- Session Resume
- Session Resume Drift
- Approval and Auth
- Interaction Timeout
- Headless Run
- Parallel Tool Approvals
- Subagent Delegation
- Scope Layering
- Project First-Run Trust
- Reload Mid-Turn
- Compaction Warning
- MCP Remote Tool Call
- MCP Prompt Consume
- MCP Resource Bind
- MCP Reconnect