README.md

  1<!--
  2SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  3
  4SPDX-License-Identifier: Unlicense
  5-->
  6
  7# synu
  8
  9Universal wrapper for LLM agents that tracks
 10[Synthetic](https://synthetic.new) usage and interactively preconfigures
 11supported agents for currently-available models (so you can try a new
 12one as soon as they support it, without waiting for the agent itself to
 13gain support!)
 14
 15## Requirements
 16
 17- Fish
 18- `curl` - for API requests
 19- `jq` - for JSON parsing
 20- `gum` - for interactive model selection
 21  ([install](https://github.com/charmbracelet/gum))
 22- `SYNTHETIC_API_KEY` environment variable (for quota tracking with
 23  Synthetic)
 24
 25## Installation
 26
 27### Using Fundle
 28
 29Add to your `~/.config/fish/config.fish`:
 30
 31```fish
 32fundle plugin 'synu' --url 'https://git.secluded.site/synu'
 33fundle init
 34```
 35
 36Then reload your shell or run `fundle install`.
 37
 38## Configuration
 39
 40Set your Synthetic API key in your `~/.config/fish/config.fish`:
 41
 42```fish
 43# For Synthetic API quota tracking
 44set -gx SYNTHETIC_API_KEY your_api_key_here
 45```
 46
 47## Usage
 48
 49Use `synu` as a wrapper for any AI agent:
 50
 51```fish
 52# Check current quota
 53synu
 54
 55# Use with configured agents (auto-routed through Synthetic)
 56synu claude "What does functions/synu.fish do?"
 57synu opencode "Help me refactor this"
 58synu aider "Fix the bug in main.go"
 59
 60# Use with other agents (passthrough with quota tracking)
 61synu crush "Help me write code"
 62
 63# Any other agent or command
 64synu [agent-name] [agent-args...]
 65```
 66
 67> **Note**: synu's configuration is ephemeral and non-invasive. Running
 68> `synu claude` routes requests through Synthetic, but running `claude`
 69> directly still uses Anthropic's API with your normal configuration.
 70> synu never modifies the agent's own config files.
 71
 72### Interactive Model Selection
 73
 74Use `synu i <agent>` to fetch the list of available models and
 75interactively filter/select them using gum:
 76
 77```fish
 78synu i claude "prompt"
 79synu i opencode "prompt"
 80synu i aider "prompt"
 81```
 82
 83You'll be asked whether to save your selection as the default for future
 84sessions.
 85
 86### Persistent Preferences
 87
 88Model selections made in interactive mode can be saved to
 89`~/.config/synu/models.conf`. These become the new defaults until
 90changed. Command-line flags always override saved preferences.
 91
 92## Configured Agents
 93
 94### Claude Code
 95
 96| Tier | Default Model |
 97|------|---------------|
 98| Opus | `hf:moonshotai/Kimi-K2-Thinking` |
 99| Sonnet | `hf:zai-org/GLM-4.6` |
100| Haiku | `hf:deepseek-ai/DeepSeek-V3.1-Terminus` |
101| Subagent | `hf:zai-org/GLM-4.6` |
102
103**Override flags:**
104
105```fish
106# Override specific models
107synu claude --opus hf:other/model "prompt"
108synu claude --sonnet hf:other/model "prompt"
109synu claude --haiku hf:other/model "prompt"
110synu claude --agent hf:other/model "prompt"
111
112# Group overrides
113synu claude --large hf:model "prompt"  # Sets Opus, Sonnet, and Subagent
114synu claude --light hf:model "prompt"  # Sets Haiku
115```
116
117### OpenCode
118
119| Default Model |
120|---------------|
121| `hf:zai-org/GLM-4.6` |
122
123```fish
124synu opencode --model hf:other/model "prompt"
125```
126
127### Aider
128
129| Slot | Default Model |
130|------|---------------|
131| Main | `hf:zai-org/GLM-4.6` |
132| Editor | `hf:deepseek-ai/DeepSeek-V3.1-Terminus` |
133
134```fish
135# Single model mode
136synu aider --model hf:some/model "prompt"
137
138# Architect + editor mode (two models)
139synu aider --model hf:architect/model --editor-model hf:editor/model "prompt"
140```
141
142### llxprt
143
144| Default Model |
145|---------------|
146| `hf:zai-org/GLM-4.6` |
147
148```fish
149synu llxprt --model hf:other/model "prompt"
150```
151
152### Qwen Code
153
154| Default Model |
155|---------------|
156| `hf:zai-org/GLM-4.6` |
157
158```fish
159synu qwen --model hf:other/model "prompt"
160```
161
162## How it works
163
164`synu` works by:
165
1661. Loading agent-specific configuration if available
1672. Fetching initial quota from the Synthetic API before running the
168   agent
1693. Configuring the agent's environment/CLI args to route through
170   Synthetic
1714. Executing the specified agent with all provided arguments
1725. Cleaning up environment variables after execution
1736. Fetching final quota and displaying session usage
174
175The quota tracking requires the `SYNTHETIC_API_KEY` environment
176variable. Without it, `synu` will show a warning and skip quota
177tracking, but still attempt to run the agent.
178
179## Shell completions
180
181Synu includes fish shell completions for configured agents and their flags.
182
183## Contributions
184
185Patch requests are in [amolith/llm-projects] on [pr.pico.sh]. You don't need a
186new account to contribute, you don't need to fork this repo, you don't need to
187fiddle with `git send-email`, you don't need to faff with your email client to
188get `git request-pull` working...
189
190You just need:
191
192- Git
193- SSH
194- An SSH key
195
196```sh
197# Clone this repo, make your changes, and commit them
198# Create a new patch request with
199git format-patch origin/main --stdout | ssh pr.pico.sh pr create amolith/llm-projects
200# After potential feedback, submit a revision to an existing patch request with
201git format-patch origin/main --stdout | ssh pr.pico.sh pr add {prID}
202# List patch requests
203ssh pr.pico.sh pr ls amolith/llm-projects
204```
205
206See "How do Patch Requests work?" on [pr.pico.sh]'s home page for a more
207complete example workflow.
208
209[amolith/llm-projects]: https://pr.pico.sh/r/amolith/llm-projects
210[pr.pico.sh]: https://pr.pico.sh