AGENTS.md

 1<!--
 2SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 3
 4SPDX-License-Identifier: Unlicense
 5-->
 6
 7# AGENTS.md
 8
 9## Project Overview
10
11**synclaude.fish** is a Fish shell wrapper for the `claude` CLI that routes requests through [Synthetic.new](https://synthetic.new)'s API. It enables using alternative AI models through the Claude CLI by proxying requests through Synthetic's Anthropic-compatible endpoint.
12
13### Key Functionality
14
15- Configurable model defaults for each Claude tier with persistent caching
16- Provides interactive TUI for model selection using `gum`
17- Supports group-based (`--heavy`/`--medium`/`--light`) and individual model overrides
18- Displays session API usage and remaining quota after each run
19- `synclaude u` shows current quota usage
20- Wraps `claude` CLI completely - all unknown flags pass through
21
22### Default Models (Fallbacks)
23
24- **Opus**: `hf:moonshotai/Kimi-K2-Thinking`
25- **Sonnet**: `hf:zai-org/GLM-4.6`
26- **Haiku**: `hf:deepseek-ai/DeepSeek-V3.1-Terminus`
27- **Sub-agent**: `hf:zai-org/GLM-4.6`
28
29### Architecture
30
31**Control Flow:**
32
331. **Usage mode** (`synclaude u`):
34   - Fetches and displays current quota usage with colored badge
352. **Interactive mode** (`synclaude i`):
36   - Fetches available models from Synthetic API
37   - Prompts user to choose Groups vs Individual models
38   - Prompts for which groups/models to override
39   - Shows current defaults in filter headers
40   - Offers to save selections as new defaults
41   - Recursively calls `synclaude` with generated flags
423. **Flag-based mode** (default):
43   - Parses custom flags with `argparse --ignore-unknown`
44   - Loads defaults from cache (or fallbacks)
45   - Applies group then individual overrides
46   - Sets environment variables for Anthropic endpoint
47   - Fetches initial quota from Synthetic API
48   - Executes `command claude $argv`
49   - Fetches final quota and displays usage stats with badge-style color-coding
50
51**Key Design Patterns:**
52
53- **Caching**: Persistent model preferences stored in `~/.config/synclaude/models.conf`
54- **Override precedence**: Individual flags override group flags, which override cached/fallback defaults
55- **Error propagation**: Uses `or return` throughout to exit on command failures
56
57## Common Gotchas
58
591. **`argparse --ignore-unknown` is critical**: Without it, unknown flags would error instead of passing through to `claude`
602. **Recursive call must use function name, not alias**: `synclaude` not `command synclaude` - this works because Fish functions can recursively invoke themselves
613. **`_flag_*` variable naming**: `argparse` creates variables from flag names with `_flag_` prefix - must use exact names
624. **Model ID vs Model Name**: Interactive mode fetches model names for display but must extract model IDs for API use
635. **jq requires argument quoting**: In jq, use `--arg name "$var"` then `$name` in filter - don't interpolate directly into filter string
646. **Quota check timing**: Initial quota fetch happens before `claude` runs to calculate session usage. If it fails, script continues anyway
657. **`math` precision**: Use `-s0` for integer output to avoid decimal points in quota percentages
668. **Local exports don't persist**: `set -lx` variables only exist in function scope - won't affect parent shell
679. **Cache file location**: Respects `XDG_CONFIG_HOME` if set, otherwise defaults to `~/.config/synclaude/`