Summary
A custom harness definition (<app-data>/custom_harnesses/<id>.json) describes exactly one runtime entry. When a runtime has a profile-per-directory layout (one command, several isolated homes), the only way to offer each home as a pickable runtime today is one hand-written definition file per profile, kept in sync by hand: add or rename a profile and the runtime dropdown is stale until someone regenerates those files.
This proposes letting one definition declare a variants block, so Buzz derives one catalog entry per detected profile directory from it.
Proposed shape
{
"id": "hermes-profiles",
"label": "Hermes Agent",
"command": "hermes-acp",
"modelSelection": "harness",
"variants": {
"dir": "~/.hermes/profiles",
"marker": "profile.yaml",
"idTemplate": "{id}-{slug}",
"labelTemplate": "{label} [{meta}] ({name})",
"labelFrom": { "file": "profile.yaml", "key": "ui_meta.hermes-bots.title" },
"env": { "HERMES_HOME": "{dir}" }
}
}
dir + marker: which directories count, by marker file, so a directory that is not a profile of that runtime is skipped.
idTemplate / labelTemplate: {id}, {label}, {name} (directory name), {slug} (id-safe directory name), and {meta} from labelFrom.
labelFrom: read one dotted key out of a file in the profile directory (a persona title, for example), so the entry can read Hermes Agent [Generalist] (generalist) rather than just the folder name.
args / env placeholders: {name}, {slug}, {dir} (the profile directory), {root} (the scanned directory), so the spawned process is pointed at its own profile.
- Expansion is capped, and a definition with no
variants returns exactly itself as one entry, so nothing changes for existing definitions.
Two things go with it:
- Generated entries are read-only. They carry
generated + generated_from, render without an edit affordance, and name the definition file the user should edit instead. Editing a derived entry would otherwise be silently overwritten by the next scan.
modelSelection: "harness". Optional, on any definition. When a runtime owns model choice, the agent config renderer omits the model field with the named reason ownedByHarnessSelection instead of showing a picker whose value the harness ignores.
The primitive is deliberately not tied to any one runtime. It covers a profile root, a per-project agent config dir, or any future profile-per-directory layout, and needs no runtime-specific code in the desktop shell.
Related existing reports
Searched open and closed PRs and issues for "harness profile", "custom harness variants", "harness definition profiles", "definitionVariants", "generated_from harness", "variants block harness": no existing work on this primitive.
Closest adjacent reports:
Status
Implementation is written, tested, and on a branch, with 12 Rust unit tests driven through the existing load_custom_harnesses / save_custom_harness_to_dir seam, a browser spec that asserts the read-only row and the omitted model picker, and two proof frames. PR to follow and cross-link here.
Summary
A custom harness definition (
<app-data>/custom_harnesses/<id>.json) describes exactly one runtime entry. When a runtime has a profile-per-directory layout (one command, several isolated homes), the only way to offer each home as a pickable runtime today is one hand-written definition file per profile, kept in sync by hand: add or rename a profile and the runtime dropdown is stale until someone regenerates those files.This proposes letting one definition declare a
variantsblock, so Buzz derives one catalog entry per detected profile directory from it.Proposed shape
{ "id": "hermes-profiles", "label": "Hermes Agent", "command": "hermes-acp", "modelSelection": "harness", "variants": { "dir": "~/.hermes/profiles", "marker": "profile.yaml", "idTemplate": "{id}-{slug}", "labelTemplate": "{label} [{meta}] ({name})", "labelFrom": { "file": "profile.yaml", "key": "ui_meta.hermes-bots.title" }, "env": { "HERMES_HOME": "{dir}" } } }dir+marker: which directories count, by marker file, so a directory that is not a profile of that runtime is skipped.idTemplate/labelTemplate:{id},{label},{name}(directory name),{slug}(id-safe directory name), and{meta}fromlabelFrom.labelFrom: read one dotted key out of a file in the profile directory (a persona title, for example), so the entry can readHermes Agent [Generalist] (generalist)rather than just the folder name.args/envplaceholders:{name},{slug},{dir}(the profile directory),{root}(the scanned directory), so the spawned process is pointed at its own profile.variantsreturns exactly itself as one entry, so nothing changes for existing definitions.Two things go with it:
generated+generated_from, render without an edit affordance, and name the definition file the user should edit instead. Editing a derived entry would otherwise be silently overwritten by the next scan.modelSelection: "harness". Optional, on any definition. When a runtime owns model choice, the agent config renderer omits the model field with the named reasonownedByHarnessSelectioninstead of showing a picker whose value the harness ignores.The primitive is deliberately not tied to any one runtime. It covers a profile root, a per-project agent config dir, or any future profile-per-directory layout, and needs no runtime-specific code in the desktop shell.
Related existing reports
Searched open and closed PRs and issues for "harness profile", "custom harness variants", "harness definition profiles", "definitionVariants", "generated_from harness", "variants block harness": no existing work on this primitive.
Closest adjacent reports:
Status
Implementation is written, tested, and on a branch, with 12 Rust unit tests driven through the existing
load_custom_harnesses/save_custom_harness_to_dirseam, a browser spec that asserts the read-only row and the omitted model picker, and two proof frames. PR to follow and cross-link here.