development
md 208 lines 10.2 KB
Rendered Raw
1 # SplitFire AI Agent
2
3 Play like you mean it.
4
5 A music assistant that speaks the [Agent Client Protocol](https://agentclientprotocol.com) and
6 ships its own terminal UI. It covers music theory, production and DAW workflow, the music
7 industry, culture and history, and live shows, and it does the arithmetic with tools instead of
8 guessing: note spelling, chords, keys, tempo maths and audio measurements are computed, not
9 recalled by the model.
10
11 It runs on [Onde Inference](https://ondeinference.com) (Onde Cloud). Built on the official
12 [Rust SDK](https://github.com/agentclientprotocol/rust-sdk).
13
14 ## What it can do
15
16 **Music theory tools** (exact, read-only, no permission prompts)
17
18 | Tool | Does |
19 |------|------|
20 | `theory_scale` | Spell a scale or mode from any root, with intervals, key signature and the diatonic chords (C# major really has E# and B#) |
21 | `theory_chord` | Spell a chord symbol (`F#m7b5`, `Bb13#11/D`, `C6/9`) or identify chords from notes |
22 | `theory_transpose` | Transpose chords or notes by semitones or between keys, with correct enharmonic spelling |
23 | `theory_progression` | Roman numerals, functions, secondary dominants, borrowed chords and ranked key candidates; or realize numerals (`ii7 V7 Imaj7`) in a key |
24 | `theory_tempo` | Note values (straight, dotted, triplet) in ms and Hz, bar length, sample counts, bpm from a loop length |
25 | `theory_pitch` | Note name, MIDI number and frequency conversion, with cents offset and adjustable A4 |
26
27 **Audio analysis**: `analyze_audio` reads WAV, FLAC, MP3, OGG, M4A/AAC and AIFF and reports
28 duration, sample rate, channels, peak, RMS, integrated loudness (LUFS), and estimated tempo
29 (including half and double time) and key with a confidence. Tempo and key are signal-analysis
30 estimates, and the agent says so. Audio attached to a prompt is saved to a scratch file and the
31 model is given its path.
32
33 **Project files**: `read_file`, `write_file`, `edit_file`, `list_directory`, `run_command`, with
34 permission prompts for writes and commands, multi-root workspaces, and the client's own
35 `fs/*` and `terminal/*` methods when the editor offers them.
36
37 **Slash commands**: `/analyze <file>`, `/chords <progression>`, `/practice <goal>`, and
38 `/stems <file>` when stem separation is installed.
39
40 **Sessions** persist across restarts: `session/list`, `load` (with tool calls and their output
41 replayed), `resume`, `close` and `delete`.
42
43 ### Stem separation (optional)
44
45 Stem separation is not built in. Install [`demucs`](https://github.com/splitfireai/demucs-rs) and
46 put it on your `PATH` (or set `SPLITFIRE_DEMUCS_BIN`). SplitFire starts `demucs --mcp` the first
47 time a session begins, and offers `separate_stems` and `list_models` as tools. Separation runs
48 locally and can take minutes; the first use of a model downloads its weights, and the permission
49 prompt tells you how large the download is. If `demucs` is missing or fails to start, SplitFire
50 logs one line and carries on without it. An MCP server named `demucs` supplied by your editor
51 takes precedence. `SPLITFIRE_MCP_DEMUCS=off` disables it.
52
53 Apps that embed SplitFire decide what stems mean the same way. They pass a `demucs` MCP server of
54 their own in `session/new`, or return no built-in servers from their `Profile` and write their own
55 stems guidance. The SplitFire AI Audio Separator supplies its own executable in `--mcp` mode on
56 its on-device engine; KaroKowe Jam and KaroKowe Karaoke supply none and point users at their in-app flows. The stem
57 hooks only check the tool name `mcp__demucs__separate_stems` and the `list_models` and
58 `separate_stems` result shapes (`structuredContent.models[]{id,size_mb,cached}` and
59 `structuredContent.stems[].path`).
60
61 Separate only music you have the right to work with.
62
63 ### Other MCP servers
64
65 Stdio MCP servers configured in your editor are connected for each session. Their tools show up
66 as `mcp__<server>__<tool>`, ask for permission unless the server marks them read-only, stream
67 progress into the tool call, and are cancelled when you cancel the turn. A server that fails to
68 start is skipped.
69
70 ## Embedding
71
72 A sandboxed app (an App Store build) can't launch the agent as a subprocess, so it runs it
73 in-process: it serves [`SplitFire`] with `ed_acp::serve` over an in-memory channel and talks to
74 it as a regular ACP client. The app-neutral half of that — the client, sessions, permissions,
75 the key store — lives in the published [`ed-acp-tauri`](https://crates.io/crates/ed-acp-tauri)
76 crate. The SplitFire-only pieces live here, behind the off-by-default `embed` feature:
77
78 ```toml
79 splitfire-agent = { version = "1.2", default-features = false, features = ["embed"] }
80 ed-acp-tauri = "1.3"
81 ed-acp = "1.3"
82 ```
83
84 `splitfire_agent::embed` has no `tauri` dependency; anything that needs the app's identifier
85 takes it as a `&str`:
86
87 - `embed::fetch_key(url, access_token, app_identifier)` asks the SplitFire API for the signed-in
88 user's Onde key, rejecting with `SIGN_IN_REQUIRED` or `UNAVAILABLE`.
89 - `embed::splitfire_mcp(url, access_token, app_identifier)` builds the SplitFire API's MCP server
90 for a session (nothing without a token).
91 - `embed::trim` drops `run_command` from the toolsets (`without_commands`) and swaps the stems
92 paragraph (`replace_no_stems`) for a profile that runs where it can't start processes, e.g.
93 iOS.
94
95 All embedding apps must resolve a single `ed-acp` 1.3.x, so an `Arc<dyn Profile>` from this crate
96 matches the one `ed-acp-tauri` expects.
97
98 ## Install and set up
99
100 ```sh
101 cargo build --release # -> target/release/splitfire-agent
102 splitfire-agent --setup
103 ```
104
105 `--setup` asks for your Onde credentials (`app-id:app-secret`, from
106 [ondeinference.com](https://ondeinference.com/root/login): register an app and assign a model),
107 checks them against Onde Cloud, and stores them in the platform config directory
108 (`~/Library/Application Support/splitfire-agent/env` on macOS, `~/.config/splitfire-agent/env` on
109 Linux, `%APPDATA%\splitfire-agent\env` on Windows). Alternatively set `ONDE_API_KEY`.
110
111 Editors that can run terminal auth (`clientCapabilities.auth.terminal`) are offered `--setup` as
112 the authentication method. Until a key exists the agent answers `session/new`, `session/load`,
113 `session/resume` and `session/prompt` with `AUTH_REQUIRED`. A key stored by `--setup` is picked up
114 without a restart, whether or not the editor calls `authenticate` afterwards. `logout` removes the
115 stored key (a key exported as `ONDE_API_KEY` stays in effect).
116
117 ## Use from the terminal
118
119 ```sh
120 cd my-project
121 splitfire-agent # asks before edits and commands
122 splitfire-agent --yolo # approves everything
123 ```
124
125 Enter sends, Esc cancels a running turn, Up/Down and PgUp/PgDn scroll, Ctrl-C or `/quit` exits.
126 Approval prompts take `y` (allow), `a` (always allow this tool), `n` (reject) or `r` (always reject this tool). The TUI is itself
127 an ACP client: it starts `splitfire-agent --acp` as a subprocess.
128
129 ## Use with Zed
130
131 Editors launch the agent with piped stdio, which selects ACP mode (or pass `--acp`).
132
133 ```json
134 {
135 "agent_servers": {
136 "splitfire-agent": {
137 "command": "/path/to/splitfire-agent",
138 "args": ["--acp"]
139 }
140 }
141 }
142 ```
143
144 The model picker lists the models Onde Cloud serves for your app. Editors that support boolean
145 config options also get an "Auto-approve actions" toggle per thread. Threads are saved to disk, so
146 Zed can reopen and import them after a restart; a thread whose history is gone reopens empty with
147 a short notice instead of failing. Linked files (`@`-mentions and selections) are inlined, only
148 the selected lines for a selection; links to audio files are handed to `analyze_audio` instead.
149 Token usage is reported against `SPLITFIRE_CONTEXT_WINDOW`.
150
151 ## Configuration
152
153 | Env var | Default | |
154 |---------|---------|---|
155 | `ONDE_API_KEY` | from the config `env` file | `app-id:app-secret`; required |
156 | `SPLITFIRE_BASE_URL` | `https://cloud.ondeinference.com/v1` | override the OpenAI-compatible endpoint |
157 | `SPLITFIRE_MODEL` | `onde-kkk` | default model |
158 | `SPLITFIRE_MODELS` | listed from `/models` | comma-separated list for the model picker |
159 | `SPLITFIRE_YOLO` | unset | `1` skips permission prompts (the default for each thread's auto-approve toggle) |
160 | `SPLITFIRE_CONTEXT_WINDOW` | `128000` | context size reported in `usage_update` |
161 | `SPLITFIRE_STEMS_DIR` | the app's iCloud and local folders | where `list_separations` looks for separated songs |
162 | `SPLITFIRE_DATA_DIR` | platform config dir | where `env`, sessions and scratch audio live |
163 | `SPLITFIRE_SURFACE` | `acp` | `tui` when launched by the terminal UI; used in the commit trailer |
164 | `SPLITFIRE_DEMUCS_BIN` | `demucs` on `PATH` | stem separation binary |
165 | `SPLITFIRE_MCP_DEMUCS` | on | `off` disables stem separation |
166 | `RUST_LOG` | unset | logs go to stderr |
167
168 `splitfire-agent --list-models` prints the models your endpoint serves.
169
170 ## Development
171
172 ```sh
173 cargo fmt -- --check
174 cargo clippy --all-targets -- -D warnings
175 cargo test --locked
176 ```
177
178 These are exactly what CI runs. To catch the formatting check before you push, enable the
179 tracked pre-commit hook once per clone:
180
181 ```sh
182 git config core.hooksPath .githooks
183 ```
184
185 SplitFire is built on the Onde Agent Platform crates in the
186 [`onde-ed`](https://github.com/ondeinference/ed) workspace, checked out next to this repository:
187 `ed-acp` (the ACP server: sessions, auth, the turn loop, approval, workspace tools),
188 `ed-acp-tui` (the terminal UI) and `ed-mcp` (MCP over `rmcp`). This crate holds the music.
189
190 The integration tests run the real binary against a scripted mock model and a test MCP server
191 (`src/bin/mcp_stdio_stub.rs`, from `ed-mcp`). `tests/acp_compliance.rs` runs the platform's ACP
192 conformance suite from `ed-acp-testkit` plus SplitFire's own tests. `tests/live.rs` talks to Onde
193 Cloud and is skipped unless `ONDE_API_KEY` is set.
194
195 ```
196 src/main.rs flags and mode dispatch (ACP, TUI, --setup, --list-models)
197 src/profile.rs the ed-acp Profile: identity, tools, commands, built-in demucs
198 src/prompt.rs system prompt and slash commands
199 src/tools/ theory, audio analysis and separation-library tools
200 src/theory/ pitch, interval, scale, chord, key, tempo
201 src/audio/ decoding and analysis
202 registry/ ACP registry submission
203 ```
204
205 ## Copyright
206
207 © 2026 [Splitfire AB](https://5mb.app) ([SplitFire AI](https://splitfire.ai)). Licensed under the
208 Apache License, Version 2.0; see [LICENSE](LICENSE).