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
Each target adapter (claude, codex, droid) now emits dispatch on child
spawn and respond on child exit with latencyMs. instance-manager emits
lifecycle events for instance create / start / stop so multi-instance flows
are traceable per requestId.
Refs #1141, #1138
Claude Code's marketplace auto-update uses a three-step atomic rename:
clone to <name>.staging → rename old dir to <name>.bak → rename staging
to the final name. On Windows, EPERM errors can interrupt the rename-dance
and leave a <name>.staging directory permanently on disk.
CCS scanned physical directories to discover marketplaces, so a lingering
.staging directory was registered as a bare { installLocation } entry in
known_marketplaces.json. Claude Code's Zod schema requires each entry to
also have `source` and `lastUpdated` fields, so the corrupt entry caused
the /plugin command to throw a validation error.
Fix (two layers of defence):
- discoverMarketplaceEntries: skip any directory whose name starts with
'.' or ends with '.staging'. This filters all hidden dirs including
.staging and .bak left behind by interrupted rename operations.
- buildMarketplaceRegistryContent: invert the loop direction. Instead of
iterating discoveredEntries and adding to the registry (which could
introduce bare entries for disk-only directories with no registry
record), iterate the merged registry and only keep entries that also
exist on disk. Disk-only directories are now silently ignored.
Adds two regression tests: one for .staging pollution, one for orphan
registry entries whose physical directory has been removed.
- serialize deleteInstance with the same profile and plugin-layout locks as ensure
- lock non-account marketplace normalization paths and ignore .locks as an instance source
- detach verified shared symlinks when a profile is reopened as bare
- prune stale marketplace entries whose payload directories no longer exist
- add regressions for bare/non-bare transitions and stale registry recovery
- keep bare and non-bare marketplace normalization inside the plugin-layout lock
- warn when malformed registry sources are skipped during reconciliation
- add regression coverage for cross-instance refresh metadata and legacy layout upgrade
- Add --bare flag to `ccs auth create` to skip shared symlinks
(commands/, skills/, agents/, settings.json). Bare profiles are
clean instances without ClaudeKit or other global extensions.
`ccs sync` respects bare flag and skips re-linking.
- Add MCP server sync from global ~/.claude.json to instances.
Claude Code stores MCP config in ~/.claude.json (not settings.json),
which was invisible to CCS profiles using CLAUDE_CONFIG_DIR isolation.
Selective copy of mcpServers key only (not OAuth sessions/caches).
`ccs sync` refreshes MCP servers across all non-bare instances.
Closes#691Closes#692
- Extract shared _resolveCcsDir() to prevent getCcsDir/getCcsDirSource divergence
- Replace all hardcoded ~/.ccs/ and ~/.claude/ in recovery-manager.ts with
dynamic paths from instance properties (ccsDir, claudeDir, sharedDir, etc.)
- Add cloud sync detection for CCS_HOME env var (parity with CCS_DIR/--config-dir)
- Cache getSessionSecretPath() in local var in auth-middleware.ts
- Cache getCacheDir() in local var in disk-cache.ts ensureCacheDir()
Allow users to relocate the entire ~/.ccs/ directory via CCS_DIR env var
or --config-dir CLI flag. Precedence: --config-dir > CCS_DIR > CCS_HOME > default.
Includes cloud sync path detection warning and doctor diagnostics.
Closes#507
- Update checkAuthCodePorts() to filter from CLIPROXY_PROFILES
- Update header comment to list all OAuth ports including Claude
- Addresses PR #384 review round 3
- Remove claude from PLUS_ONLY_PROVIDERS (Claude works with normal CLIProxy too)
- Fix color inconsistency: use #D97757 to match SVG brand color
- Add iflow to checkAuthCodePorts (pre-existing issue, fixed opportunistically)
Add Claude as a first-class OAuth provider in CCS CLI and dashboard.
Backend support already exists in CLIProxyAPIPlus (port 54545).
Changes:
- Add 'claude' to CLIProxyProvider type and profile detector
- Add Claude OAuth config (port 54545, --anthropic-login flag)
- Add Claude to oauth-port-diagnostics flow types
- Add Claude token discovery prefixes (claude-, anthropic-)
- Add Claude model catalog (Opus 4.5, Sonnet 4.5/4, Haiku 4.5)
- Add Claude logo and provider display name
- Update variant config types and adapters
Closes#380
Fix test isolation in symlink managers and checkers to prevent tests
from touching user's real ~/.ccs/ and ~/.claude/ directories.
Files fixed:
- src/api/services/profile-writer.ts - use getCcsDir()
- src/management/checks/symlink-check.ts - use functions instead of
module-level constants
- src/utils/claude-dir-installer.ts - use getCcsDir() for CCS paths
- src/utils/claude-symlink-manager.ts - use getCcsHome()/getCcsDir()