docs(codex): document runtime target support

- document the ccs-codex and ccsx runtime aliases

- capture the supported v1 matrix and bridge behavior for native Codex runs

Refs #773
This commit is contained in:
Tam Nhu Tran
2026-03-29 13:14:15 -04:00
parent f9c1238483
commit da4bb29fd7
3 changed files with 175 additions and 11 deletions
+30 -2
View File
@@ -201,17 +201,21 @@ Built-in Droid runtime aliases are installed with the package:
```bash ```bash
ccs-droid glm # explicit alias ccs-droid glm # explicit alias
ccsd glm # legacy shortcut ccsd glm # legacy shortcut
ccs-codex # explicit Codex alias
ccsx # short Codex alias
``` ```
Need additional alias names? First create the matching symlink or another launcher that Need additional alias names? First create the matching symlink or another launcher that
preserves the invoked basename, then map that name with `CCS_TARGET_ALIASES` (preferred) or legacy preserves the invoked basename, then map that name with `CCS_TARGET_ALIASES` (preferred) or legacy
`CCS_DROID_ALIASES`: target-specific env vars:
```bash ```bash
ln -s "$(command -v ccs)" /usr/local/bin/mydroid ln -s "$(command -v ccs)" /usr/local/bin/mydroid
CCS_TARGET_ALIASES='droid=mydroid' ln -s "$(command -v ccs)" /usr/local/bin/mycodex
CCS_TARGET_ALIASES='droid=mydroid;codex=mycodex'
# Legacy fallback still supported: # Legacy fallback still supported:
CCS_DROID_ALIASES='mydroid' CCS_DROID_ALIASES='mydroid'
CCS_CODEX_ALIASES='mycodex'
``` ```
For Factory BYOK compatibility, CCS also stores a per-profile Droid provider hint For Factory BYOK compatibility, CCS also stores a per-profile Droid provider hint
@@ -239,6 +243,30 @@ flag and warns about duplicates.
Dashboard parity: `ccs config` -> `Factory Droid` Dashboard parity: `ccs config` -> `Factory Droid`
### Native Codex Runtime (runtime-only in v1)
CCS can launch native Codex as a first-class runtime target without rewriting your
`~/.codex/config.toml` on every run. CCS uses transient `codex -c key=value` overrides for
Codex-routed sessions and leaves your existing Codex home/config in place.
Supported in v1:
```bash
ccs --target codex # native Codex default session
ccs-codex # explicit Codex alias
ccsx # short alias
ccs codex --target codex # built-in CLIProxy Codex on native Codex
ccs api create codex-api --cliproxy-provider codex
ccs codex-api --target codex # Codex bridge profile on native Codex
```
Not supported in v1:
- Claude account profiles on Codex target
- Copilot profiles on Codex target
- Generic API profiles that are not Codex-routed CLIProxy bridges
- Non-Codex CLIProxy providers on Codex target
- Composite CLIProxy variants on Codex target
### Per-Profile Target Defaults ### Per-Profile Target Defaults
You can pin a default target (`claude` or `droid`) per profile: You can pin a default target (`claude` or `droid`) per profile:
+21 -3
View File
@@ -1,8 +1,8 @@
# CCS Codebase Summary # CCS Codebase Summary
Last Updated: 2026-03-24 Last Updated: 2026-03-28
Comprehensive overview of the modularized CCS codebase structure following the Phase 9 modularization effort (Settings, Analytics, Auth Monitor splits + Test Infrastructure), v7.1 Remote CLIProxy feature, v7.2 Kiro + GitHub Copilot (ghcp) OAuth providers, v7.14 Hybrid Quota Management, v7.34 Image Analysis Hook, account-context validation hardening, and Official Claude Channels runtime support. Comprehensive overview of the modularized CCS codebase structure following the Phase 9 modularization effort (Settings, Analytics, Auth Monitor splits + Test Infrastructure), v7.1 Remote CLIProxy feature, v7.2 Kiro + GitHub Copilot (ghcp) OAuth providers, v7.14 Hybrid Quota Management, v7.34 Image Analysis Hook, account-context validation hardening, Official Claude Channels runtime support, and native Codex runtime target support.
## Repository Structure ## Repository Structure
@@ -35,6 +35,9 @@ The main CLI is organized into domain-specific modules with barrel exports.
``` ```
src/ src/
├── ccs.ts # Main entry point & profile execution flow ├── ccs.ts # Main entry point & profile execution flow
├── bin/ # Dedicated runtime entrypoints
│ ├── droid-runtime.ts # argv[0] shim for ccs-droid / ccsd
│ └── codex-runtime.ts # argv[0] shim for ccs-codex / ccsx
├── types/ # TypeScript type definitions ├── types/ # TypeScript type definitions
│ ├── index.ts # Barrel export (aggregates all types) │ ├── index.ts # Barrel export (aggregates all types)
│ ├── cli.ts # CLI types (ParsedArgs, ExitCode) │ ├── cli.ts # CLI types (ParsedArgs, ExitCode)
@@ -67,8 +70,12 @@ src/
│ ├── target-adapter.ts # TargetAdapter interface contract │ ├── target-adapter.ts # TargetAdapter interface contract
│ ├── target-registry.ts # Registry for runtime adapter lookup │ ├── target-registry.ts # Registry for runtime adapter lookup
│ ├── target-resolver.ts # Resolution logic (flag > config > argv[0]) │ ├── target-resolver.ts # Resolution logic (flag > config > argv[0])
│ ├── target-metadata.ts # Runtime vs persisted target metadata and alias lists
│ ├── target-runtime-compatibility.ts # Guardrails for target/profile combinations
│ ├── claude-adapter.ts # Claude Code CLI implementation │ ├── claude-adapter.ts # Claude Code CLI implementation
│ ├── droid-adapter.ts # Factory Droid CLI implementation │ ├── droid-adapter.ts # Factory Droid CLI implementation
│ ├── codex-adapter.ts # Native Codex CLI implementation
│ ├── codex-detector.ts # Codex binary detection and capability probing
│ ├── droid-detector.ts # Droid binary detection & version checks │ ├── droid-detector.ts # Droid binary detection & version checks
│ └── droid-config-manager.ts # ~/.factory/settings.json management │ └── droid-config-manager.ts # ~/.factory/settings.json management
@@ -203,7 +210,7 @@ src/
| Category | Directories | Purpose | | Category | Directories | Purpose |
|----------|-------------|---------| |----------|-------------|---------|
| Core | `commands/`, `errors/` | CLI commands, error handling | | Core | `commands/`, `errors/` | CLI commands, error handling |
| Targets | `targets/` | Multi-CLI adapter pattern (Claude Code, Factory Droid, extensible) | | Targets | `bin/`, `targets/` | Multi-CLI adapter pattern (Claude Code, Factory Droid, Codex CLI, extensible) |
| Auth | `auth/`, `cliproxy/auth/` | Authentication across providers | | Auth | `auth/`, `cliproxy/auth/` | Authentication across providers |
| Config | `config/`, `types/` | Configuration & type definitions | | Config | `config/`, `types/` | Configuration & type definitions |
| Providers | `cliproxy/`, `copilot/`, `glmt/` | Provider integrations plus retained legacy transformer internals | | Providers | `cliproxy/`, `copilot/`, `glmt/` | Provider integrations plus retained legacy transformer internals |
@@ -238,6 +245,17 @@ src/
- Runtime contract lives in `src/channels/official-channels-runtime.ts` and is consumed from `src/ccs.ts`, `src/commands/config-channels-command.ts`, and `src/web-server/routes/channels-routes.ts`. - Runtime contract lives in `src/channels/official-channels-runtime.ts` and is consumed from `src/ccs.ts`, `src/commands/config-channels-command.ts`, and `src/web-server/routes/channels-routes.ts`.
- Canonical config lives under `channels.*` in `~/.ccs/config.yaml`; legacy `discord_channels.*` remains read-compatible only when canonical fields are absent. - Canonical config lives under `channels.*` in `~/.ccs/config.yaml`; legacy `discord_channels.*` remains read-compatible only when canonical fields are absent.
### Native Codex Runtime Target
- Runtime aliases: `ccs-codex` and `ccsx` resolve through `src/bin/codex-runtime.ts` and `src/targets/target-resolver.ts`.
- Metadata boundary: `src/targets/target-metadata.ts` keeps Codex runtime-only in v1, so persisted default targets remain `claude | droid`.
- Compatibility guardrails: `src/targets/target-runtime-compatibility.ts` centralizes which profile types can execute on Codex.
- Adapter behavior: `src/targets/codex-adapter.ts` and `src/targets/codex-detector.ts` launch native Codex without rewriting `~/.codex/config.toml`; CCS-backed routes use transient `codex -c key=value` overrides and env-key injection.
- Supported Codex flows in v1:
- `default`
- CLIProxy provider `codex`
- settings/API profiles only when they resolve to a Codex CLIProxy bridge
- Telegram and Discord bot tokens are intentionally written into Claude-managed machine state under `~/.claude/channels/<channel>/.env`, unless the official `*_STATE_DIR` environment override redirects that channel elsewhere. - Telegram and Discord bot tokens are intentionally written into Claude-managed machine state under `~/.claude/channels/<channel>/.env`, unless the official `*_STATE_DIR` environment override redirects that channel elsewhere.
- iMessage is tokenless, macOS-only, and still depends on Claude-side plugin install plus OS permissions. - iMessage is tokenless, macOS-only, and still depends on Claude-side plugin install plus OS permissions.
- Auto-enable is gated on Bun availability, verified Claude Code v2.1.80+, verified `claude.ai` auth, native Claude `default/account` sessions, and per-channel setup readiness. - Auto-enable is gated on Bun availability, verified Claude Code v2.1.80+, verified `claude.ai` auth, native Claude `default/account` sessions, and per-channel setup readiness.
+124 -6
View File
@@ -1,6 +1,6 @@
# Target Adapters # Target Adapters
Last Updated: 2026-02-16 Last Updated: 2026-03-28
Detailed documentation of the target adapter pattern and implementations. Detailed documentation of the target adapter pattern and implementations.
@@ -20,8 +20,8 @@ Each CLI target implements the `TargetAdapter` contract:
```typescript ```typescript
export interface TargetAdapter { export interface TargetAdapter {
readonly type: TargetType; // 'claude' | 'droid' readonly type: TargetType; // 'claude' | 'droid' | 'codex'
readonly displayName: string; // "Claude Code" | "Factory Droid" readonly displayName: string; // "Claude Code" | "Factory Droid" | "Codex CLI"
/** Detect if the target CLI binary exists on system */ /** Detect if the target CLI binary exists on system */
detectBinary(): TargetBinaryInfo | null; detectBinary(): TargetBinaryInfo | null;
@@ -30,7 +30,15 @@ export interface TargetAdapter {
prepareCredentials(creds: TargetCredentials): Promise<void>; prepareCredentials(creds: TargetCredentials): Promise<void>;
/** Build spawn arguments for the target CLI */ /** Build spawn arguments for the target CLI */
buildArgs(profile: string, userArgs: string[]): string[]; buildArgs(
profile: string,
userArgs: string[],
options?: {
creds?: TargetCredentials;
profileType?: ProfileType;
binaryInfo?: TargetBinaryInfo;
}
): string[];
/** Build environment variables for the target CLI */ /** Build environment variables for the target CLI */
buildEnv(creds: TargetCredentials, profileType: string): NodeJS.ProcessEnv; buildEnv(creds: TargetCredentials, profileType: string): NodeJS.ProcessEnv;
@@ -46,7 +54,7 @@ export interface TargetAdapter {
### Type Definitions ### Type Definitions
```typescript ```typescript
export type TargetType = 'claude' | 'droid'; export type TargetType = 'claude' | 'droid' | 'codex';
export interface TargetCredentials { export interface TargetCredentials {
baseUrl: string; // API endpoint baseUrl: string; // API endpoint
@@ -59,6 +67,8 @@ export interface TargetCredentials {
export interface TargetBinaryInfo { export interface TargetBinaryInfo {
path: string; // Full path to binary path: string; // Full path to binary
needsShell: boolean; // Windows .cmd/.bat/.ps1? needsShell: boolean; // Windows .cmd/.bat/.ps1?
version?: string; // Optional version string
features?: readonly string[]; // Capability probes
} }
``` ```
@@ -73,8 +83,10 @@ CCS resolves which adapter to use via priority-ordered checks:
``` ```
1. --target flag (CLI argument) — highest priority 1. --target flag (CLI argument) — highest priority
└─ ccs --target droid glm └─ ccs --target droid glm
└─ ccs --target codex
2. Per-profile config (from ~/.ccs/config.yaml or settings.json) 2. Per-profile config (from ~/.ccs/config.yaml or settings.json)
└─ persisted targets are currently only `claude` and `droid`
└─ profiles: └─ profiles:
glm: glm:
target: droid target: droid
@@ -82,6 +94,8 @@ CCS resolves which adapter to use via priority-ordered checks:
3. argv[0] detection (runtime alias pattern) — binary name mapping 3. argv[0] detection (runtime alias pattern) — binary name mapping
└─ ccs-droid (explicit alias) → droid └─ ccs-droid (explicit alias) → droid
└─ ccsd (legacy shortcut) → droid └─ ccsd (legacy shortcut) → droid
└─ ccs-codex (explicit alias) → codex
└─ ccsx (short alias) → codex
└─ ccs (regular command) → default └─ ccs (regular command) → default
4. Fallback: 'claude' — lowest priority 4. Fallback: 'claude' — lowest priority
@@ -105,6 +119,7 @@ export function resolveTargetType(
// 2. Check profile config // 2. Check profile config
if (profileConfig?.target) { if (profileConfig?.target) {
// Persisted targets intentionally exclude runtime-only codex.
return profileConfig.target; return profileConfig.target;
} }
@@ -380,6 +395,103 @@ CCS_TARGET_ALIASES=droid=mydroid
--- ---
## Codex Adapter
### Implementation
The Codex adapter keeps CCS-backed Codex launches transient. It does not rewrite
`~/.codex/config.toml`. Instead it:
- passes through native default Codex sessions unchanged
- probes the installed Codex binary for `--config <key=value>` support
- injects CCS-backed provider credentials through temporary `-c` overrides
- stores the routed API key only in process env via `CCS_CODEX_API_KEY`
```typescript
// src/targets/codex-adapter.ts
export class CodexAdapter implements TargetAdapter {
readonly type: TargetType = 'codex';
readonly displayName = 'Codex CLI';
detectBinary(): TargetBinaryInfo | null {
return getCodexBinaryInfo();
}
async prepareCredentials(_creds: TargetCredentials): Promise<void> {
// No file writes. Codex uses transient -c overrides plus env_key injection.
}
buildArgs(profile: string, userArgs: string[], options?: BuildOptions): string[] {
if ((options?.profileType || 'default') === 'default') {
return userArgs;
}
if (!codexBinarySupportsConfigOverrides(options?.binaryInfo)) {
throw new Error('Upgrade Codex before using CCS-backed Codex profiles.');
}
return [
'-c',
'model_provider=\"ccs_runtime\"',
'-c',
'model_providers.ccs_runtime.base_url=\"http://127.0.0.1:8317/api/provider/codex\"',
'-c',
'model_providers.ccs_runtime.env_key=\"CCS_CODEX_API_KEY\"',
'-c',
'model_providers.ccs_runtime.wire_api=\"responses\"',
...userArgs,
];
}
buildEnv(creds: TargetCredentials, profileType: string): NodeJS.ProcessEnv {
const env = { ...stripAnthropicEnv(process.env) };
if (profileType !== 'default') {
env['CCS_CODEX_API_KEY'] = creds.apiKey;
}
return env;
}
}
```
### Support Matrix
Codex is a real runtime target, but it is intentionally narrower than Claude or Droid in v1:
| Profile Type | Codex Target | Notes |
|--------------|--------------|-------|
| `default` | Yes | Uses existing native Codex auth/config |
| `cliproxy` provider=`codex` | Yes | Routed through CLIProxy Codex Responses bridge |
| `cliproxy` composite | No | Not proven native-Codex-safe |
| `settings` with Codex bridge metadata | Yes | Only when the API profile resolves to a Codex CLIProxy bridge |
| `settings` generic API profile | No | Claude/Droid only |
| `account` | No | Claude-only account isolation concept |
| `copilot` | No | Not a native Codex provider path |
### Runtime Alias Pattern
```bash
# Built-in package bin aliases
ccs-codex
→ Target: codex (forced by runtime alias)
ccsx codex
→ Target: codex (forced by runtime alias)
→ codex ...args
```
Runtime aliases can also be extended with `CCS_TARGET_ALIASES` or legacy
`CCS_CODEX_ALIASES` after creating a matching launcher:
```bash
ln -s /path/to/ccs /path/to/mycodex
CCS_TARGET_ALIASES='codex=mycodex'
# Legacy fallback:
CCS_CODEX_ALIASES='mycodex'
```
---
## Registry and Lookup ## Registry and Lookup
The target registry is a simple map-based store for adapters: The target registry is a simple map-based store for adapters:
@@ -415,6 +527,7 @@ At startup, adapters self-register:
registerTarget(new ClaudeAdapter()); registerTarget(new ClaudeAdapter());
registerTarget(new DroidAdapter()); registerTarget(new DroidAdapter());
registerTarget(new CodexAdapter());
``` ```
--- ---
@@ -522,7 +635,7 @@ export class MyAiAdapter implements TargetAdapter {
```typescript ```typescript
// src/targets/target-adapter.ts // src/targets/target-adapter.ts
export type TargetType = 'claude' | 'droid' | 'myai'; export type TargetType = 'claude' | 'droid' | 'codex' | 'myai';
``` ```
### 3. Register in ccs.ts ### 3. Register in ccs.ts
@@ -621,8 +734,13 @@ ccs --target claude help
# Test Droid adapter (if installed) # Test Droid adapter (if installed)
ccs --target droid help ccs --target droid help
# Test Codex adapter (if installed)
ccs --target codex
ccs-codex
# Test argv[0] detection # Test argv[0] detection
ccs-droid help ccs-droid help
ccsx
``` ```
--- ---