Closes#1218.
When the user invokes `ccs <profile> agents` (and other Claude subcommands
like `mcp`, `doctor`, `plugin`, ...), CCS was unconditionally injecting
session-only Claude flags (`--append-system-prompt`, `--disallowedTools`,
`--settings`, official-channels plugin specs) and forwarding the
`DISABLE_TELEMETRY=1` env var from profile settings. Each of those
either errored out the subcommand (`error: unknown option
'--append-system-prompt'`) or silently flipped Claude into
non-interactive list mode, so the new `claude agents` agent view never
opened under CCS.
Add a small `claude-subcommand-detector` that recognizes the documented
Claude subcommand set after skipping known value-taking flags, then have
the three steering-prompt injectors (websearch, image-analysis, browser),
the cliproxy and settings launchers, and the official-channels plan
short-circuit when a subcommand invocation is detected. Also strip
`DISABLE_TELEMETRY` from the spawned env only for subcommand
invocations — upstream Claude Code uses that var as a kill switch for
the subcommand TUIs, and the user's telemetry preference still applies
to every normal interactive session.
Verified end-to-end against `ccs glm agents` and `ccs ck agents`: the
agent view opens correctly, no `unknown option` error, and all 1938
existing tests pass.
The normalizers extraction in #1168 introduced a circular module-load
chain that crashed the built CLI:
ccs.js -> errors -> services/logging -> log-config -> config-loader-facade
-> unified-config-loader -> loader/normalizers -> channels/official-channels-runtime
-> utils/claude-detector -> utils/shell-executor -> utils/websearch-manager
-> utils/websearch/hook-env -> utils/websearch/trace
-> services/logging (mid-load - createLogger undefined) -> CRASH
normalizers only needed three pure helpers from official-channels-runtime
(isOfficialChannelId, normalizeOfficialChannelIds, resolveLegacyDiscord
Selection) but pulled in the whole file's claude-detector / shell-
executor / websearch chain.
Fix: extract those three helpers + OFFICIAL_CHANNEL_IDS into a leaf
module src/channels/official-channels-ids.ts with no runtime deps.
Update normalizers.ts and config-getters.ts to import from the leaf.
official-channels-runtime.ts re-exports from the leaf for callers that
still want the bundled API.
Also revert the over-eager facade-import migration in
src/utils/config-manager.ts (it was importing from config-loader-facade
which re-exports from itself, creating a direct cycle).
Verified: dist/ccs.js boots cleanly (--version returns); test:all
1828/1828 pass; typecheck/lint/format clean.
Refs #1135
Issue #1161. Sweeps 127 files to import from
src/config/config-loader-facade.ts instead of unified-config-loader or
utils/config-manager directly.
WRITE callers (32 files): replaced raw saveUnifiedConfig /
mutateUnifiedConfig / updateUnifiedConfig calls with the facade's
cache-coherent wrappers saveConfig / mutateConfig / updateConfig. This
fixes a latent stale-cache window where direct writes through the
underlying loader bypassed the facade's memoization.
READ callers (95 files): mechanical import-path migration only —
function names unchanged because the facade re-exports them. No
behavior change.
Also updated:
- tests/unit/utils/browser/browser-setup.test.ts (DI interface rename)
- src/management/checks/image-analysis-check.ts (dynamic import rename)
- src/web-server/health-service.ts (dynamic require rename)
- src/ccs.ts (path prefix fix from sweep script)
After sweep: zero raw write callers remain outside src/config/. Direct
imports of config-manager remain only for symbols not in the facade
(getConfigPath, getCcsDirSource, etc). Behavior unchanged; full suite
passes 1824/1824.
Out of scope: switching loadOrCreateUnifiedConfig() callers to
getCachedConfig() — needs per-callsite cache-safety analysis. Tracked
as follow-up.
Refs #1161
- update CLI, API, route, and dashboard surfaces to recognize the Codex runtime target
- normalize persisted codex targets back to claude so runtime-only behavior stays truthful
- add regression coverage for help text, route parsing, and profile storage normalization
Refs #773
Add a 4096-character cap before persisting official channel tokens, map that validation failure to HTTP 400 in the dashboard route, and cover both paths with regression tests.
- replace the Discord-only config with multi-channel official channels selection
- add Telegram token handling and iMessage platform-aware runtime gating
- expand CLI, dashboard, and tests for Telegram, Discord, and iMessage
Refs #783
- add runtime injection for official Discord Channels on eligible native Claude sessions
- add CLI and dashboard configuration plus secure token handling
- add tests for launch planning, token sync, and config routing
Refs #783