feat(ccs): add CCS accounts registry configuration - #596
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughSummary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings. WalkthroughAdds CCS provider account/config templates and a hydration flow: new account data and provider settings templates, a hydration script and Nix activation to symlink and hydrate configs into $HOME, cliproxyapi auth path change, Makefile target to restart cliproxyapi, and a Linux-only AMP suppression step in the cliproxyapi start script. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Activation as home.activation.hydrateCcsSettings
participant Dotfiles as dotfilesDir (repo)
participant HydrateScript as config/ccs/hydrate.sh
participant Home as $HOME/.ccs
User->>Activation: activation runs after writeBoundary
Activation->>Dotfiles: prepare hydrate script (replace vars)
Activation->>HydrateScript: execute `${pkgs.bash}/bin/bash ${hydrateScript}`
HydrateScript->>Dotfiles: read templates and `~/.dotfiles/.env`
Dotfiles-->>HydrateScript: provide templates and env
HydrateScript->>Home: write hydrated `config.yaml` and `*.settings.json`
HydrateScript-->>Activation: exit (status logged)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
You do not have enough credits to review this pull request. Please purchase more credits to continue. |
Summary of ChangesHello @shunkakinoki, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request integrates the Claude Code Switcher (CCS) accounts registry into the home-manager configuration. By adding a new Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Add home-manager configuration for CCS (Claude Code Switcher) accounts registry. This fixes the "No accounts configured" error when using ccs agy, gemini, or codex commands. The accounts.json file maps OAuth token files to registered accounts for cliproxy providers. Token files themselves are stored separately in ~/.ccs/cliproxy/auth/ and contain secrets (not managed here). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request adds configuration for CCS to resolve an issue with account configuration. The approach of adding a static JSON file for accounts introduces a security concern by hardcoding personally identifiable information (PII) like your email address. My review provides a suggestion to dynamically generate this configuration file using Nix, which will remove the PII from your repository and make the configuration more maintainable by reusing existing values.
| { | ||
| "version": 1, | ||
| "providers": { | ||
| "agy": { | ||
| "default": "shunkakinoki@gmail.com", | ||
| "accounts": { | ||
| "shunkakinoki@gmail.com": { | ||
| "email": "shunkakinoki@gmail.com", | ||
| "nickname": "shunkakinoki", | ||
| "tokenFile": "antigravity-shunkakinoki_gmail_com.json", | ||
| "createdAt": "2026-01-17T00:00:00.000Z", | ||
| "lastUsedAt": "2026-01-17T00:00:00.000Z", | ||
| "tier": "paid" | ||
| } | ||
| } | ||
| }, | ||
| "gemini": { | ||
| "default": "shunkakinoki@gmail.com", | ||
| "accounts": { | ||
| "shunkakinoki@gmail.com": { | ||
| "email": "shunkakinoki@gmail.com", | ||
| "nickname": "shunkakinoki", | ||
| "tokenFile": "gemini-shunkakinoki@gmail.com-gen-lang-client-0359793614.json", | ||
| "createdAt": "2026-01-12T00:00:00.000Z", | ||
| "lastUsedAt": "2026-01-12T00:00:00.000Z" | ||
| } | ||
| } | ||
| }, | ||
| "codex": { | ||
| "default": "shunkakinoki@gmail.com", | ||
| "accounts": { | ||
| "shunkakinoki@gmail.com": { | ||
| "email": "shunkakinoki@gmail.com", | ||
| "nickname": "shunkakinoki", | ||
| "tokenFile": "codex-shunkakinoki@gmail.com.json", | ||
| "createdAt": "2025-12-18T00:00:00.000Z", | ||
| "lastUsedAt": "2025-12-18T00:00:00.000Z" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Committing a file with hardcoded personal information like your email address and nickname is a security risk, as it exposes Personally Identifiable Information (PII). It also makes the configuration harder to maintain and less portable. It's much better to generate this file dynamically from your Nix configuration, using variables that are already defined elsewhere (like config.accounts.email.accounts.Gmail.address). This file should be removed after applying the suggested change in config/ccs/default.nix.
| { config, ... }: | ||
| { | ||
| # CCS (Claude Code Switcher) account registry | ||
| # Maps OAuth token files to registered accounts for cliproxy providers | ||
| # Token files are stored separately in ~/.ccs/cliproxy/auth/ (not managed here as they contain secrets) | ||
| home.file.".ccs/cliproxy/accounts.json" = { | ||
| source = config.lib.file.mkOutOfStoreSymlink ./accounts.json; | ||
| force = true; | ||
| }; | ||
| } |
There was a problem hiding this comment.
To avoid hardcoding personal information in a static JSON file, you can generate accounts.json dynamically. This makes your configuration more secure and easier to maintain by centralizing personal data. This approach uses builtins.toJSON to create the file content from a Nix attribute set. After this change, you can delete the config/ccs/accounts.json file.
As a further improvement, you could also dynamically construct the tokenFile names to remove the hardcoded email strings from them as well.
{ config, ... }:
let
email = config.accounts.email.accounts.Gmail.address;
# Consider making nickname configurable or deriving it from 'config.accounts.email.accounts.Gmail.realName'
nickname = "shunkakinoki";
accountsData = {
version = 1;
providers = {
agy = {
default = email;
accounts."${email}" = {
inherit email nickname;
tokenFile = "antigravity-shunkakinoki_gmail_com.json";
createdAt = "2026-01-17T00:00:00.000Z";
lastUsedAt = "2026-01-17T00:00:00.000Z";
tier = "paid";
};
};
gemini = {
default = email;
accounts."${email}" = {
inherit email nickname;
tokenFile = "gemini-shunkakinoki@gmail.com-gen-lang-client-0359793614.json";
createdAt = "2026-01-12T00:00:00.000Z";
lastUsedAt = "2026-01-12T00:00:00.000Z";
};
};
codex = {
default = email;
accounts."${email}" = {
inherit email nickname;
tokenFile = "codex-shunkakinoki@gmail.com.json";
createdAt = "2025-12-18T00:00:00.000Z";
lastUsedAt = "2025-12-18T00:00:00.000Z";
};
};
};
};
in
{
# CCS (Claude Code Switcher) account registry
# Maps OAuth token files to registered accounts for cliproxy providers
# Token files are stored separately in ~/.ccs/cliproxy/auth/ (not managed here as they contain secrets)
home.file.".ccs/cliproxy/accounts.json" = {
text = builtins.toJSON accountsData;
force = true;
};
}
Previously auth-dir pointed to ~/.cli-proxy-api which caused cliproxyapi to scan both root-level JSON files AND objectstore/auths/, resulting in duplicate auth file detection (11 files instead of 6). Now points to ~/.cli-proxy-api/objectstore/auths directly. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Mesa DescriptionTL;DRAdds Home Manager configuration for the Claude Code Switcher (CCS) accounts registry and settings, resolving the "No accounts configured" error by symlinking What changed?
Description generated by Mesa. Update settings |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@config/cliproxyapi/config.yaml`:
- Around line 15-16: Update the project documentation to add explicit migration
guidance for legacy auth files referenced by the config key auth-dir (value
"~/.cli-proxy-api/objectstore/auths"): state whether this new directory is only
for fresh setups or required for all users, describe how to detect legacy files
at "~/.cli-proxy-api/" and provide a simple migration command sequence (e.g.,
move/backup into the new objectstore/auths subdirectory), and include any
post-migration steps or troubleshooting notes so users know how to verify the
migrated auth files work with the CLI proxy API.
♻️ Duplicate comments (1)
config/ccs/accounts.json (1)
1-42: Hardcoded PII should be generated dynamically from Nix config.This file contains hardcoded personal information (email, nickname) repeated across all providers. As previously flagged, this should be generated dynamically using
builtins.toJSONin the Nix module to centralize personal data and improve maintainability.Additionally, per coding guidelines, keys should be sorted alphabetically when possible in configuration files.
🧹 Nitpick comments (1)
config/ccs/default.nix (1)
1-10: Well-documented module, but consider dynamic generation.The comments clearly explain the purpose and security boundary (token files stored separately). However, this approach couples to the static
accounts.jsonfile containing PII.Consider the previously suggested approach: use
home.file.".ccs/cliproxy/accounts.json".text = builtins.toJSON accountsData;whereaccountsDatais constructed dynamically using values fromconfig.accounts.email.accounts.Gmail.address. This eliminates the static JSON file entirely.♻️ Suggested dynamic generation approach
{ config, ... }: let email = config.accounts.email.accounts.Gmail.address; nickname = "shunkakinoki"; # Or derive from config accountsData = { version = 1; providers = { agy = { default = email; accounts."${email}" = { inherit email nickname; tokenFile = "antigravity-shunkakinoki_gmail_com.json"; createdAt = "2026-01-17T00:00:00.000Z"; lastUsedAt = "2026-01-17T00:00:00.000Z"; tier = "paid"; }; }; # ... gemini and codex similarly }; }; in { # CCS (Claude Code Switcher) account registry home.file.".ccs/cliproxy/accounts.json" = { text = builtins.toJSON accountsData; force = true; }; }
| # Use objectstore/auths subdirectory to avoid duplicate scanning (root-level files are legacy) | ||
| auth-dir: "~/.cli-proxy-api/objectstore/auths" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Search for migration documentation or guides related to this change
rg -i "migration\|migrate" --type=md --type=txt -A 2 -B 2Repository: shunkakinoki/dotfiles
Length of output: 47
🏁 Script executed:
# Check for objectstore/auths references in documentation
rg "objectstore/auths|cli-proxy-api" --type=md --type=txt --type=nix -C 2Repository: shunkakinoki/dotfiles
Length of output: 3185
🏁 Script executed:
# Check the actual YAML file for context and formatting
cat -n config/cliproxyapi/config.yaml | head -30Repository: shunkakinoki/dotfiles
Length of output: 1807
🏁 Script executed:
# Look for README or migration guides in the repo
fd -t f -i "readme\|migration\|changelog" -E node_modulesRepository: shunkakinoki/dotfiles
Length of output: 47
Add migration guidance for legacy auth files.
The README documents that ~/.cli-proxy-api/objectstore/auths is the intended auth cache directory. However, your comment references "root-level files are legacy" without documenting how users with existing auth files at ~/.cli-proxy-api/ should migrate them. Add a note in the README or commit message clarifying the migration path, or confirm this is only for fresh setups.
🤖 Prompt for AI Agents
In `@config/cliproxyapi/config.yaml` around lines 15 - 16, Update the project
documentation to add explicit migration guidance for legacy auth files
referenced by the config key auth-dir (value
"~/.cli-proxy-api/objectstore/auths"): state whether this new directory is only
for fresh setups or required for all users, describe how to detect legacy files
at "~/.cli-proxy-api/" and provide a simple migration command sequence (e.g.,
move/backup into the new objectstore/auths subdirectory), and include any
post-migration steps or troubleshooting notes so users know how to verify the
migrated auth files work with the CLI proxy API.
There was a problem hiding this comment.
Pull request overview
This pull request adds configuration for the CCS (Claude Code Switcher) accounts registry to fix the "No accounts configured" error when using CCS commands. The PR also updates the cliproxyapi auth directory path to use a more organized subdirectory structure.
Changes:
- Add CCS module with accounts.json configuration for three providers (agy, gemini, codex)
- Update cliproxyapi auth-dir to use objectstore/auths subdirectory
- Register the new CCS module in the config imports
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| config/default.nix | Adds ccs module to the list of imported configuration modules |
| config/cliproxyapi/config.yaml | Updates auth-dir path to use objectstore/auths subdirectory structure |
| config/ccs/default.nix | Creates new Nix module that symlinks accounts.json to ~/.ccs/cliproxy/ |
| config/ccs/accounts.json | Defines account registry with OAuth token mappings for three providers |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Use objectstore/auths subdirectory to avoid duplicate scanning (root-level files are legacy) | ||
| auth-dir: "~/.cli-proxy-api/objectstore/auths" |
There was a problem hiding this comment.
The comment states "Use objectstore/auths subdirectory to avoid duplicate scanning (root-level files are legacy)", but this explanation is vague. Consider clarifying what "duplicate scanning" refers to and why root-level files are considered legacy. This would help future maintainers understand the rationale for this directory structure change.
| "tokenFile": "antigravity-shunkakinoki_gmail_com.json", | ||
| "createdAt": "2026-01-17T00:00:00.000Z", | ||
| "lastUsedAt": "2026-01-17T00:00:00.000Z", | ||
| "tier": "paid" | ||
| } | ||
| } | ||
| }, | ||
| "gemini": { | ||
| "default": "shunkakinoki@gmail.com", | ||
| "accounts": { | ||
| "shunkakinoki@gmail.com": { | ||
| "email": "shunkakinoki@gmail.com", | ||
| "nickname": "shunkakinoki", | ||
| "tokenFile": "gemini-shunkakinoki@gmail.com-gen-lang-client-0359793614.json", |
There was a problem hiding this comment.
The email address in the tokenFile is inconsistent with the format used in other providers. For the gemini provider, the tokenFile uses "@" symbol ("gemini-shunkakinoki@gmail.com-gen-lang-client-0359793614.json"), while for the agy provider it uses an underscore-separated format ("antigravity-shunkakinoki_gmail_com.json"). This inconsistency could lead to confusion when managing token files. Consider standardizing the token file naming convention across all providers.
| { | ||
| "version": 1, | ||
| "providers": { | ||
| "agy": { | ||
| "default": "shunkakinoki@gmail.com", | ||
| "accounts": { | ||
| "shunkakinoki@gmail.com": { | ||
| "email": "shunkakinoki@gmail.com", | ||
| "nickname": "shunkakinoki", | ||
| "tokenFile": "antigravity-shunkakinoki_gmail_com.json", | ||
| "createdAt": "2026-01-17T00:00:00.000Z", | ||
| "lastUsedAt": "2026-01-17T00:00:00.000Z", | ||
| "tier": "paid" | ||
| } | ||
| } | ||
| }, | ||
| "gemini": { | ||
| "default": "shunkakinoki@gmail.com", | ||
| "accounts": { | ||
| "shunkakinoki@gmail.com": { | ||
| "email": "shunkakinoki@gmail.com", | ||
| "nickname": "shunkakinoki", | ||
| "tokenFile": "gemini-shunkakinoki@gmail.com-gen-lang-client-0359793614.json", | ||
| "createdAt": "2026-01-12T00:00:00.000Z", | ||
| "lastUsedAt": "2026-01-12T00:00:00.000Z" | ||
| } | ||
| } | ||
| }, | ||
| "codex": { | ||
| "default": "shunkakinoki@gmail.com", | ||
| "accounts": { | ||
| "shunkakinoki@gmail.com": { | ||
| "email": "shunkakinoki@gmail.com", | ||
| "nickname": "shunkakinoki", | ||
| "tokenFile": "codex-shunkakinoki@gmail.com.json", | ||
| "createdAt": "2025-12-18T00:00:00.000Z", | ||
| "lastUsedAt": "2025-12-18T00:00:00.000Z" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
This configuration file contains a personal email address (shunkakinoki@gmail.com) which appears to be developer-specific rather than a placeholder or example value. If this is meant to be a shared configuration template, consider using placeholder values like "user@example.com" or add documentation indicating that users need to replace these values with their own credentials. If this is personal configuration that should not be shared, it should not be committed to version control.
The relative path ./accounts.json was being resolved within the Nix
store context. Using absolute path ${dotfilesDir}/config/ccs/accounts.json
ensures the symlink points to the actual dotfiles so CCS can write
to the file (updates lastUsedAt timestamps).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
cliproxyapi wasn't being restarted on `make switch`, causing config changes (like auth-dir) to not take effect until manual restart. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ensures cliproxyapi always runs the latest Docker image when restarted via `make switch` or `make systemctl-cliproxyapi`. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
AMP integration causes antigravity (agy) provider requests to be incorrectly routed through ampcode.com, returning 404 errors. Disabling AMP on Linux allows antigravity OAuth to work directly. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add template-based approach for managing CCS provider settings: - Create agy.settings.template.json with __CLIPROXY_API_KEY__ placeholder - Add home-manager activation script to hydrate template at switch time - ANTHROPIC_AUTH_TOKEN is substituted from CLIPROXY_API_KEY in .env Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 3 files (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="config/ccs/default.nix">
<violation number="1" location="config/ccs/default.nix:32">
P1: Secret CLIPROXY_API_KEY is written to ~/.ccs/agy.settings.json without enforcing restrictive permissions, likely creating a world-readable secrets file.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| if [ -n "$CLIPROXY_API_KEY" ]; then | ||
| ${pkgs.gnused}/bin/sed \ | ||
| -e "s|__CLIPROXY_API_KEY__|$CLIPROXY_API_KEY|g" \ | ||
| "$TEMPLATE" > "$OUTPUT" |
There was a problem hiding this comment.
P1: Secret CLIPROXY_API_KEY is written to ~/.ccs/agy.settings.json without enforcing restrictive permissions, likely creating a world-readable secrets file.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At config/ccs/default.nix, line 32:
<comment>Secret CLIPROXY_API_KEY is written to ~/.ccs/agy.settings.json without enforcing restrictive permissions, likely creating a world-readable secrets file.</comment>
<file context>
@@ -11,4 +11,29 @@ in
+ if [ -n "$CLIPROXY_API_KEY" ]; then
+ ${pkgs.gnused}/bin/sed \
+ -e "s|__CLIPROXY_API_KEY__|$CLIPROXY_API_KEY|g" \
+ "$TEMPLATE" > "$OUTPUT"
+ $VERBOSE_ECHO "Hydrated CCS agy.settings.json with CLIPROXY_API_KEY"
+ else
</file context>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@config/ccs/default.nix`:
- Around line 28-33: The sed substitution for CLIPROXY_API_KEY must escape
characters that are special in sed replacement text (backslash and ampersand)
before running ${pkgs.gnused}/bin/sed; update the block that writes "$TEMPLATE"
-> "$OUTPUT" to first transform CLIPROXY_API_KEY (e.g., via POSIX shell
parameter expansion or a small helper) replacing '\' with '\\' and '&' with
'\&', then use that escaped variable in the sed -e
"s|__CLIPROXY_API_KEY__|$ESCAPED_CLIPROXY_API_KEY|g" invocation and keep the
existing '|' delimiter (so '/' need not be escaped); ensure you reference
CLIPROXY_API_KEY when creating ESCAPED_CLIPROXY_API_KEY and retain VERBOSE_ECHO
for the log message.
♻️ Duplicate comments (1)
config/ccs/accounts.json (1)
1-42: Avoid committing personal account data in a shared config.This hardcodes PII (email/nickname/token filenames). Consider generating this file dynamically in Nix (e.g.,
builtins.toJSON) or using placeholders with activation-time hydration so personal data stays out of the repo.
🧹 Nitpick comments (1)
Makefile (1)
675-683: Guard the image pull when Docker isn’t available.On Linux hosts without Docker, this target will emit errors (even with
|| true). Consider a lightweight guard to reduce noise.♻️ Proposed tweak
systemctl-cliproxyapi: ## Pull latest image and restart cliproxyapi systemd user service. `@echo` "🔄 Pulling latest cliproxyapi image..." - `@docker` pull eceasy/cli-proxy-api:latest || true + `@if` command -v docker >/dev/null 2>&1; then \ + docker pull eceasy/cli-proxy-api:latest || true; \ + else \ + echo "⚠️ docker not found; skipping image pull"; \ + fi `@echo` "🔄 Restarting cliproxyapi..." `@systemctl` --user restart cliproxyapi.service || true `@echo` "✅ cliproxyapi restarted"
| # Substitute placeholder and write output | ||
| if [ -n "$CLIPROXY_API_KEY" ]; then | ||
| ${pkgs.gnused}/bin/sed \ | ||
| -e "s|__CLIPROXY_API_KEY__|$CLIPROXY_API_KEY|g" \ | ||
| "$TEMPLATE" > "$OUTPUT" | ||
| $VERBOSE_ECHO "Hydrated CCS agy.settings.json with CLIPROXY_API_KEY" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's look at the actual file and its context
cat -n config/ccs/default.nix | head -50Repository: shunkakinoki/dotfiles
Length of output: 1895
🏁 Script executed:
# Search for CLIPROXY_API_KEY to understand its source and usage
rg "CLIPROXY_API_KEY" -B 3 -A 3Repository: shunkakinoki/dotfiles
Length of output: 7940
🏁 Script executed:
# Check the full script context in the file
sed -n '1,50p' config/ccs/default.nixRepository: shunkakinoki/dotfiles
Length of output: 1622
🏁 Script executed:
# Look for test cases or documentation about CLIPROXY_API_KEY format
rg "CLIPROXY_API_KEY.*=" -A 2 -B 2 | head -50Repository: shunkakinoki/dotfiles
Length of output: 816
🏁 Script executed:
# Check if there are any examples or documentation files
fd -e md -e txt | xargs grep -l CLIPROXY_API_KEY 2>/dev/nullRepository: shunkakinoki/dotfiles
Length of output: 49
🏁 Script executed:
# Look for similar sed escaping patterns in the codebase
rg "sed.*\\\$.*-e.*s\|" -A 2 -B 2Repository: shunkakinoki/dotfiles
Length of output: 47
Escape special characters in CLIPROXY_API_KEY before sed substitution, but correct the escaping approach.
The concern about sed special characters is valid: if the API key contains & or \, the substitution will fail or produce incorrect JSON. However, the proposed fix is flawed—it attempts to escape / characters (unnecessary since the delimiter is |) using malformed syntax.
For sed replacement text, only & (which represents the matched string) and \ (escape char) need escaping. The correct approach:
Correct fix (escape & and backslash for sed replacement)
if [ -n "$CLIPROXY_API_KEY" ]; then
+ escaped_key="$(printf '%s' "$CLIPROXY_API_KEY" | ${pkgs.gnused}/bin/sed -e 's/[&\]/\\&/g')"
${pkgs.gnused}/bin/sed \
- -e "s|__CLIPROXY_API_KEY__|$CLIPROXY_API_KEY|g" \
+ -e "s|__CLIPROXY_API_KEY__|${escaped_key}|g" \
"$TEMPLATE" > "$OUTPUT"Also confirm: what is the expected character set for CLIPROXY_API_KEY? Is it documented anywhere that it's restricted to alphanumeric characters and hyphens?
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Substitute placeholder and write output | |
| if [ -n "$CLIPROXY_API_KEY" ]; then | |
| ${pkgs.gnused}/bin/sed \ | |
| -e "s|__CLIPROXY_API_KEY__|$CLIPROXY_API_KEY|g" \ | |
| "$TEMPLATE" > "$OUTPUT" | |
| $VERBOSE_ECHO "Hydrated CCS agy.settings.json with CLIPROXY_API_KEY" | |
| # Substitute placeholder and write output | |
| if [ -n "$CLIPROXY_API_KEY" ]; then | |
| escaped_key="$(printf '%s' "$CLIPROXY_API_KEY" | ${pkgs.gnused}/bin/sed -e 's/[&\]/\\&/g')" | |
| ${pkgs.gnused}/bin/sed \ | |
| -e "s|__CLIPROXY_API_KEY__|${escaped_key}|g" \ | |
| "$TEMPLATE" > "$OUTPUT" | |
| $VERBOSE_ECHO "Hydrated CCS agy.settings.json with CLIPROXY_API_KEY" |
🤖 Prompt for AI Agents
In `@config/ccs/default.nix` around lines 28 - 33, The sed substitution for
CLIPROXY_API_KEY must escape characters that are special in sed replacement text
(backslash and ampersand) before running ${pkgs.gnused}/bin/sed; update the
block that writes "$TEMPLATE" -> "$OUTPUT" to first transform CLIPROXY_API_KEY
(e.g., via POSIX shell parameter expansion or a small helper) replacing '\' with
'\\' and '&' with '\&', then use that escaped variable in the sed -e
"s|__CLIPROXY_API_KEY__|$ESCAPED_CLIPROXY_API_KEY|g" invocation and keep the
existing '|' delimiter (so '/' need not be escaped); ensure you reference
CLIPROXY_API_KEY when creating ESCAPED_CLIPROXY_API_KEY and retain VERBOSE_ECHO
for the log message.
- Move inline nix activation script to config/ccs/hydrate.sh - Add templates for codex and gemini providers - Process all *.settings.template.json files automatically - Substitutes __CLIPROXY_API_KEY__ from .env at activation time Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add config.template.yaml with __CLIPROXY_API_KEY__ placeholder - Update hydrate.sh to process both config.yaml and settings templates - Auth token is now managed via template substitution Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="spec/coverage_spec.sh">
<violation number="1" location="spec/coverage_spec.sh:108">
P2: New script config/ccs/hydrate.sh added to coverage list but missing corresponding spec-file assertion; coverage test won’t enforce a test exists for it.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| # List of all shell scripts that should have tests | ||
| # Update this list when adding new shell scripts | ||
| covered_scripts="config/claude/notify.sh | ||
| covered_scripts="config/ccs/hydrate.sh |
There was a problem hiding this comment.
P2: New script config/ccs/hydrate.sh added to coverage list but missing corresponding spec-file assertion; coverage test won’t enforce a test exists for it.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At spec/coverage_spec.sh, line 108:
<comment>New script config/ccs/hydrate.sh added to coverage list but missing corresponding spec-file assertion; coverage test won’t enforce a test exists for it.</comment>
<file context>
@@ -105,7 +105,8 @@ Describe 'no shell scripts are missing from coverage list'
# List of all shell scripts that should have tests
# Update this list when adding new shell scripts
-covered_scripts="config/claude/notify.sh
+covered_scripts="config/ccs/hydrate.sh
+config/claude/notify.sh
config/claude/pushover.sh
</file context>
Summary
ccs agy,ccs gemini, orccs codexcommands~/.ccs/cliproxy/auth/(not managed here as they contain secrets)Test plan
home-manager switchto apply configurationls -la ~/.ccs/cliproxy/accounts.jsonccs agy --helpworks without "No accounts configured" error🤖 Generated with Claude Code
Summary by cubic
Adds Home Manager config for the CCS accounts registry, symlinking accounts.json to ~/.ccs/cliproxy/accounts.json and fixing “No accounts configured” for ccs agy, gemini, and codex. Hydrates ~/.ccs/{provider}.settings.json (agy, gemini, codex) and ~/.ccs/config.yaml from CLIPROXY_API_KEY via templates, points cliproxyapi to ~/.cli-proxy-api/objectstore/auths, adds a Makefile restart target that pulls the latest image, and disables AMP on Linux to fix agy routing; token files remain in ~/.ccs/cliproxy/auth/.
home-manager switch(ensure.envsetsCLIPROXY_API_KEY).make systemctl-cliproxyapiormake systemctl.~/.ccs/cliproxy/accounts.jsonis a symlink,~/.ccs/{agy,gemini,codex}.settings.jsonexist, and~/.ccs/config.yamlexists.ccs agy --help,ccs gemini --help, andccs codex --helprun without the error.Written for commit c8350db. Summary will update on new commits.