Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,15 @@ launchctl-ollama: ## Restart ollama launchd agent.
##@ Systemd Services (Linux)

.PHONY: systemctl
systemctl: systemctl-clawdbot systemctl-code-syncer systemctl-dotfiles-updater systemctl-ollama ## Restart all systemd user services.
systemctl: systemctl-cliproxyapi systemctl-clawdbot systemctl-code-syncer systemctl-dotfiles-updater systemctl-ollama ## Restart all systemd user services.

.PHONY: systemctl-cliproxyapi
systemctl-cliproxyapi: ## Pull latest image and restart cliproxyapi systemd user service.
@echo "🔄 Pulling latest cliproxyapi image..."
@docker pull eceasy/cli-proxy-api:latest || true
@echo "🔄 Restarting cliproxyapi..."
@systemctl --user restart cliproxyapi.service || true
@echo "✅ cliproxyapi restarted"

.PHONY: systemctl-clawdbot
systemctl-clawdbot: ## Restart clawdbot gateway systemd user service.
Expand Down
42 changes: 42 additions & 0 deletions config/ccs/accounts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"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-17T19:28:18.251Z",
"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",
Comment on lines +10 to +23

Copilot AI Jan 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
"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"
}
}
}
}
}
Comment on lines +1 to +42

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

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.

Comment on lines +1 to +42

