Files
ccs/docs/system-architecture/target-adapters.md
T

7.7 KiB

Target Adapters

Target adapters are the last-mile boundary between CCS profile resolution and a supported CLI runtime. Profile discovery and credential resolution happen before this boundary; the selected adapter owns binary detection, target-native credential delivery, argument and environment construction, and child-process execution.

Related architecture:

Contract

The canonical interface and data types live in src/targets/target-adapter.ts. Each adapter must:

  1. detect its runtime binary without changing user configuration;
  2. reject unsupported profile types before launch;
  3. prepare only the target-owned configuration needed for the launch;
  4. construct an argument vector and environment without exposing credentials in arguments;
  5. spawn the target with inherited stdio and forward process signals.

The registry in src/targets/target-registry.ts maps a target type to its adapter. Target names, built-in aliases, legacy alias environment variables, and persistence eligibility are centralized in src/targets/target-metadata.ts.

Do not duplicate the TypeScript interface in this guide. Interface signatures and credential fields change with runtime requirements; the source files are the contract checked by the compiler.

Target Resolution

src/targets/target-resolver.ts selects the runtime in this order:

  1. --target <name> or --target=<name>; if repeated, the last flag wins.
  2. A trusted package runtime entrypoint identified by CCS_INTERNAL_ENTRY_TARGET.
  3. The invoked binary name, including built-in or configured aliases.
  4. A persisted per-profile target.
  5. claude.

All --target flags are removed before the remaining arguments reach the runtime. Parsing stops at the -- option terminator.

The built-in runtime aliases are derived from target metadata:

Target Built-in aliases
Claude Code Base ccs command
Factory Droid ccs-droid, ccsd
Codex CLI ccs-codex, ccsx, ccsxp

Custom aliases use CCS_TARGET_ALIASES with entries such as droid=team-droid;codex=team-codex. The target-specific legacy environment variables remain compatibility inputs. Alias values are validated and cannot replace reserved package binary names.

Runtime Compatibility

Adapter-level checks are deliberately conservative. Flow-specific compatibility is evaluated in src/targets/target-runtime-compatibility.ts, which has the provider and bridge context needed for an accurate decision.

Profile flow Claude Droid Codex
Native default Supported Conditional: requires resolved ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN Supported
Settings/API profile Supported Supported Codex CLIProxy bridge only
CLIProxy profile Supported Supported Non-composite codex provider only
Claude account Supported Not supported Not supported
Copilot Supported Not supported Not supported
Cursor local proxy Supported Not supported Not supported

When changing compatibility, update both the runtime evaluator and its focused tests. The authoritative coverage is in tests/unit/targets/target-runtime-compatibility.test.ts.

The compatibility evaluator accepts Droid's native-default flow, but adapter preparation still validates the resolved credentials. A default Droid launch cannot proceed without both a non-empty base URL and auth token.

Credential and Configuration Boundaries

Claude Code

src/targets/claude-adapter.ts delivers resolved provider values through the child environment. Native account and default launches remove stale Anthropic routing variables before execution. Browser and WebSearch launch preparation may add runtime-specific arguments and environment values.

The adapter does not persist provider credentials to Claude settings.

Factory Droid

src/targets/droid-adapter.ts validates the resolved base URL and token, then delegates the target-owned write to src/targets/droid-config-manager.ts. That manager updates the CCS custom model and active model in Factory settings. The adapter passes user arguments through; it does not inject a -m selector.

Factory settings are a persistent user-owned surface. Writes must preserve unrelated settings and use the configuration manager rather than direct JSON replacement.

Codex CLI

src/targets/codex-adapter.ts keeps normal CCS-backed launches transient:

  • native default sessions keep native Codex authentication and configuration;
  • CCS-backed sessions use -c key=value overrides for a Responses-compatible runtime provider;
  • the resolved API key is supplied through the provider's environment key, not on the command line;
  • stale Anthropic and nested Codex-session variables are removed before spawn.

The ccsxp shortcut is the explicit exception. It may repair the dedicated cliproxy provider block in the active Codex configuration through src/targets/codex-cliproxy-provider-config.ts. That repair preserves a valid custom base URL and the configured environment-key name. General Codex launches must not rewrite config.toml.

Execution Invariants

The dispatcher owns the order of operations:

  1. parse CCS-owned arguments and resolve the target;
  2. resolve the profile and provider credentials;
  3. evaluate target/profile/provider compatibility;
  4. detect the target binary;
  5. call prepareCredentials;
  6. build target arguments and environment;
  7. execute the child runtime.

Flow implementations live under src/dispatcher/flows/. Shared target execution logic lives in src/dispatcher/target-executor.ts.

All adapters must preserve these invariants:

  • user credentials never appear in documented examples, logs, or spawn arguments;
  • target-owned persistent writes are explicit and scoped;
  • stale routing variables from another runtime do not leak into the child;
  • Windows wrapper handling does not use a shell unless the wrapper format requires one;
  • child signals and exit behavior propagate to the CCS process;
  • binary and launch failures run registered cleanup before exit.

Adding or Changing a Target

Change the smallest complete set:

  1. update TargetType and the adapter contract only when required;
  2. add target metadata and aliases in target-metadata.ts;
  3. implement and register the adapter through src/targets/index.ts;
  4. add flow-aware compatibility rules;
  5. add focused resolver, adapter, compatibility, and integration tests;
  6. update CLI help and dashboard controls if the target becomes user configurable.

Start with these test suites:

Do not describe a target as supported from adapter registration alone. Support requires a compatible profile flow, safe credential delivery, binary detection, execution behavior, and tests for the full combination.