Local Chimaera UI protocol fixture

<a href="https://chimaera.sh/"> <img src="site/assets/img/og-workspace-2026-10.png" alt="Chimaera. A workspace for everything you do with agents. Your agents. Your files. Local or remote." width="1200"> </a>
<a href="https://chimaera.sh/#download"><strong>Download</strong></a> · <a href="https://chimaera.sh/#workspace">Explore the workspace</a> · <a href="https://chimaera.sh/docs.html">Docs</a> · <a href="docs/agent-guides/plugins.md">Build an extension</a>
<a href="https://github.com/martinappberg/chimaera/releases/latest"><img alt="Latest release" src="https://img.shields.io/github/v/release/martinappberg/chimaera"></a> <a href="LICENSE"><img alt="License: AGPL-3.0" src="https://img.shields.io/badge/license-AGPL--3.0-blue.svg"></a> <img alt="Platforms: macOS, Linux, Windows beta" src="https://img.shields.io/badge/platforms-macOS%20%7C%20Linux%20%7C%20Windows%20(beta)-lightgrey.svg">
Chimaera is an open-source agent workbench. Open a project folder and put your agents, files, and tools side by side. Read a document while an agent works on it. Inspect a table, review a diff, or run a web app beside the conversation. Work on your own machine or connect to a remote host.
It runs your own Claude Code, Codex, Antigravity, or Grok Build, with the accounts, skills, and connections configured on that host. Your agents do the work. Chimaera gives you a place to direct it, see the results, and keep the project in view.
Get started · Inside the workspace · Run from the command line · Build from source · Development
| Platform | Native app |
|---|---|
| macOS | Apple Silicon, .dmg |
| Linux | x86_64, AppImage, .deb, or .rpm |
| Windows | x64 installer, with the daemon and agents running in WSL2; beta |
Installation and platform setup · All releases
Keep several agents in the same project. Use structured chat or an agent terminal, see questions and approvals in the dashboard, and follow recent activity. Agents can exchange messages within the workspace. An optional Mastermind coordinator helps brief you and direct the work.
All four supported agents have structured chat. Claude Code and Codex also let you switch the same conversation between chat and their real terminal interfaces. Provider authentication, usage limits, and billing apply to the mode you use.
Open Markdown, PDFs, Word documents, spreadsheets, slide decks, tables, images, notebooks, diagrams, video, audio, and HTML reports. Keep a live web app in a browser pane. Edit text and Markdown directly. Give an agent a file reference, text selection, table cell, image region, or media timestamp as context.
The file manager handles uploads, downloads, moves, and copies. Git views bring status, diffs, history, and worktrees into the workspace. Session history records changes even in folders without a Git repository.
Files and previews · Browser panes · Git
Follow activity in Timeline and catch up through the dashboard. Keep source files, notes, and decisions beside the conversation. Knowledge extensions make findings, decisions, and handoffs recorded in project files browsable in the workspace.
Timeline and Knowledge · Dashboard · Session history
Connect through your existing SSH configuration. Chimaera installs its server on the remote host and opens the workspace through a tunnel. Files, agents, and tools run on that host. On Slurm clusters, start a job and open workspaces on its compute node from the same app.
SSH connections · Slurm workspaces
Extensions add views, file viewers, and tools for your agents. Workbench plugins are WebAssembly components installed separately and enabled per workspace. They can reuse Chimaera's UI, publish project context and diagnostics, and expose tools to agents through declared capabilities. The Extensions view also brings together your agents' plugins, skills, and connections.
Using extensions · Extension authoring guide for people and agents
The standalone chimaera binary serves the same web UI as the native app. Download it for your host from the latest release and make it executable. For example, on Linux x86_64:
curl -fL https://github.com/martinappberg/chimaera/releases/latest/download/chimaera-x86_64-unknown-linux-musl -o chimaera
chmod +x chimaera
./chimaera serve
Open the http://127.0.0.1:…/#token=… URL printed in the terminal. The daemon binds to loopback and chooses a free port; use serve --port 9700 to choose one yourself. The agent CLIs run on this host and need their own installation and provider login.
With chimaera on your PATH, connect to a remote host using its SSH alias:
chimaera connect work-server
Chimaera deploys a matching server, starts it, and opens a tunnel. Remote deployment requires no root access or containers. Static Linux binaries support x86_64 and aarch64 without a system glibc dependency. Scheduler-equipped hosts use the cluster workflow to run workspaces inside Slurm jobs.
Useful commands:
chimaera status # inspect the local daemon
chimaera status work-server # inspect a remote host
chimaera doctor # check local paths and prerequisites
chimaera plugin list # list available and installed workbench plugins
You need Node 22, npm, Rust through rustup, and a C/C++ build toolchain. The repository pins Rust in rust-toolchain.toml; rustup selects it automatically. Run these commands on macOS, Linux, or inside WSL2 on Windows. Build the UI first because the daemon embeds it.
git clone https://github.com/martinappberg/chimaera
cd chimaera
npm --prefix web-ui ci
npm --prefix web-ui run build
cargo build --locked --release -p chimaera
./target/release/chimaera serve
A source checkout uses isolated development state under ~/.chimaera-dev until release version stamping. It does not share the installed app's state. Building or running the daemon does not require building plugins.
The native app is a separate Tauri workspace in crates/chimaera-app. See contributor setup for native development and verification.
The server is Rust, the web UI is Svelte 5, and the native shell is Tauri 2. The same daemon and web UI power local and remote workspaces.
| Directory | Contents |
|---|---|
crates/ | CLI, daemon, PTY engine, agent protocols, remote connections, plugin API, and native app |
web-ui/ | Svelte workspace UI |
plugins/ | Curated plugin lock and host test fixtures; released plugins live in their own repositories |
site/ | Public website and usage docs |
docs/ | Feature guides, developer guides, and design records |
scripts/ | Build, verification, and repository maintenance tools |
After the UI build above, install just and run:
npm --prefix web-ui run check # Svelte and TypeScript checks
npm --prefix web-ui run test # targeted Vitest suites
just check # plugin test assets, then Rust fmt, clippy, and tests
node scripts/check-doc-links.mjs
node scripts/check-agent-assets.mjs
For an isolated daemon or native-app preview, follow the development workflow. It gives the checkout its own state and port. The contributing guide covers the full loop and the checks required for each kind of change.
Chimaera is licensed under the GNU AGPL-3.0. A commercial license is available for closed-source products and services: contact the author. Contributions require the Contributor License Agreement; see contributing for the process.
hooks/register.js 36 lines1let count = 0;
2let value = 'Initial';
3let selected = 'one';
4export function register(on) {
5 on('session.start', async ($, e, next) => {
6 await $.command.register({name:'chimaera-mod-test',description:'Open test pane',immediate:true});
7 return next(e);
8 });
9 on('session.attach', async ($, e, next) => { await $.ui.open({id:'chimaera-test',title:'Mod controls',closeOnEscape:true}); return next(e); });
10 on('command.run', {command:'chimaera-mod-test'}, async ($) => {await $.ui.open({id:'chimaera-test',title:'Mod controls',closeOnEscape:true}); return {};});
11 on('ui.render', {component:'Pane'}, async ($, e, next) => {
12 if(e.requestId !== 'chimaera-test') return next(e);
13 const {Box,Text,Button,Input,Select,Markdown,Code,Client}= $.ui.resolve(e);
14 const redraw=()=>$.ui.invalidate('ui.render');
15 return Box({flexDirection:'column',gap:1,children:[
16 Text({bold:true,children:['Live Claude Mod']}),
17 Text({children:['Count: '+count+' / '+value+' / '+selected]}),
18 Button({key:'increment',label:'Add one',onPress:()=>{count++;redraw();}}),
19 Input({key:'name',label:'Name',value,onInput:(s)=>{value=s;redraw();},onSubmit:(s)=>{value=s;redraw();}}),
20 Select({key:'choice',label:'Choice',value:selected,options:[{value:'one',label:'One'},{value:'two',label:'Two'}],onSelect:(s)=>{selected=s;redraw();}}),
21 Markdown({text:'**Markdown** with a [link](https://example.com)'}),
22 Code({source:'const count = 1;',language:'javascript'}),
23 Client({key:'client-counter',module:'./counter.tsx',props:{label:'Local counter'}}),
24 Box({flexDirection:'row',gap:1,children:[
25 Button({key:'fill',label:'Fill composer',onPress:async()=>{await $.prompt.fill({text:'Mod draft',mode:'replace',decorations:[{start:0,end:3,bold:true,color:'green'}]});}}),
26 Button({key:'append',label:'Append note',onPress:async()=>{await $.prompt.fill({text:' note',mode:'append',decorations:[{start:1,end:5,italic:true}]});}}),
27 Button({key:'suggest',label:'Suggest draft',onPress:async()=>{await $.prompt.suggest({text:'Suggested by the Mod'});}}),
28 Button({key:'copy',label:'Copy text',onPress:async()=>{await $.ui.copy({text:'Mod copied text',surface:'desktop'});}})
29 ]})
30 ]});
31 });
32 on('ui.render', {component:'AbovePrompt'}, async ($, e, next) => {
33 const {Text}= $.ui.resolve(e); return Text({children:['Fixture ready · '+count]});
34 });
35}
36hooks/counter.tsx 19 lines1export default function Counter(props, surface) {
2 const {Box,Text,Button} = surface.elements;
3 const state = surface.state ?? {count:0,key:'none',pointer:'none'};
4 const patch = (value) => surface.setState({...surface.state ?? state,...value});
5 surface.onKey((event)=>patch({key:event.key}));
6 surface.onPointer((event)=>{
7 if(event.type === 'down' || event.type === 'up') patch({pointer:event.type+' '+event.x+','+event.y});
8 });
9 return Box({flexDirection:'column',children:[
10 Text({children:[props.label + ': ' + state.count]}),
11 Text({children:['Key: '+state.key+' · Pointer: '+state.pointer]}),
12 Text({children:['Viewport: '+surface.columns+' × '+surface.rows]}),
13 Box({flexDirection:'row',gap:1,children:[
14 Button({key:'local-add',label:'Add locally',onPress:()=>patch({count:(surface.state?.count ?? 0)+1})}),
15 Button({key:'post',label:'Post count',onPress:()=>surface.post({count:state.count})})
16 ]})
17 ]});
18}
19