From e4a244c619813e4c3942c6d9f32416a99c74ebaf Mon Sep 17 00:00:00 2001 From: Kirill Korikov Date: Sun, 6 Sep 2026 12:07:45 +0400 Subject: [PATCH 1/4] docs: HarnessKit integration design notes --- docs/harnesskit-integration.md | 78 ++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 docs/harnesskit-integration.md diff --git a/docs/harnesskit-integration.md b/docs/harnesskit-integration.md new file mode 100644 index 0000000..3c43dde --- /dev/null +++ b/docs/harnesskit-integration.md @@ -0,0 +1,78 @@ +# HarnessKit integration — design notes + +Status: draft / thinking. Branch: `feat/harnesskit-integration`. Date: 2026-09-06. + +## Finding + +[HarnessKit](https://github.com/RealZST/HarnessKit) (RealZST/HarnessKit, Rust, Apache-2.0, ~420★, active) is a web UI (also desktop/CLI) that inspects and manages agent extensions, configs, memory, and rules across 13 harnesses. Verified live against the maintainer's machine on 2026-09-06: it detects and reads the **full dotagents stack** — Claude Code, Codex, **Oh My Pi** (`~/.omp/agent/`), **Hermes** (`~/.hermes/`), plus Gemini CLI, Copilot, OpenCode, Grok Build. This is exactly the coverage (Pi/OMP + Hermes) that CCO and ai-config-sync-manager lack. + +Consequence: dotagents does **not** need to build its own config viewer. HarnessKit already does the read/inspect/audit surface better than we would from scratch, and on every harness we care about. + +## Why integrate, and the one boundary rule + +HarnessKit and dotagents are complementary, not competing: + +- **HarnessKit** = read/inspect/audit dashboard + marketplace. Reads *materialized native dirs*. Its write model is **convergence** ("deploy this extension to every agent"). +- **dotagents** = sync engine + source of truth. Manages the 5 surfaces (skills, MCP, hooks, roles, plugins) via symlinks + `dotagents.lock` + intentional per-harness divergence. + +**Boundary invariant for this integration:** dotagents stays the only writer. HarnessKit is consumed read-mostly. We never route dotagents' managed surfaces *through* HarnessKit's convergence writer, and we never let HK's "deploy to all" become the mechanism that mutates a dotagents-owned symlink. Divergence is a feature here, not drift — HK's model treats it as drift, so its write path is off-limits for managed surfaces. + +## Integration levels + +### L0 — Recommend (docs only, zero coupling) + +Name HarnessKit in `README.md`, `docs/comparison.md`, and the `dotagents` skill as the inspection dashboard: "dotagents owns sync; use HarnessKit to see/audit the result across harnesses." No code. Ships today. + +### L1 — Optional dependency (`deps` / `setup`) + +Register HarnessKit as an **optional, opt-in** external tool: + +- `dotagents setup` offers (never forces) HK install after the first sync, gated behind a prompt. +- `dotagents deps check` reports whether HK is present + version; `deps update` bumps it. +- Honor the existing publish-age gate (`checkExternalPackageAge`, `package_age.go`) — HK is a fast-moving Rust binary; do not auto-pull a release younger than the configured window. + +Install method is an **open question** (see below) — do not hardcode one until verified. + +### L2 — Launch command (`dotagents view`) + +New subcommand that starts HK pointed at the active dotagents config root and opens the browser: + +- Resolves the config root the same way the rest of the CLI does (`--config` → `$DOTAGENTS_HOME` → `~/.agents`). +- Spawns the HK local server (127.0.0.1, token in URL — as observed at `:7070`), prints the URL, optionally opens it. Mirrors the existing external-CLI launch path (`external_cli.go`, `cli_launch_test.go`). +- Read-only intent: we launch HK as a viewer over what dotagents already materialized. + +L0–L2 are the concrete near-term scope. All three keep the boundary invariant trivially (no managed-surface writes). + +### L3 — Write-through (research spike, do not build yet) + +The "can we drive changes from HK's UI via dotagents commands" question. HK writes to native dirs directly; dotagents owns those via symlinks/lock. Reconciling them needs one of: + +- **(a) HK-as-frontend:** HK calls `dotagents` as its backend for mutations. Requires HK to expose a pluggable write backend — **not known to exist**; would need an upstream change or fork. Verify before assuming. +- **(b) Watch-and-reconcile:** dotagents watches HK's writes and folds them back into the canonical store + re-syncs. Fragile (race with HK's own convergence writes), and it inverts the source-of-truth direction. + +Both risk exactly the drift the boundary invariant forbids. Treat L3 as a spike with a written go/no-go, not a committed feature. Likely outcome: keep writes in dotagents; if HK-authored edits are wanted, add a `dotagents import` path that pulls a specific HK change into the canonical store deliberately, rather than a live bridge. + +## Codebase seams (verified in-tree) + +- `cmd/dotagents/deps.go` — `deps check`/`update`, already wraps external-package-age. Home for L1. +- `cmd/dotagents/setup.go`, `setup_scaffold.go` — first-run; add the opt-in HK prompt here. +- `cmd/dotagents/external.go`, `external_cli.go`, `cli_launch_test.go` — external tool materialization + launch. Model for L2. +- `cmd/dotagents/detect.go`, `harness.go` — harness detection; useful if HK install is only offered when ≥1 supported harness is present. +- `cmd/dotagents/report.go`, `inspect.go` — the `status`/`inspect` output; where a "view in HarnessKit" pointer could surface. + +## Open questions (need verification, do not guess) + +1. **HK install method** — GitHub release binary vs `cargo install` vs `brew`. Check the repo's releases/install docs before wiring L1. +2. **HK headless/CLI mode** — does HK expose a non-interactive "start server on port X, no onboarding" invocation suitable for `dotagents view`? The web UI ran a 3-step onboarding wizard on first open; confirm it can be skipped/scripted. +3. **Config-root targeting** — can HK be pointed at an arbitrary config root (for `--config`/`$DOTAGENTS_HOME` setups), or does it only scan default `~/.` paths? Observed it reading default paths (`~/.omp`, `~/.hermes`); custom-root support unconfirmed. +4. **Pluggable write backend (L3)** — does HK have any hook/API to delegate mutations? Assume no until shown. +5. **Publish-age policy fit** — HK releases cadence vs the 3-day external-package rule; pick a window. + +## Recommended first slice + +Ship **L0 + L2** first; hold L1's auto-install behind the package-age answer: + +1. L0 docs pointer (README + comparison + skill). +2. `dotagents view` that launches HK against the resolved config root, read-only framing. Answer open questions #2 and #3 as part of this slice. +3. Then L1 opt-in install once #1 and #5 are settled. +4. L3: separate spike doc, no code, decision recorded here. From c6401d36c141ea96b376034455e6df03a8f4d7f0 Mon Sep 17 00:00:00 2001 From: Kirill Korikov Date: Sun, 6 Sep 2026 12:16:59 +0400 Subject: [PATCH 2/4] feat: add dotagents view to launch HarnessKit read-only inspector --- README.md | 3 +++ cmd/dotagents/main.go | 3 +++ cmd/dotagents/view.go | 47 ++++++++++++++++++++++++++++++++++ cmd/dotagents/view_test.go | 33 ++++++++++++++++++++++++ docs/harnesskit-integration.md | 30 +++++++++++++--------- skills/dotagents/SKILL.md | 9 +++++++ 6 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 cmd/dotagents/view.go create mode 100644 cmd/dotagents/view_test.go diff --git a/README.md b/README.md index 875867b..b178c9a 100644 --- a/README.md +++ b/README.md @@ -81,10 +81,13 @@ dotagents setup [--memory off|basic|memsearch] [--yes] [--dry-run] [--json] dotagents status [--agents ...] dotagents sync [--pull] [--agents ...] dotagents doctor [--e2e] [--agents ...] +dotagents view [--port N] [--host ADDR] # launch HarnessKit (read-only inspector) dotagents skill new|update|promote dotagents mcp list|add|import|remove ``` +`dotagents view` shells out to [HarnessKit](https://github.com/RealZST/HarnessKit) (`hk serve`) for a read-only web UI over every detected harness — skills, MCP servers, hooks, and configs in one place. dotagents stays the only writer; use it to inspect and audit, not to deploy. Install HarnessKit separately. + ## Configuration `~/.agents/dotagents.yaml` is the single source of truth; `setup` fills in detected harnesses. Resolution order: `--config ` → `$DOTAGENTS_HOME/dotagents.yaml` → `~/.agents/dotagents.yaml`; never walks the current project. Machine-local entries overlay via `dotagents.local.yaml`. Managed entries are marked in native configs; anything else is left untouched. diff --git a/cmd/dotagents/main.go b/cmd/dotagents/main.go index 49bf74a..53cfdef 100644 --- a/cmd/dotagents/main.go +++ b/cmd/dotagents/main.go @@ -139,6 +139,8 @@ func run(args []string) error { return runSyncCommand(args[1:]) case "doctor": return runDoctorCommand(args[1:]) + case "view": + return runView(args[1:]) case "skill": return runSkillCommand(args[1:]) case "mcp": @@ -490,6 +492,7 @@ func printAllUsage() { fmt.Println(" dotagents status [--agents ...]") fmt.Println(" dotagents sync [--pull] [--agents ...]") fmt.Println(" dotagents doctor [--e2e] [--agents ...]") + fmt.Println(" dotagents view [hk serve flags: --port N, --host ADDR, --no-token]") fmt.Println(" dotagents skill new [--description ...]") fmt.Println(" dotagents skill update [name ...]") fmt.Println(" dotagents skill promote [--dry-run]") diff --git a/cmd/dotagents/view.go b/cmd/dotagents/view.go new file mode 100644 index 0000000..e3b7b2b --- /dev/null +++ b/cmd/dotagents/view.go @@ -0,0 +1,47 @@ +package main + +import ( + "errors" + "fmt" + "os" + "os/exec" +) + +// hkBinary is the HarnessKit CLI that `dotagents view` launches as a read-only +// cross-harness inspector. dotagents stays the only writer of the five managed +// surfaces; HarnessKit is consumed purely as a viewer over the materialized +// native harness directories, so `view` never mutates managed config. +const hkBinary = "hk" + +// hkLookPath is indirected so tests can exercise the missing-binary path +// without depending on the host PATH. +var hkLookPath = exec.LookPath + +const hkInstallHint = `HarnessKit (hk) not found on PATH. + +dotagents view launches HarnessKit as a read-only cross-harness inspector for +skills, MCP servers, hooks, and configs across every detected agent. + +Install it from https://github.com/RealZST/HarnessKit, then re-run "dotagents view".` + +// hkServeArgs builds the argv for the underlying `hk serve` invocation. Extra +// args are forwarded verbatim to hk serve (e.g. --port, --host, --no-token). +func hkServeArgs(passthrough []string) []string { + return append([]string{"serve"}, passthrough...) +} + +// runView launches the HarnessKit web UI over the materialized native harness +// dirs. Read-only by intent: dotagents remains the source of truth, so this +// command inspects but never writes managed surfaces. +func runView(args []string) error { + path, err := hkLookPath(hkBinary) + if err != nil { + return errors.New(hkInstallHint) + } + fmt.Fprintln(os.Stdout, "Launching HarnessKit (read-only). dotagents stays the source of truth — avoid HarnessKit's enable/disable/deploy actions on dotagents-managed skills, MCP, and hooks.") + cmd := exec.Command(path, hkServeArgs(args)...) // nosemgrep: go.lang.security.audit.dangerous-exec-command + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} diff --git a/cmd/dotagents/view_test.go b/cmd/dotagents/view_test.go new file mode 100644 index 0000000..e719065 --- /dev/null +++ b/cmd/dotagents/view_test.go @@ -0,0 +1,33 @@ +package main + +import ( + "errors" + "reflect" + "strings" + "testing" +) + +func TestHKServeArgs(t *testing.T) { + if got := hkServeArgs(nil); !reflect.DeepEqual(got, []string{"serve"}) { + t.Fatalf("hkServeArgs(nil) = %v, want [serve]", got) + } + got := hkServeArgs([]string{"--port", "8080"}) + want := []string{"serve", "--port", "8080"} + if !reflect.DeepEqual(got, want) { + t.Fatalf("hkServeArgs passthrough = %v, want %v", got, want) + } +} + +func TestRunViewMissingBinary(t *testing.T) { + orig := hkLookPath + t.Cleanup(func() { hkLookPath = orig }) + hkLookPath = func(string) (string, error) { return "", errors.New("not found") } + + err := runView(nil) + if err == nil { + t.Fatal("expected error when hk binary is missing") + } + if !strings.Contains(err.Error(), "HarnessKit") || !strings.Contains(err.Error(), "github.com/RealZST/HarnessKit") { + t.Fatalf("error should guide install, got: %v", err) + } +} diff --git a/docs/harnesskit-integration.md b/docs/harnesskit-integration.md index 3c43dde..9e47c91 100644 --- a/docs/harnesskit-integration.md +++ b/docs/harnesskit-integration.md @@ -4,7 +4,7 @@ Status: draft / thinking. Branch: `feat/harnesskit-integration`. Date: 2026-09-0 ## Finding -[HarnessKit](https://github.com/RealZST/HarnessKit) (RealZST/HarnessKit, Rust, Apache-2.0, ~420★, active) is a web UI (also desktop/CLI) that inspects and manages agent extensions, configs, memory, and rules across 13 harnesses. Verified live against the maintainer's machine on 2026-09-06: it detects and reads the **full dotagents stack** — Claude Code, Codex, **Oh My Pi** (`~/.omp/agent/`), **Hermes** (`~/.hermes/`), plus Gemini CLI, Copilot, OpenCode, Grok Build. This is exactly the coverage (Pi/OMP + Hermes) that CCO and ai-config-sync-manager lack. +[HarnessKit](https://github.com/RealZST/HarnessKit) (RealZST/HarnessKit, Rust, Apache-2.0, ~420★, active) is a web UI (also desktop/CLI) that inspects and manages agent extensions, configs, memory, and rules across 13 harnesses. Verified live against a full stack install on 2026-09-06: it detects and reads the **full dotagents stack** — Claude Code, Codex, **Oh My Pi** (`~/.omp/agent/`), **Hermes** (`~/.hermes/`), plus Gemini CLI, Copilot, OpenCode, Grok Build. This is exactly the coverage (Pi/OMP + Hermes) that CCO and ai-config-sync-manager lack. Consequence: dotagents does **not** need to build its own config viewer. HarnessKit already does the read/inspect/audit surface better than we would from scratch, and on every harness we care about. @@ -60,19 +60,25 @@ Both risk exactly the drift the boundary invariant forbids. Treat L3 as a spike - `cmd/dotagents/detect.go`, `harness.go` — harness detection; useful if HK install is only offered when ≥1 supported harness is present. - `cmd/dotagents/report.go`, `inspect.go` — the `status`/`inspect` output; where a "view in HarnessKit" pointer could surface. -## Open questions (need verification, do not guess) +## Open questions -1. **HK install method** — GitHub release binary vs `cargo install` vs `brew`. Check the repo's releases/install docs before wiring L1. -2. **HK headless/CLI mode** — does HK expose a non-interactive "start server on port X, no onboarding" invocation suitable for `dotagents view`? The web UI ran a 3-step onboarding wizard on first open; confirm it can be skipped/scripted. -3. **Config-root targeting** — can HK be pointed at an arbitrary config root (for `--config`/`$DOTAGENTS_HOME` setups), or does it only scan default `~/.` paths? Observed it reading default paths (`~/.omp`, `~/.hermes`); custom-root support unconfirmed. -4. **Pluggable write backend (L3)** — does HK have any hook/API to delegate mutations? Assume no until shown. -5. **Publish-age policy fit** — HK releases cadence vs the 3-day external-package rule; pick a window. +Resolved 2026-09-06 by inspecting `hk` 1.10.0 (`hk --help`, `hk serve --help`, `hk list --help`): + +1. **HK headless/CLI mode — RESOLVED (yes).** `hk serve` is fully scriptable: `--port`, `--host`, `--token`/`--no-token`, `--name`. The 3-step onboarding is client-side UI state, not a server gate. HK also ships a pure CLI — `hk status`, `hk list --json`, `hk audit`, `hk info`, `hk enable/disable` — so a future text/status integration can consume `hk list --json` without the web server. +2. **Config-root targeting — RESOLVED (no flag, not needed).** `hk serve`/`hk list` have no `--config`/`--root`; only `HK_SCOPE_LAST_USED` (scope memory). HK reads the native harness homes (`~/.claude`, `~/.codex`, `~/.omp`, `~/.hermes`), which is exactly what dotagents materializes — so `view` targets the right thing for the default `~/.agents` root. Custom `$DOTAGENTS_HOME`/`--config` only relocates dotagents' YAML, not the harness homes HK reads, so no retargeting is required. +3. **HK binary/version — RESOLVED.** `hk` 1.10.0, Mach-O arm64, installed at `~/.local/bin/hk`. + +Still open (gate L1, not L2): + +4. **HK install method (L1)** — release binary vs `cargo install` vs `brew` tap. Verify from HK's releases/install docs before wiring an opt-in installer. +5. **Publish-age policy fit (L1)** — HK's release cadence vs the 3-day external-package rule (`package_age.go`); pick a window. +6. **Pluggable write backend (L3)** — does HK expose any hook/API to delegate mutations? Assume no until shown. ## Recommended first slice -Ship **L0 + L2** first; hold L1's auto-install behind the package-age answer: +**L0 + L2, now unblocked** (open questions #1–#3 resolved in HK's favor): -1. L0 docs pointer (README + comparison + skill). -2. `dotagents view` that launches HK against the resolved config root, read-only framing. Answer open questions #2 and #3 as part of this slice. -3. Then L1 opt-in install once #1 and #5 are settled. -4. L3: separate spike doc, no code, decision recorded here. +1. L0 docs pointer — README + `dotagents` SKILL + CLI help. Pointer only, no duplicated harness-compat table. +2. `dotagents view` — thin launcher: `exec.LookPath("hk")`, forward args to `hk serve`, read-only framing, install hint when absent. Implemented on this branch (`cmd/dotagents/view.go`, `view_test.go`). +3. L1 opt-in install — deferred until #4 and #5 are settled. +4. L3 — separate spike, no code; decision recorded here. diff --git a/skills/dotagents/SKILL.md b/skills/dotagents/SKILL.md index cefedc9..5e854a4 100644 --- a/skills/dotagents/SKILL.md +++ b/skills/dotagents/SKILL.md @@ -22,6 +22,7 @@ dotagents setup [--memory off|basic|memsearch] [--agents ...] [--yes] [--dry-run dotagents status [--agents ...] dotagents sync [--pull] [--agents ...] dotagents doctor [--e2e] [--agents ...] +dotagents view [--port N] [--host ADDR] dotagents skill new [--description ...] dotagents skill update [name ...] dotagents skill promote [--dry-run] @@ -119,6 +120,14 @@ Runs sync, status, and doctor as one health check. It fails on drift, conflicts, dotagents doctor --e2e ``` +## view + +Launches [HarnessKit](https://github.com/RealZST/HarnessKit) (`hk serve`) as a read-only web UI over every detected harness — skills, MCP, hooks, and configs in one place, with a security audit. dotagents stays the only writer; `view` is for inspection and audit, not deployment. Requires `hk` on `PATH` (install HarnessKit separately); flags are forwarded to `hk serve`. + +```bash +dotagents view --port 7070 +``` + ## Capability matrix | Harness | Skills | Roles | MCP | Hooks | From 171b2134cae503904cc0b9a0b69e4db007b66583 Mon Sep 17 00:00:00 2001 From: Kirill Korikov Date: Sun, 6 Sep 2026 13:25:20 +0400 Subject: [PATCH 3/4] fix: drop trailing punctuation in hk install hint (ST1005) --- cmd/dotagents/view.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/dotagents/view.go b/cmd/dotagents/view.go index e3b7b2b..0f4900b 100644 --- a/cmd/dotagents/view.go +++ b/cmd/dotagents/view.go @@ -22,7 +22,7 @@ const hkInstallHint = `HarnessKit (hk) not found on PATH. dotagents view launches HarnessKit as a read-only cross-harness inspector for skills, MCP servers, hooks, and configs across every detected agent. -Install it from https://github.com/RealZST/HarnessKit, then re-run "dotagents view".` +Install it from https://github.com/RealZST/HarnessKit, then re-run: dotagents view` // hkServeArgs builds the argv for the underlying `hk serve` invocation. Extra // args are forwarded verbatim to hk serve (e.g. --port, --host, --no-token). From 126b5e5be65216109c0ca532efdc749839ede6ae Mon Sep 17 00:00:00 2001 From: Kirill Korikov Date: Sun, 6 Sep 2026 13:29:10 +0400 Subject: [PATCH 4/4] docs: reframe view as inspection (HK writes not enforced); fix launch behavior notes --- README.md | 4 ++-- cmd/dotagents/view.go | 21 ++++++++++++--------- docs/harnesskit-integration.md | 10 +++++----- skills/dotagents/SKILL.md | 2 +- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index b178c9a..1c1b27d 100644 --- a/README.md +++ b/README.md @@ -81,12 +81,12 @@ dotagents setup [--memory off|basic|memsearch] [--yes] [--dry-run] [--json] dotagents status [--agents ...] dotagents sync [--pull] [--agents ...] dotagents doctor [--e2e] [--agents ...] -dotagents view [--port N] [--host ADDR] # launch HarnessKit (read-only inspector) +dotagents view [--port N] [--host ADDR] # launch HarnessKit (inspection UI) dotagents skill new|update|promote dotagents mcp list|add|import|remove ``` -`dotagents view` shells out to [HarnessKit](https://github.com/RealZST/HarnessKit) (`hk serve`) for a read-only web UI over every detected harness — skills, MCP servers, hooks, and configs in one place. dotagents stays the only writer; use it to inspect and audit, not to deploy. Install HarnessKit separately. +`dotagents view` shells out to [HarnessKit](https://github.com/RealZST/HarnessKit) (`hk serve`) for an inspection UI over every detected harness — skills, MCP servers, hooks, and configs in one place. HarnessKit does its own harness discovery and can also enable/disable/deploy; those writes bypass dotagents, so use `view` to inspect and reconcile any changes with `dotagents sync`. Install HarnessKit separately. ## Configuration diff --git a/cmd/dotagents/view.go b/cmd/dotagents/view.go index 0f4900b..652db7c 100644 --- a/cmd/dotagents/view.go +++ b/cmd/dotagents/view.go @@ -7,10 +7,12 @@ import ( "os/exec" ) -// hkBinary is the HarnessKit CLI that `dotagents view` launches as a read-only -// cross-harness inspector. dotagents stays the only writer of the five managed -// surfaces; HarnessKit is consumed purely as a viewer over the materialized -// native harness directories, so `view` never mutates managed config. +// hkBinary is the HarnessKit CLI that `dotagents view` launches as a +// cross-harness inspection surface over the materialized native harness dirs. +// The `view` command itself never writes. dotagents does NOT enforce read-only: +// the launched HarnessKit UI can enable/disable/deploy, and those writes go +// straight to native dirs, bypassing dotagents. The launch banner warns against +// using them on managed surfaces; reconcile any drift with `dotagents sync`. const hkBinary = "hk" // hkLookPath is indirected so tests can exercise the missing-binary path @@ -19,7 +21,7 @@ var hkLookPath = exec.LookPath const hkInstallHint = `HarnessKit (hk) not found on PATH. -dotagents view launches HarnessKit as a read-only cross-harness inspector for +dotagents view launches HarnessKit as a cross-harness inspection surface for skills, MCP servers, hooks, and configs across every detected agent. Install it from https://github.com/RealZST/HarnessKit, then re-run: dotagents view` @@ -30,15 +32,16 @@ func hkServeArgs(passthrough []string) []string { return append([]string{"serve"}, passthrough...) } -// runView launches the HarnessKit web UI over the materialized native harness -// dirs. Read-only by intent: dotagents remains the source of truth, so this -// command inspects but never writes managed surfaces. +// runView starts `hk serve` (forwarding its stdio, which prints the tokenized +// URL) so the user can inspect every harness in HarnessKit's web UI. The +// launcher itself writes nothing; the banner cautions that HarnessKit's own +// write actions bypass dotagents. func runView(args []string) error { path, err := hkLookPath(hkBinary) if err != nil { return errors.New(hkInstallHint) } - fmt.Fprintln(os.Stdout, "Launching HarnessKit (read-only). dotagents stays the source of truth — avoid HarnessKit's enable/disable/deploy actions on dotagents-managed skills, MCP, and hooks.") + fmt.Fprintln(os.Stdout, "Launching HarnessKit for inspection. Note: HarnessKit can also enable/disable/deploy, and those writes bypass dotagents — avoid them on dotagents-managed skills, MCP, and hooks (reconcile drift with: dotagents sync).") cmd := exec.Command(path, hkServeArgs(args)...) // nosemgrep: go.lang.security.audit.dangerous-exec-command cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout diff --git a/docs/harnesskit-integration.md b/docs/harnesskit-integration.md index 9e47c91..3cee303 100644 --- a/docs/harnesskit-integration.md +++ b/docs/harnesskit-integration.md @@ -35,11 +35,11 @@ Install method is an **open question** (see below) — do not hardcode one until ### L2 — Launch command (`dotagents view`) -New subcommand that starts HK pointed at the active dotagents config root and opens the browser: +New subcommand that starts `hk serve` and forwards its stdio, which prints the tokenized URL for the user to open: -- Resolves the config root the same way the rest of the CLI does (`--config` → `$DOTAGENTS_HOME` → `~/.agents`). -- Spawns the HK local server (127.0.0.1, token in URL — as observed at `:7070`), prints the URL, optionally opens it. Mirrors the existing external-CLI launch path (`external_cli.go`, `cli_launch_test.go`). -- Read-only intent: we launch HK as a viewer over what dotagents already materialized. +- HarnessKit does its own harness discovery over the native homes (`~/.claude`, `~/.omp`, `~/.hermes`, …), so `view` does not load or pass the dotagents config root; a nonstandard `--config`/`$DOTAGENTS_HOME` only relocates dotagents' YAML, not the harness homes HK reads. +- Spawns the HK local server (127.0.0.1, token in URL — as observed at `:7070`) and prints the URL; the launcher does not open a browser itself. Mirrors the existing external-CLI launch path (`external_cli.go`, `cli_launch_test.go`). +- Inspection intent, not enforced: `hk serve` has no read-only mode, so HarnessKit's own enable/disable/deploy actions can still write native dirs and bypass dotagents. The launch banner warns against using them on managed surfaces; reconcile drift with `dotagents sync`. L0–L2 are the concrete near-term scope. All three keep the boundary invariant trivially (no managed-surface writes). @@ -79,6 +79,6 @@ Still open (gate L1, not L2): **L0 + L2, now unblocked** (open questions #1–#3 resolved in HK's favor): 1. L0 docs pointer — README + `dotagents` SKILL + CLI help. Pointer only, no duplicated harness-compat table. -2. `dotagents view` — thin launcher: `exec.LookPath("hk")`, forward args to `hk serve`, read-only framing, install hint when absent. Implemented on this branch (`cmd/dotagents/view.go`, `view_test.go`). +2. `dotagents view` — thin launcher: `exec.LookPath("hk")`, forward args to `hk serve`, inspection framing (writes not enforced — banner cautions), install hint when absent. Implemented on this branch (`cmd/dotagents/view.go`, `view_test.go`). 3. L1 opt-in install — deferred until #4 and #5 are settled. 4. L3 — separate spike, no code; decision recorded here. diff --git a/skills/dotagents/SKILL.md b/skills/dotagents/SKILL.md index 5e854a4..788bb8d 100644 --- a/skills/dotagents/SKILL.md +++ b/skills/dotagents/SKILL.md @@ -122,7 +122,7 @@ dotagents doctor --e2e ## view -Launches [HarnessKit](https://github.com/RealZST/HarnessKit) (`hk serve`) as a read-only web UI over every detected harness — skills, MCP, hooks, and configs in one place, with a security audit. dotagents stays the only writer; `view` is for inspection and audit, not deployment. Requires `hk` on `PATH` (install HarnessKit separately); flags are forwarded to `hk serve`. +Launches [HarnessKit](https://github.com/RealZST/HarnessKit) (`hk serve`) as an inspection web UI over every detected harness — skills, MCP, hooks, and configs in one place, with a security audit. The `view` command writes nothing, but HarnessKit's own enable/disable/deploy actions bypass dotagents; treat `view` as inspect/audit and reconcile any HarnessKit changes with `dotagents sync`. Requires `hk` on `PATH` (install HarnessKit separately); flags are forwarded to `hk serve`. ```bash dotagents view --port 7070