host_features¶
Parse and validate <namespace>:<feature> opt-in subselector tokens that gate emission of host-specific artifacts (Claude hooks, subagents, schedule routines, todo-projection skill, cache-aware CLAUDE.md, etc.). Default emission is unchanged when no subselectors are passed.
The flag is --target-host-features TOKENS (comma-separated). Tokens flow onto manifest["host_features"] and are consumed by feature-gated emitters such as bridge_subagents, hooks_emit, schedule_emit, and instructions_split.
Token → emitter → output at a glance¶
Each validated token routes to one emitter, which writes under .claude/, .codex/, or .goose/.
The figure is the visual companion to the token table below. Generated deterministically from
scripts/gen_api_cluster_figures.py.
Public Surface¶
Parse a CSV string of subselectors into a normalized, deduped list. Empty /None input returns []. Each surviving token is run through validate; the function raises HostFeatureError on malformed input.
Validate a single <ns>:<feature> token against a fixed allow-list. The namespace may itself contain a colon (e.g. bridge:copilot-vscode-to-claude:subagents); validation splits on the last colon to separate the feature from the namespace. Raises HostFeatureError when the token has no colon at all, when the namespace is not one of the enumerated _VALID_NAMESPACES, or when the feature is not in that namespace's _KNOWN_FEATURES set — e.g. claude:not-a-real-feature raises even though it is syntactically well-formed.
Return True iff <namespace>:<feature> is present in the active set. Provided as a convenience membership check; note that, in practice, the feature-gated emitters do not call is_enabled — they perform their own literal membership tests against the active feature list (e.g. mcp_emit.mcp_enabled). It is not a single enforced check point.
Raised by parse_tokens / validate for any malformed token.
Currently Recognized Subselectors¶
| Token | Effect |
|---|---|
bridge:copilot-vscode-to-claude:subagents |
Emit per-agent Claude subagent stubs under <project>/.claude/agents/ (see bridge_subagents). |
bridge:copilot-vscode-to-claude:hooks |
Emit .claude/settings.agentteams.example.json + .claude/hook-guard.sh (see hooks_emit). |
bridge:copilot-vscode-to-claude:cache-split |
Render cache-aware CLAUDE.md (see instructions_split). |
bridge:copilot-vscode-to-claude:schedule |
Emit .claude/schedules.agentteams.json (see schedule_emit). |
bridge:copilot-vscode-to-claude:todo-projection |
Emit .claude/skills/todo-from-plan/SKILL.md (see plan_steps_todo). |
bridge:copilot-vscode-to-claude:parallelize |
Emit .claude/skills/parallelize-plan/SKILL.md — the Claude-only deterministic affordance for deriving fail-safe parallel waves from a plan-steps CSV's depends_on (see parallel_plan). |
claude:sandbox |
Inject a sandbox block into the emitted .claude/settings.hooks.example.json (via the Claude adapter's extra_output_files). The block turns on Claude Code's native OS-level filesystem sandbox (macOS Seatbelt / Linux + WSL2 bubblewrap), confining every Bash command and child-process file write to workspace_write_roots (default ["."] — the project root) with allowUnsandboxedCommands: false. Like the hooks block, it is inert until the operator merges it into their own .claude/settings.json; agentteams never writes settings.json directly. .claude/ is auto-protected even inside the writable root. Usually selected via the privilege_profile: confined/exclusive project-description field, which expands to this token. See Workspace Privilege Scoping. |
claude:mcp |
Emit .claude/mcp-servers.agentteams.json — an inert list of MCP server definitions (deliberately not .mcp.json; credentialed activation is withheld). Only first-party read-only servers scoped to an agent are auto-wired (see mcp_emit). |
bridge:copilot-vscode-to-claude:mcp |
Same .claude/mcp-servers.agentteams.json emission as claude:mcp, via the canonical bridge token (see mcp_emit). |
goose:mcp |
Wire operator-specified mcp_servers[] into Goose recipes as stdio/streamable_http extensions (opt-in; Goose already grants CLI via the developer builtin, so this is never a default). Only first-party read-only servers scoped to an agent are auto-wired; others are surfaced as recipe comments (see mcp_emit). |
codex:mcp |
Splice operator-specified mcp_servers[] into .codex/config.toml's [mcp_servers.*] tables — a real, live config Codex reads to launch servers, so the same first-party/read-only/no-review-required auto-wire bar as goose:mcp applies. Unrelated file content (comments, sandbox/profile settings) is verified unchanged before any write, refusing the write rather than risk data loss if not (see codex_mcp_emit). |
codex:sandbox |
Emit the operator-run .codex/confined-run.example.sh on Linux and macOS (via CodexAdapter.extra_output_files), beside the framework-neutral launcher sandbox/confine-run.sh. It runs codex --sandbox danger-full-access inside the launcher, because Codex's own sandbox cannot nest there; the launcher is the boundary. Inert until the operator runs Codex through it, which generation can't verify. Per-role limits on Codex stay instruction-level only (Codex ignores a spawned agent's sandbox_mode, and every agent shares the writable CODEX_HOME), except under write_policy: "orchestrator-only", where the runner turns on a generated role gate that limits spawned agents to read-only tools. Usually selected via privilege_profile: confined/exclusive, which expands to this token on codex (see CodexAdapter). |
bridge:<src>-to-goose:subagents |
Emit one thin Goose subagent-stub recipe per source agent into .goose/recipes/ when bridging a source team to Goose (reserved/bridge-owned slugs skipped; existing recipes never overwritten — see bridge_subagents_goose). |
bridge:<src>-to-goose:mcp |
Wire selected MCP servers (read from the source team's inert .claude/mcp-servers.agentteams.json) as extensions into the emitted Goose bridge recipe (see mcp_emit). |
Namespace scope: this table lists the tokens — spanning the
claude,bridge:copilot-vscode-to-claude:*,bridge:<src>-to-goose:*,goose, andcodexnamespaces — that have a wired-up effect today.validate/parse_tokensenforce a fixed allow-list —_VALID_NAMESPACESand a per-namespace_KNOWN_FEATURESset — not free-form syntactic well-formedness; a namespace or feature absent from those lists raisesHostFeatureErrorhowever well-formed the token otherwise looks (e.g.claude:not-a-real-featureraises). Tokens whose namespace and feature are both allow-listed but not in this table — e.g. bareclaude:hooksorclaude:subagents— pass validation and simply produce no emission unless an emitter is looking for them.
Genuinely unrecognized tokens do not pass through silently: a namespace or feature absent from the allow-list is rejected at validate() with HostFeatureError and never reaches manifest["host_features"]. "No emission" describes only tokens that clear the allow-list but whose namespace:feature combination no current emitter checks for — emitters perform their own membership test against the active feature list and silently no-op when the flag they look for is absent.
Example¶
agentteams --bridge-refresh \
--target-host-features bridge:copilot-vscode-to-claude:subagents,bridge:copilot-vscode-to-claude:hooks \
--bridge-from /path/to/source-team --output .claude
See also¶
bridge— the host-agnostic bridge that consumesmanifest["host_features"].mcp_detect— the analyze-time MCP-suitability rubric (distinct from the*:mcpemission tokens above).