Copilot AI Jan 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
10 changes: 10 additions & 0 deletions config/ccs/agy.settings.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/agy",
"ANTHROPIC_AUTH_TOKEN": "__CLIPROXY_API_KEY__",
"ANTHROPIC_MODEL": "claude-opus-4-5-thinking",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-5-thinking",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-opus-4-5-thinking",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-sonnet-4-5"
}
}
10 changes: 10 additions & 0 deletions config/ccs/codex.settings.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/codex",
"ANTHROPIC_AUTH_TOKEN": "__CLIPROXY_API_KEY__",
"ANTHROPIC_MODEL": "gpt-5.1-codex-max",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "gpt-5.1-codex-max-high",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "gpt-5.1-codex-max",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "gpt-5.1-codex-mini-high"
}
}
131 changes: 131 additions & 0 deletions config/ccs/config.template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# CCS Unified Configuration
# Docs: https://github.com/kaitranntt/ccs
version: 7
# ----------------------------------------------------------------------------
# Accounts: Isolated Claude instances (each with separate auth/sessions)
# Manage with: ccs auth add <name>, ccs auth list, ccs auth remove <name>
# ----------------------------------------------------------------------------
accounts: {}
# ----------------------------------------------------------------------------
# Profiles: API-based providers (GLM, GLMT, Kimi, custom endpoints)
# Each profile points to a *.settings.json file containing env vars.
# Edit the settings file directly to customize (ANTHROPIC_MAX_TOKENS, etc.)
# ----------------------------------------------------------------------------
profiles: {}
# ----------------------------------------------------------------------------
# CLIProxy: OAuth-based providers (gemini, codex, agy, qwen, iflow)
# Each variant can reference a *.settings.json file for custom env vars.
# Edit the settings file directly to customize model or other settings.
# ----------------------------------------------------------------------------
cliproxy:
oauth_accounts: {}
providers:
- gemini
- codex
- agy
- qwen
- iflow
- kiro
- ghcp
variants: {}
logging:
enabled: false
request_log: false
# ----------------------------------------------------------------------------
# CLIProxy Server: Remote proxy connection settings
# Configure via Dashboard (`ccs config`) > Proxy tab.
#
# remote: Connect to a remote CLIProxyAPI instance
# fallback: Use local proxy if remote is unreachable
# local: Local proxy settings (port, auto-start)
# ----------------------------------------------------------------------------
cliproxy_server:
remote:
enabled: true
host: 127.0.0.1
port: 8317
protocol: http
auth_token: __CLIPROXY_API_KEY__
fallback:
enabled: true
auto_start: false
local:
port: 8317
auto_start: false
# ----------------------------------------------------------------------------
# Preferences: User settings
# ----------------------------------------------------------------------------
preferences:
theme: system
telemetry: false
auto_update: true
# ----------------------------------------------------------------------------
# WebSearch: CLI-based web search for third-party profiles
# Dashboard (`ccs config`) is the source of truth for provider selection.
#
# Third-party providers (gemini, codex, agy, etc.) do not have access to
# Anthropic's WebSearch tool. These CLI tools provide fallback web search.
#
# Fallback chain: Gemini -> OpenCode -> Grok (tries in order until success)
#
# Gemini models: gemini-2.5-flash (default), gemini-2.5-pro, gemini-2.5-flash-lite
# OpenCode models: opencode/grok-code (default), opencode/gpt-4o, opencode/claude-3.5-sonnet
#
# Install commands:
# gemini: npm i -g @google/gemini-cli (FREE - 1000 req/day)
# opencode: curl -fsSL https://opencode.ai/install | bash (FREE via Zen)
# grok: npm i -g @vibe-kit/grok-cli (requires GROK_API_KEY)
# ----------------------------------------------------------------------------
websearch:
enabled: true
providers:
gemini:
enabled: true
model: gemini-2.5-flash
timeout: 55
opencode:
enabled: false
model: opencode/grok-code
timeout: 90
grok:
enabled: false
timeout: 55
# ----------------------------------------------------------------------------
# Copilot: GitHub Copilot API proxy (via copilot-api)
# Uses your existing GitHub Copilot subscription with Claude Code.
#
# !! DISCLAIMER - USE AT YOUR OWN RISK !!
# This uses an UNOFFICIAL reverse-engineered API.
# Excessive usage may trigger GitHub account restrictions.
# CCS provides NO WARRANTY and accepts NO RESPONSIBILITY for consequences.
#
# Setup: npx copilot-api auth (authenticate with GitHub)
# Usage: ccs copilot (switch to copilot profile)
#
# Models: claude-sonnet-4.5, claude-opus-4.5, gpt-5.1, gemini-2.5-pro
# Account types: individual, business, enterprise
# ----------------------------------------------------------------------------
copilot:
enabled: false
auto_start: false
port: 4141
account_type: individual
rate_limit: null
wait_on_limit: true
model: gpt-4.1
# ----------------------------------------------------------------------------
# Global Environment Variables: Injected into all non-Claude subscription profiles
# These env vars disable telemetry/reporting for third-party providers.
# Configure via Dashboard (`ccs config`) > Global Env tab.
#
# Default variables:
# DISABLE_BUG_COMMAND: Disables /bug command (not supported by proxy)
# DISABLE_ERROR_REPORTING: Disables error reporting to Anthropic
# DISABLE_TELEMETRY: Disables usage telemetry
# ----------------------------------------------------------------------------
global_env:
enabled: true
env:
DISABLE_BUG_COMMAND: "1"
DISABLE_ERROR_REPORTING: "1"
DISABLE_TELEMETRY: "1"
31 changes: 31 additions & 0 deletions config/ccs/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
config,
lib,
pkgs,
...
}:
let
dotfilesDir = "${config.home.homeDirectory}/dotfiles";

# Hydration script for CCS provider settings
hydrateScript = pkgs.replaceVars ./hydrate.sh {
sed = "${pkgs.gnused}/bin/sed";
};
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)
# Note: Using mkOutOfStoreSymlink with absolute path so CCS can write to the file (updates lastUsedAt)
home.file.".ccs/cliproxy/accounts.json" = {
source = config.lib.file.mkOutOfStoreSymlink "${dotfilesDir}/config/ccs/accounts.json";
force = true;
};

# Hydrate CCS settings templates with secrets from .env
# ANTHROPIC_AUTH_TOKEN is substituted from CLIPROXY_API_KEY at activation time
# Processes all *.settings.template.json files in config/ccs/
home.activation.hydrateCcsSettings = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
${pkgs.bash}/bin/bash ${hydrateScript} || true
'';
}
10 changes: 10 additions & 0 deletions config/ccs/gemini.settings.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/gemini",
"ANTHROPIC_AUTH_TOKEN": "__CLIPROXY_API_KEY__",
"ANTHROPIC_MODEL": "gemini-2.5-pro",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "gemini-2.5-pro",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "gemini-2.5-pro",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "gemini-2.5-flash"
}
}
51 changes: 51 additions & 0 deletions config/ccs/hydrate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# Hydrate CCS provider settings and config from templates
# Substitutes __CLIPROXY_API_KEY__ placeholder with actual API key from .env
# shellcheck source=/dev/null
set -euo pipefail

