@agntn/harnesses 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/dist/THIRD-PARTY-LICENSES.md +36 -0
  4. package/dist/_chunks/agents-sync.d.mts +417 -0
  5. package/dist/_chunks/agents-sync.d.mts.map +1 -0
  6. package/dist/_chunks/agents-sync.mjs +2719 -0
  7. package/dist/_chunks/agents-sync.mjs.map +1 -0
  8. package/dist/_chunks/agents.mjs +62 -0
  9. package/dist/_chunks/agents.mjs.map +1 -0
  10. package/dist/_chunks/libs/typebox.mjs +5512 -0
  11. package/dist/_chunks/libs/typebox.mjs.map +1 -0
  12. package/dist/_chunks/mcp-servers.mjs +149 -0
  13. package/dist/_chunks/mcp-servers.mjs.map +1 -0
  14. package/dist/_chunks/mcp.mjs +164 -0
  15. package/dist/_chunks/mcp.mjs.map +1 -0
  16. package/dist/_chunks/mcp2.mjs +17 -0
  17. package/dist/_chunks/mcp2.mjs.map +1 -0
  18. package/dist/_chunks/tool-operations.mjs +361 -0
  19. package/dist/_chunks/tool-operations.mjs.map +1 -0
  20. package/dist/_chunks/tool-schemas.d.mts +94 -0
  21. package/dist/_chunks/tool-schemas.d.mts.map +1 -0
  22. package/dist/_chunks/tool-schemas.mjs +112 -0
  23. package/dist/_chunks/tool-schemas.mjs.map +1 -0
  24. package/dist/_chunks/types.mjs +4 -0
  25. package/dist/_chunks/types.mjs.map +1 -0
  26. package/dist/cli.d.mts +1 -0
  27. package/dist/cli.mjs +350 -0
  28. package/dist/cli.mjs.map +1 -0
  29. package/dist/index.d.mts +300 -0
  30. package/dist/index.d.mts.map +1 -0
  31. package/dist/index.mjs +6 -0
  32. package/dist/index.mjs.map +1 -0
  33. package/dist/mcp.d.mts +15 -0
  34. package/dist/mcp.d.mts.map +1 -0
  35. package/dist/mcp.mjs +2 -0
  36. package/dist/tool-operations.d.mts +222 -0
  37. package/dist/tool-operations.d.mts.map +1 -0
  38. package/dist/tool-operations.mjs +3 -0
  39. package/dist/tool-schemas.d.mts +2 -0
  40. package/dist/tool-schemas.mjs +2 -0
  41. package/package.json +102 -0
  42. package/packages/omp/extensions/AGENTS.md +7 -0
  43. package/packages/omp/extensions/harnesses.ts +253 -0
  44. package/packages/pi/extensions/AGENTS.md +7 -0
  45. package/packages/pi/extensions/harnesses.ts +265 -0
  46. package/packages/shared/AGENTS.md +7 -0
  47. package/packages/shared/tui.ts +346 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 oritwoen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # @agntn/harnesses
