Initial Claude launcher profiles

This commit is contained in:
Dieter Schlüter 2026-06-28 01:50:13 +02:00
commit 7fd845235c
7 changed files with 258 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
config/profiles.yml
*.log
.DS_Store

66
README.md Normal file
View file

@ -0,0 +1,66 @@
# claude-launcher-profiles
Portable Claude Code launcher profiles for Anthropic Pro and OpenRouter models.
## Ziel
Claude Code über einfache Profile starten:
- `claude-pro`
- `claude-glm`
- `claude-kimi`
- `claude-free`
- `claude-profile <name>`
Die eigentliche Konfiguration liegt in einer YAML-Datei.
## Voraussetzungen
- `claude` installiert
- funktionierendes Claude-Pro-Login für das `pro`-Profil
- `bash`
- `yq` zum Parsen der YAML-Datei
Beispiel Debian/Ubuntu:
```bash
sudo apt-get update
sudo apt-get install -y yq
```
## Setup
```bash
git clone https://kitux.de/forgejo/dschlueter/claude-launcher-profiles.git
cd claude-launcher-profiles
cp config/profiles.example.yml config/profiles.yml
$EDITOR config/profiles.yml
chmod +x bin/claude-profile bin/install-claude-profiles lib/profiles.sh
./bin/install-claude-profiles
source ~/.bashrc
```
## Nutzung
```bash
claude-pro
claude-glm
claude-kimi
claude-free
```
Oder generisch:
```bash
claude-profile pro
claude-profile glm
claude-profile kimi
```
## Sicherheit
`config/profiles.yml` enthält echte Keys und wird nicht committed.
Nur `config/profiles.example.yml` gehört ins Repo.

15
bin/claude-profile Executable file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=/dev/null
source "$SCRIPT_DIR/../lib/profiles.sh"
PROFILE="${1:-}"
if [[ -z "$PROFILE" ]]; then
echo "Usage: claude-profile <profile>"
exit 1
fi
launch_profile "$PROFILE"

24
bin/install-claude-profiles Executable file
View file

@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
TARGET_DIR="$HOME/src"
TARGET_REPO="$TARGET_DIR/claude-launcher-profiles"
BASHRC="$HOME/.bashrc"
ALIAS_LINE="source $TARGET_REPO/shell/aliases.sh"
mkdir -p "$TARGET_DIR"
if [[ "$REPO_DIR" != "$TARGET_REPO" ]]; then
if [[ ! -e "$TARGET_REPO" ]]; then
ln -s "$REPO_DIR" "$TARGET_REPO"
fi
fi
if ! grep -Fq "$ALIAS_LINE" "$BASHRC" 2>/dev/null; then
printf '\n# claude-launcher-profiles\n%s\n' "$ALIAS_LINE" >> "$BASHRC"
fi
echo "Installed. Run: source ~/.bashrc"

View file

@ -0,0 +1,23 @@
defaults:
claude_cmd: "claude"
openrouter_base_url: "https://openrouter.ai/api"
profiles:
pro:
mode: "pro"
glm:
mode: "openrouter"
openrouter_api_key: "REPLACE_ME"
model: "z-ai/glm-5.2"
kimi:
mode: "openrouter"
openrouter_api_key: "REPLACE_ME"
model: "moonshotai/kimi-k2.7-code"
free:
mode: "openrouter"
openrouter_api_key: "REPLACE_ME"
model: "openrouter/free"

121
lib/profiles.sh Executable file
View file

@ -0,0 +1,121 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root() {
local script_dir
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
printf '%s\n' "$script_dir"
}
config_file() {
printf '%s/config/profiles.yml\n' "$(repo_root)"
}
require_yq() {
command -v yq >/dev/null 2>&1 || {
echo "Error: yq is required but not installed." >&2
exit 1
}
}
require_config() {
local cfg
cfg="$(config_file)"
[[ -f "$cfg" ]] || {
echo "Error: missing config file: $cfg" >&2
echo "Create it from config/profiles.example.yml" >&2
exit 1
}
}
cfg_get() {
local expr="$1"
yq -r "$expr // \"\"" "$(config_file)"
}
profile_exists() {
local profile="$1"
[[ "$(cfg_get ".profiles.${profile}.mode")" != "" ]]
}
clear_claude_env() {
unset OPENROUTER_API_KEY
unset ANTHROPIC_BASE_URL
unset ANTHROPIC_AUTH_TOKEN
unset ANTHROPIC_API_KEY
unset ANTHROPIC_MODEL
unset ANTHROPIC_DEFAULT_OPUS_MODEL
unset ANTHROPIC_DEFAULT_SONNET_MODEL
unset ANTHROPIC_DEFAULT_HAIKU_MODEL
unset CLAUDE_CODE_SUBAGENT_MODEL
}
resolve_env_ref() {
local value="$1"
if [[ "$value" =~ ^\$[A-Za-z_][A-Za-z0-9_]*$ ]]; then
local var_name="${value:1}"
printf '%s\n' "${!var_name:-}"
else
printf '%s\n' "$value"
fi
}
launch_profile() {
local profile="$1"
local mode claude_cmd base_url api_key model
require_yq
require_config
profile_exists "$profile" || {
echo "Error: profile '$profile' not found in $(config_file)" >&2
exit 1
}
claude_cmd="$(cfg_get '.defaults.claude_cmd')"
[[ -n "$claude_cmd" ]] || claude_cmd="claude"
mode="$(cfg_get ".profiles.${profile}.mode")"
clear_claude_env
case "$mode" in
pro)
echo "Claude Pro profile active"
exec "$claude_cmd"
;;
openrouter)
base_url="$(cfg_get '.defaults.openrouter_base_url')"
[[ -n "$base_url" ]] || base_url="https://openrouter.ai/api"
api_key="$(cfg_get ".profiles.${profile}.openrouter_api_key")"
api_key="$(resolve_env_ref "$api_key")"
model="$(cfg_get ".profiles.${profile}.model")"
[[ -n "$api_key" && "$api_key" != "REPLACE_ME" ]] || {
echo "Error: openrouter_api_key missing for profile '$profile'" >&2
exit 1
}
[[ -n "$model" ]] || {
echo "Error: model missing for profile '$profile'" >&2
exit 1
}
export OPENROUTER_API_KEY="$api_key"
export ANTHROPIC_BASE_URL="$base_url"
export ANTHROPIC_AUTH_TOKEN="$OPENROUTER_API_KEY"
export ANTHROPIC_API_KEY=""
export ANTHROPIC_MODEL="$model"
echo "OpenRouter profile active: $profile -> $model"
exec "$claude_cmd"
;;
*)
echo "Error: unsupported mode '$mode' for profile '$profile'" >&2
exit 1
;;
esac
}

5
shell/aliases.sh Executable file
View file

@ -0,0 +1,5 @@
alias claude-pro="$HOME/src/claude-launcher-profiles/bin/claude-profile pro"
alias claude-glm="$HOME/src/claude-launcher-profiles/bin/claude-profile glm"
alias claude-kimi="$HOME/src/claude-launcher-profiles/bin/claude-profile kimi"
alias claude-free="$HOME/src/claude-launcher-profiles/bin/claude-profile free"