DOTFILES_DIR="${HOME}/dotfiles"
CCS_DIR="${HOME}/.ccs"
TEMPLATE_DIR="${DOTFILES_DIR}/config/ccs"
ENV_FILE="${DOTFILES_DIR}/.env"

# Load environment variables
if [ -f "$ENV_FILE" ]; then
set -a
. "$ENV_FILE"
set +a
fi

# Check for required API key
if [ -z "${CLIPROXY_API_KEY:-}" ]; then
echo "Warning: CLIPROXY_API_KEY not set in .env, skipping CCS hydration" >&2
exit 0
fi

mkdir -p "$CCS_DIR"

# Hydrate config.yaml
CONFIG_TEMPLATE="${TEMPLATE_DIR}/config.template.yaml"
if [ -f "$CONFIG_TEMPLATE" ]; then
@sed@ \
-e "s|__CLIPROXY_API_KEY__|${CLIPROXY_API_KEY}|g" \
"$CONFIG_TEMPLATE" >"${CCS_DIR}/config.yaml"
echo "Hydrated CCS config.yaml" >&2
fi

# Process all provider settings templates
for template in "$TEMPLATE_DIR"/*.settings.template.json; do
[ -f "$template" ] || continue

# Extract provider name: foo.settings.template.json -> foo
filename=$(basename "$template")
provider="${filename%.settings.template.json}"
output="${CCS_DIR}/${provider}.settings.json"

# Substitute placeholder and write output
@sed@ \
-e "s|__CLIPROXY_API_KEY__|${CLIPROXY_API_KEY}|g" \
"$template" >"$output"

echo "Hydrated CCS ${provider}.settings.json" >&2
done
3 changes: 2 additions & 1 deletion config/cliproxyapi/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ remote-management:
# Disable the bundled management control panel asset download and HTTP route when true.
disable-control-panel: false
# Authentication directory (supports ~ for home directory). If you use Windows, please set the directory like this: `C:/cli-proxy-api/`
auth-dir: "~/.cli-proxy-api"
# Use objectstore/auths subdirectory to avoid duplicate scanning (root-level files are legacy)
auth-dir: "~/.cli-proxy-api/objectstore/auths"
Comment on lines +15 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 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 2

Repository: 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 2

Repository: shunkakinoki/dotfiles

Length of output: 3185


🏁 Script executed:

# Check the actual YAML file for context and formatting
cat -n config/cliproxyapi/config.yaml | head -30

Repository: 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_modules

Repository: 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.

Comment on lines +15 to +16

Copilot AI Jan 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
# API keys for client authentication (optional - leave commented for open access)
# api-keys:
# - "__CLIPROXY_API_KEY__"
Expand Down
1 change: 1 addition & 0 deletions config/default.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[
./amp
./ccs
./cliproxyapi
./codex
./crush
Expand Down
10 changes: 10 additions & 0 deletions home-manager/services/cliproxyapi/scripts/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ if [ -f "$TEMPLATE" ]; then
-e "s|^# - \"__CLIPROXY_API_KEY__\"| - \"${CLIPROXY_API_KEY}\"|" \
"$CONFIG"
fi

# Disable AMP on Linux (causes routing issues with antigravity provider)
if [ "$(uname)" = "Linux" ]; then
@sed@ -i \
-e "s|^ampcode:|# ampcode:|" \
-e "s|^ upstream-url:|# upstream-url:|" \
-e "s|^ upstream-api-key:|# upstream-api-key:|" \
-e "s|^ restrict-management-to-localhost:|# restrict-management-to-localhost:|" \
"$CONFIG"
fi
fi

cd "$CONFIG_DIR"
Expand Down
3 changes: 2 additions & 1 deletion spec/coverage_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ Describe 'no shell scripts are missing from coverage list'
It 'covers all non-spec shell scripts in the repository'
# 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

@cubic-dev-ai cubic-dev-ai Bot Jan 17, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Fix with Cubic

config/claude/notify.sh
config/claude/pushover.sh
config/claude/security.sh
config/claude/statusline-git.sh
Expand Down
Loading