Skip to content

Offer the harness's slash commands in hosted-agent chat #747

Closed

Description

@alexeyzimarev

Hosted-agent chat has no / picker in the server web UI or the desktop app, because nothing tells the UI which slash commands the launched harness exposes. The assumption that this is unknowable turned out to be wrong: every vendor we host can report its command list, and T3 Code already builds its picker this way.

What the harnesses offer

  • Claude Code: in -p --input-format stream-json mode, an initialize control request is answered with commands: [{name, description, argumentHint, aliases}]. Verified on 2.1.258: 373 entries, plugin commands prefixed plugin:command, built-ins like compact, model, clear included. The same response carries the model catalogue with effort levels, the account, and the current permission mode. No API call is made when no user message is sent.
  • ACP vendors (Cursor, Copilot, Gemini, Kiro, OpenCode): session/update with available_commands_update carries [{name, description}]. Cursor is probe-confirmed in docs/acp-probe-findings.md. The daemon already receives it and drops it in AcpEventTranslator.
  • Codex app-server: skills/list, plugin/list and model/list methods. No slash-command list as such; Codex surfaces skills the way T3 Code's $ picker does.

Proposed shape

  1. Daemon reports a per-agent command list after launch (per agent, not per daemon: project-scoped commands differ by cwd). ACP vendors forward the update they already get; Claude runs a headless initialize probe in the launch cwd alongside the PTY start and kills it after the response; Codex calls skills/list.
  2. Server keeps the list on the agent read model and pushes it with the rest of the agent state.
  3. Composer in the web UI and the desktop app shows a / picker and inserts /name on pick. Nothing else changes: hosted Claude already receives chat input as a bracketed paste plus Enter, which is how the daemon submits /exit today, so a typed command should execute as-is. Worth one manual check that a pasted command submits instead of opening the autocomplete popup.

Trap

The Claude probe fires SessionStart hooks, including the kcap plugin's own hook, so it records a phantom session unless KCAP_SKIP=1 is set, as ClaudeCliRunner already does for headless runs. --bare would skip hooks but also drops plugins and their commands.

Reference

T3 Code: apps/server/src/provider/Layers/ClaudeProvider.ts (probe via the Agent SDK with a never-yielding prompt), apps/server/src/provider/Drivers/ClaudeSkills.ts (filesystem skill scan), apps/web/src/components/chat/ChatComposer.tsx (picker merges its own built-ins with the provider list and inserts text on pick).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions