feat(profile,shell-completion,prompt): add profile commands and improve input handling (#34)

* fix(cliproxy): use double-dash flags for cliproxyapi auth (#24)

CLIProxyAPI updated from single-dash to double-dash CLI flags.
Changed -login to --login, -codex-login to --codex-login,
-antigravity-login to --antigravity-login, -config to --config,
and -no-browser to --no-browser.

* chore(release): 5.1.1-beta.1 [skip ci]

## [5.1.1-beta.1](https://github.com/kaitranntt/ccs/compare/v5.1.0...v5.1.1-beta.1) (2025-12-01)

### Bug Fixes

* **cliproxy:** use double-dash flags for cliproxyapi auth ([#24](https://github.com/kaitranntt/ccs/issues/24)) ([4c81f28](https://github.com/kaitranntt/ccs/commit/4c81f28f0b67ef92cf74d0f5c13a5943ff0a7f00))

* chore(release): 5.1.1-beta.2 [skip ci]

## [5.1.1-beta.2](https://github.com/kaitranntt/ccs/compare/v5.1.1-beta.1...v5.1.1-beta.2) (2025-12-01)

### Bug Fixes

* **cliproxy:** use double-dash flags for cliproxyapi auth ([9489884](https://github.com/kaitranntt/ccs/commit/94898848ea4533dcfc142e1b6c9bf939ba655537))

* fix(glmt): handle 401 errors and headers-already-sent exception (#30)

- add res.headersSent check before writing error headers
- write error as SSE event when headers already sent (streaming mode)
- add parseUpstreamError() for user-friendly error messages
- return proper HTTP status codes (401, 403, 429, 502, 504)
- clear auth error: check ANTHROPIC_AUTH_TOKEN in config

Fixes #26

* chore(release): 5.1.1-beta.3 [skip ci]

## [5.1.1-beta.3](https://github.com/kaitranntt/ccs/compare/v5.1.1-beta.2...v5.1.1-beta.3) (2025-12-01)

### Bug Fixes

* **glmt:** handle 401 errors and headers-already-sent exception ([#30](https://github.com/kaitranntt/ccs/issues/30)) ([c953382](https://github.com/kaitranntt/ccs/commit/c95338232a37981b95b785b47185ce18d6d94b7a)), closes [#26](https://github.com/kaitranntt/ccs/issues/26)

* chore(release): enable success comments and released labels in semantic-release

* feat(cliproxy): add qwen code oauth provider support (#31)

Add 'qwen' as new CLIProxy OAuth provider with --qwen-login flag.
Support qwen3-coder model with base config at config/base-qwen.settings.json.
Register qwen OAuth endpoints and token prefix handling.
Update help documentation across all CLI entry points.

Implements issue #29

* chore(release): 5.2.0-beta.1 [skip ci]

# [5.2.0-beta.1](https://github.com/kaitranntt/ccs/compare/v5.1.1-beta.3...v5.2.0-beta.1) (2025-12-01)

### Features

* **cliproxy:** add qwen code oauth provider support ([#31](https://github.com/kaitranntt/ccs/issues/31)) ([a3f1e52](https://github.com/kaitranntt/ccs/commit/a3f1e52ac68600ba0806d67aacceb6477ffa3543)), closes [#29](https://github.com/kaitranntt/ccs/issues/29)

* feat(cliproxy): auto-update cliproxyapi to latest release on startup

- add github api integration to fetch latest release version
- check for updates on every startup (cached for 1 hour)
- auto-download newer versions when available
- rename CLIPROXY_VERSION to CLIPROXY_FALLBACK_VERSION (safety net)
- add version tracking (.version file) and caching (.version-cache.json)
- non-blocking: startup continues if update check fails

* chore(release): 5.2.0-beta.2 [skip ci]

# [5.2.0-beta.2](https://github.com/kaitranntt/ccs/compare/v5.2.0-beta.1...v5.2.0-beta.2) (2025-12-01)

### Features

* **cliproxy:** auto-update cliproxyapi to latest release on startup ([8873ccd](https://github.com/kaitranntt/ccs/commit/8873ccd981679e8acff8965accdc22215c6e4aa2))

* chore(release): 5.3.0-beta.1 [skip ci]

# [5.3.0-beta.1](https://github.com/kaitranntt/ccs/compare/v5.2.0...v5.3.0-beta.1) (2025-12-01)

### Bug Fixes

* **cliproxy:** use double-dash flags for cliproxyapi auth ([#24](https://github.com/kaitranntt/ccs/issues/24)) ([4c81f28](https://github.com/kaitranntt/ccs/commit/4c81f28f0b67ef92cf74d0f5c13a5943ff0a7f00))
* **glmt:** handle 401 errors and headers-already-sent exception ([#30](https://github.com/kaitranntt/ccs/issues/30)) ([c953382](https://github.com/kaitranntt/ccs/commit/c95338232a37981b95b785b47185ce18d6d94b7a)), closes [#26](https://github.com/kaitranntt/ccs/issues/26)

### Features

* **cliproxy:** add qwen code oauth provider support ([#31](https://github.com/kaitranntt/ccs/issues/31)) ([a3f1e52](https://github.com/kaitranntt/ccs/commit/a3f1e52ac68600ba0806d67aacceb6477ffa3543)), closes [#29](https://github.com/kaitranntt/ccs/issues/29)
* **cliproxy:** auto-update cliproxyapi to latest release on startup ([8873ccd](https://github.com/kaitranntt/ccs/commit/8873ccd981679e8acff8965accdc22215c6e4aa2))

* fix(cliproxy): improve qwen oauth error handling

- Updated OAuth port documentation with correct flow types per provider
- Removed Qwen from port cleanup logic (Device Code Flow has no callback)
- Fixed Qwen error messages to show Device Code Flow troubleshooting tips

Fixes #29

* chore(release): 5.3.0-beta.2 [skip ci]

# [5.3.0-beta.2](https://github.com/kaitranntt/ccs/compare/v5.3.0-beta.1...v5.3.0-beta.2) (2025-12-01)

### Bug Fixes

* **cliproxy:** improve qwen oauth error handling ([7e0b0fe](https://github.com/kaitranntt/ccs/commit/7e0b0feca8ce2ed5d505c5bf6c84e54c6df8839e)), closes [#29](https://github.com/kaitranntt/ccs/issues/29)

* feat(profile): add profile command with configuration display

* feat(shell-completion): add --force flag and fix zsh profile coloring

* fix(prompt): improve password input handling with raw mode and buffer support

* chore(release): 5.3.0-beta.3 [skip ci]

# [5.3.0-beta.3](https://github.com/kaitranntt/ccs/compare/v5.3.0-beta.2...v5.3.0-beta.3) (2025-12-01)

### Bug Fixes

* **prompt:** improve password input handling with raw mode and buffer support ([bc56d2e](https://github.com/kaitranntt/ccs/commit/bc56d2e135532b2ae443144dd42217b26bcba951))

### Features

* **profile:** add profile command with configuration display ([53d7a15](https://github.com/kaitranntt/ccs/commit/53d7a15c047e760723e051dc0f7be3c0dd42d087))
* **shell-completion:** add --force flag and fix zsh profile coloring ([7faed1d](https://github.com/kaitranntt/ccs/commit/7faed1d84ba29ba02bf687bae5b3458617512e67))

* chore(release): 5.3.0-beta.4 [skip ci]

# [5.3.0-beta.4](https://github.com/kaitranntt/ccs/compare/v5.3.0-beta.3...v5.3.0-beta.4) (2025-12-01)

### Bug Fixes

* **cliproxy:** improve qwen oauth error handling ([#33](https://github.com/kaitranntt/ccs/issues/33)) ([1c3374f](https://github.com/kaitranntt/ccs/commit/1c3374f6a7e4440e299d49b58808c6454b4547c2)), closes [#29](https://github.com/kaitranntt/ccs/issues/29)

---------

Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
This commit is contained in:
Kai (Tam Nhu) Tran
2025-12-01 18:04:04 -05:00
committed by GitHub
co-authored by semantic-release-bot
parent 7f3f1fc34a
commit 7ec8cc8369
15 changed files with 777 additions and 36 deletions
+31 -1
View File
@@ -18,7 +18,7 @@ _ccs_completion() {
# Top-level completion (first argument)
if [[ ${COMP_CWORD} -eq 1 ]]; then
local commands="auth doctor sync update"
local commands="auth profile doctor sync update"
local flags="--help --version --shell-completion -h -v -sc"
local profiles=""
@@ -45,6 +45,36 @@ _ccs_completion() {
return 0
fi
# profile subcommands
if [[ ${prev} == "profile" ]]; then
local profile_commands="create list remove --help -h"
COMPREPLY=( $(compgen -W "${profile_commands}" -- ${cur}) )
return 0
fi
# Completion for profile subcommands
if [[ ${COMP_WORDS[1]} == "profile" ]]; then
case "${prev}" in
remove|delete|rm)
# Complete with settings profile names
if [[ -f ~/.ccs/config.json ]]; then
local profiles=$(jq -r '.profiles | keys[]' ~/.ccs/config.json 2>/dev/null || true)
COMPREPLY=( $(compgen -W "${profiles}" -- ${cur}) )
fi
return 0
;;
create)
# Complete with create flags
COMPREPLY=( $(compgen -W "--base-url --api-key --model --force --yes -y" -- ${cur}) )
return 0
;;
list)
# No flags for list
return 0
;;
esac
fi
# Completion for auth subcommands that need profile names
if [[ ${COMP_WORDS[1]} == "auth" ]]; then
case "${prev}" in
+43 -10
View File
@@ -78,22 +78,23 @@ complete -c ccs -s v -l version -d 'Show version information'
complete -c ccs -s sc -l shell-completion -d 'Install shell completion'
# Commands - grouped with [cmd] prefix for visual distinction
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a 'auth' -d '[cmd] Manage multiple Claude accounts'
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a 'doctor' -d '[cmd] Run health check and diagnostics'
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a 'sync' -d '[cmd] Sync delegation commands and skills'
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a 'update' -d '[cmd] Update CCS to latest version'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a 'auth' -d '[cmd] Manage multiple Claude accounts'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a 'profile' -d '[cmd] Manage API profiles (create/remove)'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a 'doctor' -d '[cmd] Run health check and diagnostics'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a 'sync' -d '[cmd] Sync delegation commands and skills'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a 'update' -d '[cmd] Update CCS to latest version'
# Model profiles - grouped with [model] prefix for visual distinction
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a 'default' -d '[model] Default Claude Sonnet 4.5'
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a 'glm' -d '[model] GLM-4.6 (cost-optimized)'
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a 'glmt' -d '[model] GLM-4.6 with thinking mode'
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a 'kimi' -d '[model] Kimi for Coding (long-context)'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a 'default' -d '[model] Default Claude Sonnet 4.5'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a 'glm' -d '[model] GLM-4.6 (cost-optimized)'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a 'glmt' -d '[model] GLM-4.6 with thinking mode'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a 'kimi' -d '[model] Kimi for Coding (long-context)'
# Custom model profiles - dynamic with [model] prefix
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a '(__fish_ccs_get_custom_settings_profiles)' -d '[model] Settings-based profile'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a '(__fish_ccs_get_custom_settings_profiles)' -d '[model] Settings-based profile'
# Account profiles - dynamic with [account] prefix
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync update' -a '(__fish_ccs_get_account_profiles)' -d '[account] Account-based profile'
complete -c ccs -n 'not __fish_seen_subcommand_from auth profile doctor sync update' -a '(__fish_ccs_get_account_profiles)' -d '[account] Account-based profile'
# shell-completion subflags
complete -c ccs -n '__fish_seen_argument -l shell-completion; or __fish_seen_argument -s sc' -l bash -d 'Install for bash'
@@ -132,3 +133,35 @@ complete -c ccs -n '__fish_ccs_using_auth_subcommand default' -a '(__fish_ccs_ge
# doctor command flags
complete -c ccs -n '__fish_seen_subcommand_from doctor' -s h -l help -d 'Show help for doctor command'
# Helper function to check if we're in profile context
function __fish_ccs_using_profile
__fish_seen_subcommand_from profile
end
# Helper function to check specific profile subcommand
function __fish_ccs_using_profile_subcommand
set -l subcommand $argv[1]
__fish_ccs_using_profile; and __fish_seen_subcommand_from $subcommand
end
# profile subcommands
complete -c ccs -n '__fish_ccs_using_profile; and not __fish_seen_subcommand_from create list remove' -a 'create' -d 'Create new API profile'
complete -c ccs -n '__fish_ccs_using_profile; and not __fish_seen_subcommand_from create list remove' -a 'list' -d 'List all profiles'
complete -c ccs -n '__fish_ccs_using_profile; and not __fish_seen_subcommand_from create list remove' -a 'remove' -d 'Remove a profile'
# profile command flags
complete -c ccs -n '__fish_ccs_using_profile' -s h -l help -d 'Show help for profile commands'
# profile create flags
complete -c ccs -n '__fish_ccs_using_profile_subcommand create' -l base-url -d 'API base URL'
complete -c ccs -n '__fish_ccs_using_profile_subcommand create' -l api-key -d 'API key'
complete -c ccs -n '__fish_ccs_using_profile_subcommand create' -l model -d 'Default model'
complete -c ccs -n '__fish_ccs_using_profile_subcommand create' -l force -d 'Overwrite existing profile'
complete -c ccs -n '__fish_ccs_using_profile_subcommand create' -l yes -d 'Skip prompts'
complete -c ccs -n '__fish_ccs_using_profile_subcommand create' -s y -d 'Skip prompts'
# profile remove - profile names and flags
complete -c ccs -n '__fish_ccs_using_profile_subcommand remove' -a '(__fish_ccs_get_settings_profiles)' -d 'Settings profile'
complete -c ccs -n '__fish_ccs_using_profile_subcommand remove' -l yes -d 'Skip confirmation'
complete -c ccs -n '__fish_ccs_using_profile_subcommand remove' -s y -d 'Skip confirmation'
+57 -1
View File
@@ -12,8 +12,10 @@
Register-ArgumentCompleter -CommandName ccs -ScriptBlock {
param($commandName, $wordToComplete, $commandAst, $fakeBoundParameters)
$commands = @('auth', 'doctor', 'sync', 'update', '--help', '--version', '--shell-completion', '-h', '-v', '-sc')
$commands = @('auth', 'profile', 'doctor', 'sync', 'update', '--help', '--version', '--shell-completion', '-h', '-v', '-sc')
$authCommands = @('create', 'list', 'show', 'remove', 'default', '--help', '-h')
$profileCommands = @('create', 'list', 'remove', '--help', '-h')
$profileCreateFlags = @('--base-url', '--api-key', '--model', '--force', '--yes', '-y')
$shellCompletionFlags = @('--bash', '--zsh', '--fish', '--powershell')
$listFlags = @('--verbose', '--json')
$removeFlags = @('--yes', '-y')
@@ -170,4 +172,58 @@ Register-ArgumentCompleter -CommandName ccs -ScriptBlock {
}
}
}
# profile subcommand completion
if ($words[1] -eq 'profile') {
if ($position -eq 3) {
# profile subcommands
$profileCommands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new(
$_,
$_,
'ParameterValue',
$_
)
}
} elseif ($position -eq 4) {
# Profile names or flags for profile subcommands
switch ($words[2]) {
'remove' {
$options = (Get-CcsProfiles -Type settings) + $removeFlags
$options | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new(
$_,
$_,
'ParameterValue',
$_
)
}
}
'create' {
$profileCreateFlags | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new(
$_,
$_,
'ParameterValue',
$_
)
}
}
}
} elseif ($position -eq 5) {
# Flags after profile name
switch ($words[2]) {
'remove' {
$removeFlags | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new(
$_,
$_,
'ParameterValue',
$_
)
}
}
}
}
}
}
+57 -1
View File
@@ -16,7 +16,7 @@
# Color codes: 0;34=blue, 0;32=green, 0;33=yellow, 2;37=dim white
# Pattern format: =(#b)(group1)(group2)==color_for_group1=color_for_group2
# The leading '=' means no color for whole match, then each '=' assigns to each group
zstyle ':completion:*:*:ccs:*:commands' list-colors '=(#b)(auth|doctor|sync|update)([[:space:]]#--[[:space:]]#*)==0\;34=2\;37'
zstyle ':completion:*:*:ccs:*:commands' list-colors '=(#b)(auth|profile|doctor|sync|update)([[:space:]]#--[[:space:]]#*)==0\;34=2\;37'
zstyle ':completion:*:*:ccs:*:model-profiles' list-colors '=(#b)(default|glm|glmt|kimi|[^[:space:]]##)([[:space:]]#--[[:space:]]#*)==0\;32=2\;37'
zstyle ':completion:*:*:ccs:*:account-profiles' list-colors '=(#b)([^[:space:]]##)([[:space:]]#--[[:space:]]#*)==0\;33=2\;37'
zstyle ':completion:*:*:ccs:*' group-name ''
@@ -33,6 +33,7 @@ _ccs() {
# Define top-level commands (padded for alignment)
commands=(
'auth:Manage multiple Claude accounts'
'profile:Manage API profiles (create/remove)'
'doctor:Run health check and diagnostics'
'sync:Sync delegation commands and skills'
'update:Update CCS to latest version'
@@ -90,6 +91,9 @@ _ccs() {
auth)
_ccs_auth
;;
profile)
_ccs_profile
;;
doctor)
_arguments \
'(- *)'{-h,--help}'[Show help for doctor command]'
@@ -110,6 +114,58 @@ _ccs() {
esac
}
_ccs_profile() {
local curcontext="$curcontext" state line
typeset -A opt_args
local -a profile_commands settings_profiles
# Define profile subcommands
profile_commands=(
'create:Create new API profile (interactive)'
'list:List all profiles'
'remove:Remove a profile'
)
# Load settings profiles for remove command
if [[ -f ~/.ccs/config.json ]]; then
settings_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/config.json 2>/dev/null)"})
fi
_arguments -C \
'(- *)'{-h,--help}'[Show help for profile commands]' \
'1: :->subcommand' \
'*:: :->subargs'
case $state in
subcommand)
_describe -t profile-commands 'profile commands' profile_commands
;;
subargs)
case $words[1] in
create)
_arguments \
'1:profile name:' \
'--base-url[API base URL]:url:' \
'--api-key[API key]:key:' \
'--model[Default model]:model:' \
'--force[Overwrite existing profile]' \
{--yes,-y}'[Skip prompts]'
;;
list)
# No arguments
;;
remove|delete|rm)
_arguments \
'1:profile:($settings_profiles)' \
{--yes,-y}'[Skip confirmation]'
;;
esac
;;
esac
}
_ccs_auth() {
local curcontext="$curcontext" state line
typeset -A opt_args