Agent harnesses move to a config registry, with Muse and Grok on board - #79
Conversation
…sets, hooks and titles (Muse and Grok included) Why: every new agent CLI meant touching Rust across the daemon and the TUI, and turning one off meant code-adjacent settings. Follow-up to AgentSystemLabs#66. What: a harnesses map in config (built-ins compiled in, user entries merged over them, legacy keys folded in as fallback) now drives n, e, spawn, resume, hooks and session titles. The New session dialog and the Agents settings tab render one section per entry, with ? and s jumping to its settings. Muse ships as a built-in row; Grok needed only a config block. Broken entries isolate per harness with a warning.
|
this PR basically makes #67 possible very easily. @webdevcody let me know if you want me to add |
|
let me spend some time thinking about if this is the approach I want to take moving forward, but so far the idea seems good. I honestly only use claude code and codex for most of my development, so allowing a user to configure other harnesses for their own needs is nice, but I do think this opens another attack surface for the config.json might now have commands nebula executes on bootup and those config files are pushed to remote servers on |
nebula ssh forwards config.json to the remote by default, and a harnesses entry can repoint program at any binary the remote daemon then executes on session spawn. Remote-scope exports now strip harnesses and custom_harnesses (backups keep them), with a stderr note, so each machine only ever runs programs its own files name.
|
You were right, and my first answer understated it: a Just pushed a fix for it: Remote-scope exports now strip
What still syncs: everything else in |
…ext, not shell syntax `probe_cli` asked the login shell `command -v '<program>'` with the name pasted in bare. Before the registry that name came from a fixed table; now it comes from config.json, where a single quote closes the word and the rest of the string runs as a command — at daemon boot, since `warm_cli_probes` asks for every entry, so no session has to be created. The word now goes through `shell_quote`, the escaping the launch path already applies to every argument, so it is looked up verbatim. Built-in names produce the identical line they always did (`command -v 'claude'`). The test pins both: the unchanged built-in lines, and that a hostile name fails the lookup quietly under a real /bin/sh instead of running. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
if you get time, update readme to explain how a user can setup a custom harness with hooks |
…ll wanted wrapped Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
https://github.com/kaminskypavel/nebula/tree/ft/muse-harness#teach-nebula-a-new-agent-cli also added a nice table |
Follow-up to #66: every agent CLI used to be a Rust edit across the daemon and the TUI, and turning one off meant code-adjacent settings. This PR puts all of it in one config table, so adding or tuning a harness no longer needs a rebuild, and it keeps working for everyone because the built-ins compile in.
What you get
harnessesmap in config drives thenpicker, theepresets, spawn, resume, hooks and session titles. User entries merge over the built-ins, legacy keys fold in as fallback, and a broken file falls back to defaults with a warning instead of refusing to start.?(ori) andsjump from the New session dialog straight to its settings.nebula config harnessesprints the merged table, so you can see what the daemon sees.Proof it is easy now: Muse and Grok
Muse ships as one built-in descriptor row. Grok needed only a config block (binary path, model flag, session flag; it has no hooks dialect, so it uses process-based status and fresh boot). No Rust changed for either, and the Grok session below is live.
How it works
Descriptors live in
nebula-core/harness.rs(flags, resume, system prompt, hooks dialect, effort presets). The daemon merges config over the built-ins at load; the TUI reads the same table instead of its old static specs. Users without aharnesseskey inconfig.jsonsee all five built-ins automatically.Risk
Low. Reads are lenient and failures isolate per harness, existing configs are untouched, and model behavior is unchanged (suite counts below). Rollback:
git revertrestores the static table, and aharnesseskey left inconfig.jsonis ignored by older builds since config parsing does not deny unknown fields.Gate
cargo testgreen: core 30, daemon 265, TUI 831, plus new registry/merge coverage.e2e_tuihas 2 failures that reproduce identically on clean HEAD (pre-existing).make ci(fmt/clippy) still needs a run where those tools exist.