2
+
3
+ [![npm version](https://img.shields.io/npm/v/%40agntn%2Fharnesses?style=flat&colorA=130f40&colorB=474787)](https://npmjs.com/package/@agntn/harnesses)
4
+ [![npm downloads](https://img.shields.io/npm/dm/%40agntn%2Fharnesses?style=flat&colorA=130f40&colorB=474787)](https://npm.chart.dev/@agntn/harnesses)
5
+ [![license](https://img.shields.io/github/license/agntn/harnesses?style=flat&colorA=130f40&colorB=474787)](https://github.com/agntn/harnesses/blob/main/LICENSE)
6
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/agntn/harnesses)
7
+
8
+ Metadata toolkit for AI coding harnesses. One registry of paths, formats, and detection rules for every major CLI.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pnpm add @agntn/harnesses
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```ts
19
+ import { getHarness, detectHarness, detectProjectHarnesses } from "@agntn/harnesses";
20
+
21
+ const claude = getHarness("claude");
22
+ console.log(claude.skills); // [{ path: ".claude/skills/", scope: "project", ... }, ...]
23
+ console.log(claude.hooks); // [{ path: ".claude/hooks/", scope: "project", ... }, ...]
24
+ console.log(claude.invocationModes); // advisor and full agent modes, no read-only mode
25
+
26
+ const codex = getHarness("codex");
27
+ await codex.invoke("Review this patch", { readOnly: true });
28
+
29
+ const pi = getHarness("pi");
30
+ const { models } = await pi.listModels({ search: "gpt-5.4" });
31
+ console.log(models); // [{ provider: "openai-codex", id: "gpt-5.4", ... }]
32
+ await pi.invoke("Review this patch", { model: "openai-codex/gpt-5.4" });
33
+
34
+ // Resolve to absolute paths for current platform
35
+ const paths = claude.resolve({ platform: "linux", homeDir: "/home/dev" });
36
+ console.log(paths.config); // [{ path: "/home/dev/.claude/settings.json", ... }, ...]
37
+
38
+ // Detect which agent is running (env vars first, then project markers)
39
+ const active = detectHarness();
40
+ if (active) {
41
+ console.log(`Running inside ${active.name}`);
42
+ }
43
+
44
+ // Find all agents configured in a project directory
45
+ const harnesses = detectProjectHarnesses("/path/to/project");
46
+ ```
47
+
48
+ Session schemas are typed per agent, so you get structure when parsing JSONL/SQLite/JSON files:
49
+
50
+ ```ts
51
+ import type { ClaudeSessionEntry, CodexThread, GeminiConversationRecord } from "@agntn/harnesses";
52
+ ```
53
+
54
+ ## Supported agents
55
+
56
+ | Agent | ID | Detection | Skills | Hooks | Sessions |
57
+ | --------------- | ---------------- | ------------- | --------------------- | ------------------------ | -------------- |
58
+ | Antigravity CLI | `antigravity` | project | `.agents/skills/` | - | JSONL + SQLite |
59
+ | Claude Code | `claude` | env + project | `.claude/skills/` | `.claude/hooks/` | JSONL |
60
+ | Codex CLI | `codex` | project | `.agents/skills/` | - | SQLite + JSONL |
61
+ | Gemini CLI | `gemini` | env + project | `.gemini/skills/` | - | JSON |
62
+ | Grok CLI | `grok` | env + project | `.grok/skills/` | `.grok/hooks/` | TOML + JSONL |
63
+ | OpenCode | `opencode` | project | `.opencode/skills/` | - | SQLite |
64
+ | Cursor | `cursor` | env + project | `.cursor/skills/` | - | - |
65
+ | GitHub Copilot | `github-copilot` | env + project | `.github/skills/` | - | - |
66
+ | Mastra Code | `mastracode` | project | `.mastracode/skills/` | `.mastracode/hooks.json` | SQLite |
67
+ | OMP (oh-my-pi) | `omp` | env + project | `.omp/skills/` | - | JSONL + SQLite |
68
+ | Pi Coding Agent | `pi` | env + project | `.pi/skills/` | - | JSON + JSONL |
69
+ | Freebuff | `freebuff` | project | `.agents/skills/` | - | JSON + JSONL |
70
+
71
+ ### Native audio and video input
72
+
73
+ `audio` and `video` report whether the harness has a verified native route that puts that medium into model context. External conversion, MCP tools, and voice dictation that becomes text do not count. `false` means no native route was verified, not that every possible provider or extension was disproved.
74
+
75
+ | Agent | Audio | Video | Evidence boundary |
76
+ | --------------- | :---: | :---: | --------------------------------------------------------------------------- |
77
+ | Antigravity CLI | Yes | Yes | Native attachments; documented audio formats and direct video pasting |
78
+ | Gemini CLI | Yes | No | The `read_file` tool supports audio; native video support is not documented |
79
+ | Claude Code | No | No | No verified native route |
80
+ | Codex CLI | No | No | No verified native route |
81
+ | Grok CLI | No | No | Its ACP parser recognizes audio blocks, but the runtime rejects them |
82
+ | OpenCode | No | No | Its attachment documentation explicitly excludes audio and video |
83
+ | Cursor | No | No | Voice input is transcribed to text |
84
+ | GitHub Copilot | No | No | Voice input is transcribed locally to text |
85
+ | Mastra Code | No | No | No verified native route |
86
+ | OMP (oh-my-pi) | No | No | No verified native route |
87
+ | Pi Coding Agent | No | No | No verified native route |
88
+ | Freebuff | No | No | No verified native route |
89
+
90
+ Primary references: [Antigravity prompting](https://antigravity.google/docs/cli/prompting/), [Antigravity changelog](https://github.com/google-antigravity/antigravity-cli/blob/main/CHANGELOG.md), [Gemini CLI tools](https://github.com/google-gemini/gemini-cli/blob/main/docs/reference/tools.md), [Gemini CLI video request](https://github.com/google-gemini/gemini-cli/issues/27194), [OpenCode attachments](https://opencode.ai/v2/docs/attachments/), [Cursor prompting](https://cursor.com/docs/agent/prompting), and [Copilot CLI voice input](https://docs.github.com/en/copilot/how-tos/copilot-cli/use-copilot-cli/voice-input).
91
+
92
+ Each agent is a concrete subclass of the abstract `Harness` class. Custom subclasses can be added with `registerHarness`. Every harness exposes config paths, session locations, instruction files, skills dirs, hooks, commands, persistence formats, capabilities (MCP, vision, audio, video, tools, streaming), detection rules, a normalized non-interactive invocation (`harness.invoke(prompt, { model })`) where the CLI has a headless mode, native model listing (`harness.listModels()`) where the CLI supports it, and its MCP server config files (`listMcpServers`/`addMcpServer`/`removeMcpServer` normalize the dialects; writes rewrite JSON and surgically edit TOML with comments preserved). `syncMcpServers` treats `~/.config/agntn/mcp.jsonc` (JSONC, XDG-aware) as the single source of truth and resets every harness's user-scope MCP config to exactly that list; a top-level `"excludes": ["codex"]` array opts individual harnesses out of the sync (their own servers stay, master-listed names are withdrawn), and `~`/`${HOME}` in commands, args, and env values expand to absolute paths at sync time (harnesses spawn MCP servers without a shell). `syncAgentsFiles` links every harness's global instructions file (CLAUDE.md/AGENTS.md/GEMINI.md) to one master file as symlinks, so an edit made through any harness lands in the single physical copy; `~/.config/agntn/agents.jsonc` sets the `source`, `companions`, and `excludes`, diverged regular files are backed up and relinked, and check mode reports without writing. Companion paths are relative to the source directory and are linked at the same relative path beside each harness target.
93
+
94
+ ```jsonc
95
+ {
96
+ "source": "bundle/AGENTS.md",
97
+ "companions": ["RULES.md"],
98
+ "excludes": ["codex"],
99
+ }
100
+ ```
101
+
102
+ All paths carry `scope` (user/project/system/data), `level` (official/community/inferred), and optional `platforms` tags.
103
+
104
+ The `harnesses_info` agent tool accepts one harness id or a batch of up to 20 ids. Batch results keep the input order and include errors for unknown ids beside successful metadata.
105
+
106
+ ## CLI
107
+
108
+ ```bash
109
+ harnesses list # all known harnesses
110
+ harnesses detect # which ones are installed + versions
111
+ harnesses info claude # metadata, including supported invocation modes
112
+ harnesses paths claude # resolved paths for current platform
113
+ harnesses info codex --json # machine-readable output
114
+ harnesses models pi # models available to Pi
115
+ harnesses models pi gpt-5.4 --json
116
+ harnesses run claude "review this design" # advisor without tools mode (default)
117
+ harnesses run pi --model openai-codex/gpt-5.4 "review this design"
118
+ harnesses run claude --tools "fix lint" # full agent with tools enabled
119
+ harnesses run codex --read-only "review this" # tools inside a native read-only sandbox
120
+ harnesses mcp-servers list # MCP servers configured across all harnesses
121
+ harnesses mcp-servers add omp probe --command node --args "srv.mjs mcp"
122
+ harnesses mcp-servers remove omp probe
123
+ harnesses mcp-servers sync # reset all harnesses to ~/.config/agntn/mcp.jsonc
124
+ harnesses agents sync --check # doctor: link global AGENTS.md files to one master
125
+ harnesses mcp # run the MCP server over stdio
126
+ ```
127
+
128
+ `tools` defaults to `false` in the library and CLI. The MCP, Pi, and OMP tools require agents to choose it explicitly. `false` must use a native CLI flag that removes tools from the model context; it is a lightweight advisor, not an agent constrained only by prompt wording. Set `tools: true` (or CLI `--tools`) whenever the task needs harness tools, including Grok's native X search. Add `readOnly: true` when those tools must stay inside a sandbox enforced by the harness CLI; the agent tools pass it beside `tools: true`, while the library and CLI let it imply tools. Read-only mode is rejected when a harness has no verified native recipe, so it never falls back to broader access. Harnesses whose CLI cannot disable tools reject advisor mode instead of silently running an agent and return an explicit `tools` retry when their full agent mode can handle the request.
129
+
130
+ ## How harnesses compares to unagent
131
+
132
+ [unagent](https://github.com/onmax/unagent) covers similar ground but makes different tradeoffs.
133
+
134
+ **harnesses is deep and narrow.** Each harness gets verified, platform-specific paths with scope, evidence level, and platform tags. Session formats are typed per harness. Twelve harnesses, each fully mapped.
135
+
136
+ **unagent is wide and shallow.** 40+ agents detected by env vars, but each definition is just `configDir` + `rulesFile` + `skillsDir`. No platform-specific paths, no session schemas. In exchange, it ships runtime primitives harnesses doesn't touch yet: skill install/uninstall, vector stores, browser automation, sandboxes, queues, workflows.
137
+
138
+ harnesses tells you _where coding harnesses live and what format their data uses_. unagent tells you _which agent is running_ and gives you tools to _do things_ with skills. They could use each other.
139
+
140
+ ## License
141
+
142
+ [MIT](./LICENSE)
@@ -0,0 +1,36 @@
1
+ # Licenses of Bundled Dependencies
2
+
3
+ The published artifact additionally contains code with the following licenses:
4
+ MIT
5
+
6
+ # Bundled Dependencies
7
+
8
+ ## typebox
9
+
10
+ License: MIT
11
+ By: sinclairzx81
12
+ Repository: https://github.com/sinclairzx81/typebox
13
+
14
+ > TypeBox
15
+ >
16
+ > The MIT License (MIT)
17
+ >
18
+ > Copyright (c) 2017-2026 Haydn Paterson
19
+ >
20
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
21
+ > of this software and associated documentation files (the "Software"), to deal
22
+ > in the Software without restriction, including without limitation the rights
23
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24
+ > copies of the Software, and to permit persons to whom the Software is
25
+ > furnished to do so, subject to the following conditions:
26
+ >
27
+ > The above copyright notice and this permission notice shall be included in
28
+ > all copies or substantial portions of the Software.
29
+ >
30
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36
+ > THE SOFTWARE.
@@ -0,0 +1,417 @@
1
+ declare const version: string;
2
+ type HarnessId = "antigravity" | "codex" | "gemini" | "grok" | "claude" | "opencode" | "cursor" | "freebuff" | "github-copilot" | "mastracode" | "omp" | "pi";
3
+ type EvidenceLevel = "official" | "community" | "inferred";
4
+ type Platform = "linux" | "darwin" | "win32";
5
+ interface PathCandidate {
6
+ path: string;
7
+ scope: "user" | "project" | "system" | "data";
8
+ level: EvidenceLevel;
9
+ platforms?: Platform[];
10
+ note?: string;
11
+ }
12
+ interface StorageDescriptor {
13
+ format: string;
14
+ level: EvidenceLevel;
15
+ note?: string;
16
+ }
17
+ interface HarnessCapabilities {
18
+ mcp: boolean;
19
+ vision: boolean;
20
+ /** Audio reaches the model without conversion or MCP. */
21
+ audio: boolean;
22
+ /** Video reaches the model without conversion or MCP. */
23
+ video: boolean;
24
+ tools: boolean;
25
+ streaming: boolean;
26
+ }
27
+ /** How to run one prompt through the harness non-interactively. */
28
+ interface HarnessInvocation {
29
+ /** Binary to spawn; defaults to the harness's first `binaries` entry. */
30
+ binary?: string;
31
+ /** Full agent argument template; every "{prompt}" is replaced with the prompt text. */
32
+ args: string[];
33
+ /** Structured full agent argument template. */
34
+ jsonArgs?: string[];
35
+ /** Advisor argument template without tools; absent when the CLI cannot disable tools. */
36
+ noToolsArgs?: string[];
37
+ /** Structured advisor argument template without tools. */
38
+ noToolsJsonArgs?: string[];
39
+ /** Agent argument template whose native sandbox enforces read-only tool access. */
40
+ readOnlyArgs?: string[];
41
+ /** Structured agent argument template with read-only tool access. */
42
+ readOnlyJsonArgs?: string[];
43
+ /** Arguments appended when a model is selected; every "{model}" is replaced. */
44
+ modelArgs?: string[];
45
+ level: EvidenceLevel;
46
+ note?: string;
47
+ }
48
+ /** Invocation modes a harness supports without fallback or prompt-only restrictions. */
49
+ interface HarnessInvocationModes {
50
+ advisor: boolean;
51
+ advisorStructured: boolean;
52
+ readOnly: boolean;
53
+ readOnlyStructured: boolean;
54
+ agent: boolean;
55
+ agentStructured: boolean;
56
+ }
57
+ /** How to ask one harness CLI for the models currently available to it. */
58
+ interface HarnessModelListing {
59
+ /** Arguments used when no search filter is supplied. */
60
+ args: string[];
61
+ /** Optional argument template for a search filter; every "{search}" is replaced. */
62
+ searchArgs?: string[];
63
+ level: EvidenceLevel;
64
+ note?: string;
65
+ }
66
+ /** One model normalized from a harness's native model-listing output. */
67
+ interface AvailableModel {
68
+ provider: string;
69
+ id: string;
70
+ contextWindow: number;
71
+ maxOutputTokens: number;
72
+ thinking: boolean;
73
+ images: boolean;
74
+ }
75
+ /** Options for querying the models available to one harness. */
76
+ interface ListModelsOptions {
77
+ search?: string;
78
+ cwd?: string;
79
+ env?: Record<string, string>;
80
+ /** Kill the model-listing command after this many milliseconds; unset means no timeout. */
81
+ timeoutMs?: number;
82
+ }
83
+ interface InvokeOptions {
84
+ cwd?: string;
85
+ env?: Record<string, string>;
86
+ /** Harness-native model id or selector. */
87
+ model?: string;
88
+ /** Enable the spawned harness's tools; defaults to advisor without tools mode. */
89
+ tools?: boolean;
90
+ /** Require native enforcement of read-only tool access. Implies `tools: true`. */
91
+ readOnly?: boolean;
92
+ /** Kill the harness after this many milliseconds; unset means no timeout. */
93
+ timeoutMs?: number;
94
+ /** Use the harness's structured (JSON) output mode instead of plain text. */
95
+ structured?: boolean;
96
+ }
97
+ interface InvokeResult {
98
+ command: string;
99
+ args: string[];
100
+ stdout: string;
101
+ stderr: string;
102
+ /** Process exit code; null when the run hit `timeoutMs` and was killed. */
103
+ exitCode: number | null;
104
+ timedOut: boolean;
105
+ }
106
+ /** Result of one native model-listing command. */
107
+ interface ListModelsResult extends InvokeResult {
108
+ /** Empty on a successful no-match response or when the command itself failed. */
109
+ models: AvailableModel[];
110
+ }
111
+ /** Normalized MCP server entry, shared across every harness dialect. */
112
+ interface McpServerConfig {
113
+ name: string;
114
+ transport: "stdio" | "http" | "sse";
115
+ command?: string;
116
+ args?: string[];
117
+ env?: Record<string, string>;
118
+ url?: string;
119
+ headers?: Record<string, string>;
120
+ /** Present only when the harness tracks an on/off state per server. */
121
+ enabled?: boolean;
122
+ }
123
+ /** How one harness config file stores its MCP servers. */
124
+ interface McpConfigFile extends PathCandidate {
125
+ format: "json" | "toml";
126
+ /** Object path to the server map inside the file, e.g. ["mcpServers"]. */
127
+ key: string[];
128
+ /** Shape of individual entries; "standard" is the {command, args, env, url} family. */
129
+ dialect: "standard" | "antigravity" | "opencode" | "vscode";
130
+ }
131
+ interface HarnessDetection {
132
+ /** Environment variables that indicate running inside this agent. */
133
+ envVars: string[];
134
+ /** Project-level files or directories whose presence indicates this agent. */
135
+ projectMarkers: string[];
136
+ }
137
+ interface ResolveOptions {
138
+ homeDir?: string;
139
+ projectRoot?: string;
140
+ platform?: Platform;
141
+ }
142
+ interface ResolvedPaths {
143
+ config: PathCandidate[];
144
+ sessions: PathCandidate[];
145
+ instructions: PathCandidate[];
146
+ skills: PathCandidate[];
147
+ commands: PathCandidate[];
148
+ hooks: PathCandidate[];
149
+ }
150
+ type InvocationOptions = Readonly<{
151
+ model?: string;
152
+ structured?: boolean;
153
+ tools?: boolean;
154
+ readOnly?: boolean;
155
+ }>;
156
+ declare abstract class Harness {
157
+ abstract readonly id: HarnessId;
158
+ abstract readonly name: string;
159
+ abstract readonly binaries: string[];
160
+ abstract readonly config: PathCandidate[];
161
+ abstract readonly sessions: PathCandidate[];
162
+ abstract readonly persistence: StorageDescriptor[];
163
+ abstract readonly instructions: PathCandidate[];
164
+ abstract readonly skills: PathCandidate[];
165
+ abstract readonly commands: PathCandidate[];
166
+ abstract readonly hooks: PathCandidate[];
167
+ abstract readonly capabilities: HarnessCapabilities;
168
+ abstract readonly detection: HarnessDetection;
169
+ /** Non-interactive invocation recipe; null when the harness has no headless mode. */
170
+ abstract readonly invocation: HarnessInvocation | null;
171
+ /** Native model-listing recipe; null when the harness cannot enumerate available models. */
172
+ readonly modelListing: HarnessModelListing | null;
173
+ /** Config files that hold MCP server definitions; empty when unknown or unsupported. */
174
+ readonly mcpConfigs: McpConfigFile[];
175
+ /**
176
+ * The user-scope global instructions file this harness reads, as a path
177
+ * template; null when there is no stable file (or another harness's file
178
+ * covers it via vendor compatibility).
179
+ */
180
+ readonly agentsFile: string | null;
181
+ isInstalled(): boolean;
182
+ detectEnv(): boolean;
183
+ detectProject(cwd?: string): boolean;
184
+ get version(): string | null;
185
+ /**
186
+ * Invocation modes available without fallback or prompt-only restrictions.
187
+ *
188
+ * @returns {HarnessInvocationModes} The exact supported invocation modes.
189
+ */
190
+ get invocationModes(): HarnessInvocationModes;
191
+ /**
192
+ * Expands the invocation template for one prompt, without spawning anything.
193
+ * Returns null when the harness has no headless mode, or no structured mode
194
+ * when `structured` is requested.
195
+ *
196
+ * @param prompt - Prompt inserted into the invocation template.
197
+ * @param options - Requested model and execution mode.
198
+ * @returns {{ command: string, args: string[] } | null} The executable invocation, or null.
199
+ */
200
+ buildInvocation(prompt: string, options?: InvocationOptions): {
201
+ command: string;
202
+ args: string[];
203
+ } | null;
204
+ /**
205
+ * Explains why an invocation option set cannot be built, or returns null when supported.
206
+ *
207
+ * @param options - Requested model and execution mode.
208
+ * @returns {string | null} The incompatibility reason, or null when supported.
209
+ */
210
+ invocationError(options?: InvocationOptions): string | null;
211
+ /**
212
+ * Runs one prompt through the harness non-interactively and collects the
213
+ * output. stdin is closed so a harness that falls back to interactive mode
214
+ * exits instead of waiting forever.
215
+ *
216
+ * @param prompt - Prompt sent to the harness.
217
+ * @param options - Invocation, environment, and timeout options.
218
+ * @returns {Promise<InvokeResult>} The completed process result.
219
+ */
220
+ invoke(prompt: string, options?: InvokeOptions): Promise<InvokeResult>;
221
+ /**
222
+ * Expands the native model-listing recipe without spawning anything.
223
+ *
224
+ * @param search - Optional native model search filter.
225
+ * @returns {{ command: string, args: string[] } | null} The command, or null when unsupported.
226
+ */
227
+ buildModelListInvocation(search?: string): {
228
+ command: string;
229
+ args: string[];
230
+ } | null;
231
+ /**
232
+ * Runs the harness's native model-listing command and normalizes its output.
233
+ * stdin is closed for the same reason as {@link invoke}.
234
+ *
235
+ * @param options - Search, environment, and timeout options.
236
+ * @returns {Promise<ListModelsResult>} The normalized command and model result.
237
+ */
238
+ listModels(options?: ListModelsOptions): Promise<ListModelsResult>;
239
+ /**
240
+ * Converts a successful native model-listing response to the shared shape.
241
+ *
242
+ * @param _stdout - Native command output to parse.
243
+ */
244
+ protected parseModelListingOutput(_stdout: string): AvailableModel[];
245
+ /**
246
+ * Filters one candidate list to the platform and expands its path
247
+ * templates: the shared pipeline behind {@link resolve} and the MCP
248
+ * config surface.
249
+ *
250
+ * @param entries - Candidate paths to filter and resolve.
251
+ * @param options - Platform and path-resolution overrides.
252
+ * @returns {T[]} Resolved candidates supported on the selected platform.
253
+ */
254
+ resolveCandidates<T extends PathCandidate>(entries: readonly T[], options?: ResolveOptions): T[];
255
+ resolve(options?: ResolveOptions): ResolvedPaths;
256
+ }
257
+ type HarnessConstructor = new () => Harness;
258
+ /** One resolved config file together with the servers it declares. */
259
+ interface McpConfigListing {
260
+ path: string;
261
+ scope: McpConfigFile["scope"];
262
+ format: McpConfigFile["format"];
263
+ level: EvidenceLevel;
264
+ note?: string;
265
+ exists: boolean;
266
+ servers: McpServerConfig[];
267
+ /** Set when the file exists but could not be parsed. */
268
+ error?: string;
269
+ }
270
+ /**
271
+ * Lists the MCP servers a harness has configured, per declared config file.
272
+ * Missing files come back with `exists: false`; unparsable ones carry `error`.
273
+ *
274
+ * @param harness - Harness whose configs should be read.
275
+ * @param options - Platform and path-resolution overrides.
276
+ * @returns {McpConfigListing[]} One listing per declared config file.
277
+ */
278
+ declare function listMcpServers(harness: Harness, options?: ResolveOptions): McpConfigListing[];
279
+ /**
280
+ * Adds (or replaces) one MCP server in a harness's config. The rest of the
281
+ * file is preserved: JSON through a parse/serialize round trip (formatting
282
+ * normalizes to two-space indentation), TOML through a surgical line edit.
283
+ *
284
+ * @param harness - Target harness.
285
+ * @param server - Normalized server configuration to write.
286
+ * @param scope - User or project config scope.
287
+ * @param options - Platform and path-resolution overrides.
288
+ * @returns {{ path: string, replaced: boolean }} The written path and replacement status.
289
+ */
290
+ declare function addMcpServer(harness: Harness, server: McpServerConfig, scope?: "user" | "project", options?: ResolveOptions): {
291
+ path: string;
292
+ replaced: boolean;
293
+ };
294
+ /**
295
+ * Removes one MCP server from a harness's config.
296
+ *
297
+ * @param harness - Target harness.
298
+ * @param name - Server name to remove.
299
+ * @param scope - User or project config scope.
300
+ * @param options - Platform and path-resolution overrides.
301
+ * @returns {{ path: string, removed: boolean }} The targeted path and removal status.
302
+ */
303
+ declare function removeMcpServer(harness: Harness, name: string, scope?: "user" | "project", options?: ResolveOptions): {
304
+ path: string;
305
+ removed: boolean;
306
+ };
307
+ /**
308
+ * Strips JSONC extensions (comments and trailing commas) so the master sync
309
+ * file can be read with JSON.parse. String contents are left untouched.
310
+ *
311
+ * @param text - JSONC source text.
312
+ * @returns {unknown} The parsed JSON value.
313
+ */
314
+ declare function parseJsonc(text: string): unknown;
315
+ /**
316
+ * Resolves the master sync file path: $XDG_CONFIG_HOME or ~/.config.
317
+ *
318
+ * @param options - Path-resolution overrides.
319
+ * @returns {string} The resolved master MCP config path.
320
+ */
321
+ declare function masterMcpPath(options?: ResolveOptions): string;
322
+ /** One harness's outcome of a sync run. */
323
+ interface SyncTargetResult {
324
+ id: string;
325
+ path?: string;
326
+ /** Reason this harness could not be targeted; `results` is empty then. */
327
+ skipped?: string;
328
+ /** Set when the master list excludes this harness; master-listed names are withdrawn. */
329
+ excluded?: true;
330
+ results: Array<{
331
+ name: string;
332
+ action: "added" | "replaced" | "removed" | "unchanged";
333
+ }>;
334
+ }
335
+ /** Outcome of resetting the harness configs to the master list. */
336
+ interface SyncReport {
337
+ source: string;
338
+ servers: string[];
339
+ targets: SyncTargetResult[];
340
+ }
341
+ /**
342
+ * Reads and normalizes the master list; throws when the file is missing or invalid.
343
+ *
344
+ * @param options - Path-resolution overrides.
345
+ * @returns {{ path: string, servers: McpServerConfig[], excludes: string[] }} The master list.
346
+ */
347
+ declare function readMasterMcpServers(options?: ResolveOptions): {
348
+ path: string;
349
+ servers: McpServerConfig[];
350
+ /** Harness ids the master list opts out of syncing. */
351
+ excludes: string[];
352
+ };
353
+ /**
354
+ * Resets each harness's user-scope MCP config to exactly the master list:
355
+ * missing servers are added, drifted ones replaced, and servers absent from
356
+ * the master are removed. The master file is the single source of truth.
357
+ *
358
+ * @param harnesses - Harnesses to synchronize.
359
+ * @param options - Platform and path-resolution overrides.
360
+ * @returns {SyncReport} Per-harness synchronization outcomes.
361
+ */
362
+ declare function syncMcpServers(harnesses: readonly Harness[], options?: ResolveOptions): SyncReport;
363
+ /** Configuration read from agents.jsonc. */
364
+ interface AgentsConfig {
365
+ /** The master instructions file every harness links to. */
366
+ source: string;
367
+ /** Relative files to link beside every harness instructions target. */
368
+ companions: string[];
369
+ /** Harness ids the sync leaves untouched. */
370
+ excludes: string[];
371
+ /** Path the config was read from; absent when defaults were used. */
372
+ configPath?: string;
373
+ }
374
+ type AgentsSyncAction = "linked" | "relinked" | "adopted" | "unchanged" | "skipped";
375
+ /** One companion file's outcome for a harness target. */
376
+ interface AgentsCompanionTargetResult {
377
+ readonly source: string;
378
+ readonly path: string;
379
+ readonly action: Exclude<AgentsSyncAction, "skipped">;
380
+ /** Backup path for an adopted file, or a check-mode note. */
381
+ readonly detail?: string;
382
+ }
383
+ /** One harness's outcome of an agents sync run. */
384
+ interface AgentsTargetResult {
385
+ id: string;
386
+ path?: string;
387
+ action: AgentsSyncAction;
388
+ /** Reason for a skip, or the backup path for an adopted diverged file. */
389
+ detail?: string;
390
+ /** Companion outcomes, present when companions are configured. */
391
+ companions?: readonly AgentsCompanionTargetResult[];
392
+ }
393
+ /** Outcome of one agents sync/doctor run. */
394
+ interface AgentsSyncReport {
395
+ source: string;
396
+ check: boolean;
397
+ targets: AgentsTargetResult[];
398
+ }
399
+ /**
400
+ * Reads agents.jsonc; missing file falls back to defaults.
401
+ *
402
+ * @param options - Path-resolution overrides.
403
+ * @returns {AgentsConfig} The normalized sync configuration.
404
+ */
405
+ declare function readAgentsConfig(options?: ResolveOptions): AgentsConfig;
406
+ /**
407
+ * Links every harness's user-scope instructions file to the master. In check
408
+ * mode nothing is written; the report shows what a real run would do.
409
+ *
410
+ * @param harnesses - Harnesses to inspect or update.
411
+ * @param check - Report intended changes without writing them.
412
+ * @param options - Path-resolution overrides.
413
+ * @returns {AgentsSyncReport} Per-harness synchronization outcomes.
414
+ */
415
+ declare function syncAgentsFiles(harnesses: readonly Harness[], check?: boolean, options?: ResolveOptions): AgentsSyncReport;
416
+ export { AgentsCompanionTargetResult, AgentsConfig, AgentsSyncAction, AgentsSyncReport, AgentsTargetResult, AvailableModel, EvidenceLevel, Harness, HarnessCapabilities, HarnessConstructor, HarnessDetection, HarnessId, HarnessInvocation, HarnessInvocationModes, HarnessModelListing, InvokeOptions, InvokeResult, ListModelsOptions, ListModelsResult, McpConfigFile, McpConfigListing, McpServerConfig, PathCandidate, Platform, ResolveOptions, ResolvedPaths, StorageDescriptor, SyncReport, SyncTargetResult, addMcpServer, listMcpServers, masterMcpPath, parseJsonc, readAgentsConfig, readMasterMcpServers, removeMcpServer, syncAgentsFiles, syncMcpServers, version };
417
+ //# sourceMappingURL=agents-sync.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents-sync.d.mts","names":[],"sources":["../../src/types.ts","../../src/harness.ts","../../src/mcp-servers.ts","../../src/agents-sync.ts"],"mappings":"AAEA,cAAa;KAED;KAaA;KACA;UAEK;EACf;EACA;EACA,OAAO;EACP,YAAY;EACZ;;UAGe;EACf;EACA,OAAO;EACP;;UAGe;EACf;EACA;;EAEA;;EAEA;EACA;EACA;;;UAIe;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;EACA,OAAO;EACP;;;UAIe;EACf;EACA;EACA;EACA;EACA;EACA;;;UAIe;;EAEf;;EAEA;EACA,OAAO;EACP;;;UAIe;EACf;EACA;EACA;EACA;EACA;EACA;;;UAIe;EACf;EACA;EACA,MAAM;;EAEN;;UAGe;EACf;EACA,MAAM;;EAEN;;EAEA;;EAEA;;EAEA;;EAEA;;UAGe;EACf;EACA;EACA;EACA;;EAEA;EACA;;;UAIe,yBAAyB;;EAExC,QAAQ;;;UAIO;EACf;EACA;EACA;EACA;EACA,MAAM;EACN;EACA,UAAU;;EAEV;;;UAIe,sBAAsB;EACrC;;EAEA;;EAEA;;UAGe;;EAEf;;EAEA;;UAGe;EACf;EACA;EACA,WAAW;;UAGI;EACf,QAAQ;EACR,UAAU;EACV,cAAc;EACd,QAAQ;EACR,UAAU;EACV,OAAO;;KC9IJ,oBAAoB;EACvB;EACA;EACA;EACA;;uBAqHoB;oBACF,IAAI;oBACJ;oBACA;oBACA,QAAQ;oBACR,UAAU;oBACV,aAAa;oBACb,cAAc;oBACd,QAAQ;oBACR,UAAU;oBACV,OAAO;oBACP,cAAc;oBACd,WAAW;;oBAEX,YAAY;;WAErB,cAAc;;WAEd,YAAY;;;;;;WAMZ;EAET;EAYA;EAIA,cAAc;MAKV;;;;;;MAsBA,mBAAmB;;;;;;;;;;EAoBvB,gBACE,gBACA,UAAS;IACN;IAAiB;;;;;;;;EAmBtB,gBAAgB,UAAS;;;;;;;;;;EAwBzB,OAAO,gBAAgB,UAAS,gBAAqB,QAAQ;;;;;;;EAuB7D,yBAAyB;IAAoB;IAAiB;;;;;;;;;EAmBxD,WAAW,UAAS,oBAAyB,QAAQ;;;;;;YAyBjD,wBAAwB,kBAAkB;;;;;;;;;;EAapD,kBAAkB,UAAU,eAC1B,kBAAkB,KAClB,UAAS,iBACR;EAcH,QAAQ,UAAS,iBAAsB;;KAY7B,+BAA+B;;UC9X1B;EACf;EACA,OAAO;EACP,QAAQ;EACR,OAAO;EACP;EACA;EACA,SAAS;;EAET;;;;;;;;;;iBAmRc,eAAe,SAAS,SAAS,UAAS,iBAAsB;;;;;;;;;;;;iBAiLhE,aACd,SAAS,SACT,QAAQ,iBACR,4BACA,UAAS;EACN;EAAc;;;;;;;;;;;iBA0BH,gBACd,SAAS,SACT,cACA,4BACA,UAAS;EACN;EAAc;;;;;;;;;iBA8FH,WAAW;;;;;;;iBAwBX,cAAc,UAAS;;UAKtB;EACf;EACA;;EAEA;;EAEA;EACA,SAAS;IAAQ;IAAc;;;;UAIhB;EACf;EACA;EACA,SAAS;;;;;;;;iBAuEK,qBAAqB,UAAS;EAC5C;EACA,SAAS;;EAET;;;;;;;;;;;iBA2Hc,eACd,oBAAoB,WACpB,UAAS,iBACR;;UC1zBc;;EAEf;;EAEA;;EAEA;;EAEA;;KAGU;;UAGK;WACN;WACA;WACA,QAAQ,QAAQ;;WAEhB;;;UAIM;EACf;EACA;EACA,QAAQ;;EAER;;EAEA,sBAAsB;;;UAIP;EACf;EACA;EACA,SAAS;;;;;;;;iBAkFK,iBAAiB,UAAS,iBAAsB;;;;;;;;;;iBAiMhD,gBACd,oBAAoB,WACpB,iBACA,UAAS,iBACR"}