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
ccs-droid glm # explicit alias
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
preserves the invoked basename, then map that name with `CCS_TARGET_ALIASES` (preferred) or legacy
`CCS_DROID_ALIASES`:
target-specific env vars:
```bash
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:
CCS_DROID_ALIASES='mydroid'
CCS_CODEX_ALIASES='mycodex'
```
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`
### 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
You can pin a default target (`claude` or `droid`) per profile:
+21 -3
View File
@@ -1,8 +1,8 @@
# 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
@@ -35,6 +35,9 @@ The main CLI is organized into domain-specific modules with barrel exports.
```
src/
├── 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
│ ├── index.ts # Barrel export (aggregates all types)
│ ├── cli.ts # CLI types (ParsedArgs, ExitCode)
@@ -67,8 +70,12 @@ src/
│ ├── target-adapter.ts # TargetAdapter interface contract
│ ├── target-registry.ts # Registry for runtime adapter lookup
│ ├── 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
│ ├── 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-config-manager.ts # ~/.factory/settings.json management
@@ -203,7 +210,7 @@ src/
| Category | Directories | Purpose |
|----------|-------------|---------|
| 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 |
| Config | `config/`, `types/` | Configuration & type definitions |
| 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`.
- 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.
- 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.
+124 -6
View File
@@ -1,6 +1,6 @@
# Target Adapters
Last Updated: 2026-02-16
Last Updated: 2026-03-28
Detailed documentation of the target adapter pattern and implementations.
@@ -20,8 +20,8 @@ Each CLI target implements the `TargetAdapter` contract:
```typescript
export interface TargetAdapter {
readonly type: TargetType; // 'claude' | 'droid'
readonly displayName: string; // "Claude Code" | "Factory Droid"
readonly type: TargetType; // 'claude' | 'droid' | 'codex'
readonly displayName: string; // "Claude Code" | "Factory Droid" | "Codex CLI"
/** Detect if the target CLI binary exists on system */
detectBinary(): TargetBinaryInfo | null;
@@ -30,7 +30,15 @@ export interface TargetAdapter {
prepareCredentials(creds: TargetCredentials): Promise<void>;
/** 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 */
buildEnv(creds: TargetCredentials, profileType: string): NodeJS.ProcessEnv;
@@ -46,7 +54,7 @@ export interface TargetAdapter {
### Type Definitions
```typescript
export type TargetType = 'claude' | 'droid';
export type TargetType = 'claude' | 'droid' | 'codex';
export interface TargetCredentials {
baseUrl: string; // API endpoint
@@ -59,6 +67,8 @@ export interface TargetCredentials {
export interface TargetBinaryInfo {
path: string; // Full path to binary
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
└─ ccs --target droid glm
└─ ccs --target codex
2. Per-profile config (from ~/.ccs/config.yaml or settings.json)
└─ persisted targets are currently only `claude` and `droid`
└─ profiles:
glm:
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
└─ ccs-droid (explicit alias) → droid
└─ ccsd (legacy shortcut) → droid
└─ ccs-codex (explicit alias) → codex
└─ ccsx (short alias) → codex
└─ ccs (regular command) → default
4. Fallback: 'claude' — lowest priority
@@ -105,6 +119,7 @@ export function resolveTargetType(
// 2. Check profile config
if (profileConfig?.target) {
// Persisted targets intentionally exclude runtime-only codex.
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
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 DroidAdapter());
registerTarget(new CodexAdapter());
```
---
@@ -522,7 +635,7 @@ export class MyAiAdapter implements TargetAdapter {
```typescript
// src/targets/target-adapter.ts
export type TargetType = 'claude' | 'droid' | 'myai';
export type TargetType = 'claude' | 'droid' | 'codex' | 'myai';
```
### 3. Register in ccs.ts
@@ -621,8 +734,13 @@ ccs --target claude help
# Test Droid adapter (if installed)
ccs --target droid help
# Test Codex adapter (if installed)
ccs --target codex
ccs-codex
# Test argv[0] detection
ccs-droid help
ccsx
```
---