harnessbrew 0.4.0

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 (60) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/LICENSE +21 -0
  3. package/README.md +266 -0
  4. package/dist/bin.d.ts +3 -0
  5. package/dist/bin.d.ts.map +1 -0
  6. package/dist/bin.js +4 -0
  7. package/dist/bin.js.map +1 -0
  8. package/dist/cli.d.ts +9 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +242 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/core/bundle.d.ts +43 -0
  13. package/dist/core/bundle.d.ts.map +1 -0
  14. package/dist/core/bundle.js +195 -0
  15. package/dist/core/bundle.js.map +1 -0
  16. package/dist/core/errors.d.ts +4 -0
  17. package/dist/core/errors.d.ts.map +1 -0
  18. package/dist/core/errors.js +7 -0
  19. package/dist/core/errors.js.map +1 -0
  20. package/dist/core/formulas.d.ts +29 -0
  21. package/dist/core/formulas.d.ts.map +1 -0
  22. package/dist/core/formulas.js +185 -0
  23. package/dist/core/formulas.js.map +1 -0
  24. package/dist/core/git.d.ts +3 -0
  25. package/dist/core/git.d.ts.map +1 -0
  26. package/dist/core/git.js +36 -0
  27. package/dist/core/git.js.map +1 -0
  28. package/dist/core/installations.d.ts +38 -0
  29. package/dist/core/installations.d.ts.map +1 -0
  30. package/dist/core/installations.js +250 -0
  31. package/dist/core/installations.js.map +1 -0
  32. package/dist/core/paths.d.ts +8 -0
  33. package/dist/core/paths.d.ts.map +1 -0
  34. package/dist/core/paths.js +39 -0
  35. package/dist/core/paths.js.map +1 -0
  36. package/dist/core/state.d.ts +16 -0
  37. package/dist/core/state.d.ts.map +1 -0
  38. package/dist/core/state.js +43 -0
  39. package/dist/core/state.js.map +1 -0
  40. package/dist/core/taps.d.ts +16 -0
  41. package/dist/core/taps.d.ts.map +1 -0
  42. package/dist/core/taps.js +102 -0
  43. package/dist/core/taps.js.map +1 -0
  44. package/dist/core/targets.d.ts +11 -0
  45. package/dist/core/targets.d.ts.map +1 -0
  46. package/dist/core/targets.js +150 -0
  47. package/dist/core/targets.js.map +1 -0
  48. package/dist/core/upgrades.d.ts +14 -0
  49. package/dist/core/upgrades.d.ts.map +1 -0
  50. package/dist/core/upgrades.js +127 -0
  51. package/dist/core/upgrades.js.map +1 -0
  52. package/dist/index.d.ts +15 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +9 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/version.d.ts +2 -0
  57. package/dist/version.d.ts.map +1 -0
  58. package/dist/version.js +2 -0
  59. package/dist/version.js.map +1 -0
  60. package/package.json +63 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,83 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## 0.4.0 - 2026-08-12
6
+
7
+ ### Added
8
+
9
+ - Git Tap registration, validation, updates, commit checkout, and removal
10
+ - Formula catalog for skills, agents, workflows, instructions, prompts, MCP configurations, and adapters
11
+ - dependency resolution, conflict detection, immutable Cellar installs, and SHA-256 receipts
12
+ - OpenAI Codex and Claude Code target linking with ownership and tamper checks
13
+ - `update`, `outdated`, and rollback-safe `upgrade` commands
14
+ - Git-reproducible `Harnessfile`, `Harnessfile.lock`, `bundle install`, and `bundle cleanup`
15
+ - TypeScript 7.0 strict builds, comprehensive tests, npm packaging, and GitHub release automation
16
+
17
+ ### Changed
18
+
19
+ - redefined HarnessBrew as a Git-native package manager for AI Agent assets
20
+ - moved version history from per-asset snapshots to Tap commits and tags
21
+ - raised the minimum supported Node.js version to 20
22
+
23
+ ### Removed
24
+
25
+ - repository-owned sample assets and the obsolete workspace/export architecture
26
+
27
+ ## 0.3.0 - 2026-06-27
28
+
29
+ ### Added
30
+
31
+ - asset maintenance commands: `set`, `add-dependency`, `remove-dependency`, `clone`, and `archive`
32
+ - dependency graph commands: `deps`, `dependents`, `orphans`, and `impact`
33
+ - bundle `checksums.json` generation plus manifest digest metadata for release artifact verification
34
+ - `verify-bundle` command for validating required bundle files, SHA-256 digests, and asset payload consistency
35
+ - `pack --channel draft|stable`, with `stable` bundles requiring workspace validation before packaging
36
+ - `pack --archive` for producing distributable `.tar.gz` bundle archives
37
+ - `docs/walkthrough-asset-to-bundle.md` covering asset creation through bundle verification
38
+ - `docs/release-0.3.0.md` with version touchpoints, verification commands, manual checks, and release flow
39
+
40
+ ### Changed
41
+
42
+ - repository sample agent now declares dependencies that match the initialized sample workspace
43
+ - asset metadata now includes `status: "active" | "archived"` and `list --status` filtering
44
+ - README command surface now reflects the `0.3.0` asset lifecycle, dependency graph, and bundle verification workflows
45
+ - smoke coverage now exercises lifecycle commands, graph queries, bundle digests, bundle verification, release channels, and archive packaging
46
+
47
+ ### Fixed
48
+
49
+ - archive flow now blocks assets that are still depended on, avoiding broken dependency graphs
50
+ - bundle verification now catches missing files, checksum mismatches, and manifest/assets asset set drift
51
+
52
+ ## 0.2.0 - 2026-06-17
53
+
54
+ ### Added
55
+
56
+ - asset dependency modeling with validation for missing, duplicate, cyclic, and target-incompatible dependencies
57
+ - `show --resolved` for inspecting dependency trees and flattened dependency graphs
58
+ - filtered and grouped `list` output with `--kind`, `--tag`, `--owner`, `--target`, and `--group-by`
59
+ - structured `--json` output for `list`, `validate`, `history`, `diff`, `export`, and `pack`
60
+ - entry-scoped exports with `--entry <kind:id>` and optional `--include-dependencies`
61
+ - `pack` command for bundle delivery with `manifest.json`, `assets.json`, and `rendered/<target>.json`
62
+ - workspace-level `schemaVersion` and `bundleDirectory` configuration
63
+ - `0.2.0` roadmap documentation covering milestones, command design, and bundle packaging direction
64
+
65
+ ### Changed
66
+
67
+ - strengthened target compatibility enforcement during export and pack flows
68
+ - expanded smoke coverage for dependency resolution, local adapter compatibility, scoped exports, and bundle generation
69
+ - updated README and architecture docs to reflect the `0.2.0` asset, export, and packaging model
70
+
71
+ ## 0.1.1 - 2026-06-17
72
+
73
+ ### Added
74
+
75
+ - `harness --version` support for checking the CLI release version directly
76
+ - release-facing documentation for version visibility and pre-release verification
77
+
78
+ ### Changed
79
+
80
+ - stricter workspace validation for timezone presence, history integrity, compatibility target duplication, and snapshot consistency
81
+ - clearer `diff` output with metadata-field change summaries
82
+ - clearer `history` output with current-version markers and snapshot paths
83
+ - more focused `show` output with `--metadata` and `--content` modes
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HarnessBrew contributors
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,266 @@
1
+ # HarnessBrew
2
+
3
+ HarnessBrew 是面向 AI Agent 资产的 Git 包管理器。它的定位类似 Homebrew:通过 Git Tap 发现资产,通过 Formula 描述资产,通过 Cellar 与 Receipt 安装、升级和安全卸载资产。
4
+
5
+ HarnessBrew 不托管资产。个人、团队和第三方资产都保存在各自的 Git 仓库中,并使用完全相同的安装机制。
6
+
7
+ ## 主要能力
8
+
9
+ - 注册、更新和移除 Git Tap
10
+ - 校验并搜索 skill、agent、workflow、instruction、prompt、MCP 和 adapter Formula
11
+ - 解析依赖、循环、缺失项与冲突
12
+ - 按 Git commit 将不可变内容安装到 Cellar
13
+ - 链接到 OpenAI Codex 和 Claude Code
14
+ - 通过 Receipt 跟踪文件所有权和 SHA-256 摘要
15
+ - 检测可用升级,并在升级后保留 Agent target 链接
16
+ - 使用 `Harnessfile` 和 lockfile 在不同设备上复现环境
17
+ - 从 npm 安装并通过 GitHub Release 发布
18
+
19
+ ## 安装
20
+
21
+ 要求:Node.js 20 或更高版本,系统中可用 Git。
22
+
23
+ ```bash
24
+ npm install --global harnessbrew
25
+ harnessbrew --version
26
+ ```
27
+
28
+ 也可以直接使用:
29
+
30
+ ```bash
31
+ npx harnessbrew help
32
+ ```
33
+
34
+ HarnessBrew 默认将受管状态保存到 `~/.harnessbrew`。测试或隔离环境可以设置 `HARNESSBREW_HOME`。
35
+
36
+ ## 快速开始
37
+
38
+ 注册自己的资产 Tap:
39
+
40
+ ```bash
41
+ harnessbrew tap add xiejinheng/agents git@github.com:xiejinheng/agent-assets.git
42
+ ```
43
+
44
+ 搜索并查看 Formula:
45
+
46
+ ```bash
47
+ harnessbrew search review
48
+ harnessbrew search --kind skill --target openai-codex
49
+ harnessbrew info xiejinheng/agents/code-review
50
+ ```
51
+
52
+ 安装到 Cellar,并链接到 Codex:
53
+
54
+ ```bash
55
+ harnessbrew install xiejinheng/agents/code-review \
56
+ --target openai-codex
57
+ ```
58
+
59
+ 如果只希望保存到 Cellar,不写入 Agent 配置目录,可以省略 `--target`。
60
+
61
+ 更新和升级:
62
+
63
+ ```bash
64
+ harnessbrew update
65
+ harnessbrew outdated
66
+ harnessbrew upgrade code-review
67
+ ```
68
+
69
+ 安全卸载:
70
+
71
+ ```bash
72
+ harnessbrew uninstall code-review
73
+ ```
74
+
75
+ 若受管文件或链接已被修改,HarnessBrew 会停止卸载。确认需要删除时可以显式传入 `--force`。
76
+
77
+ ## Homebrew 概念对应
78
+
79
+ | Homebrew | HarnessBrew |
80
+ | --- | --- |
81
+ | `brew` | `harnessbrew` |
82
+ | Tap | Git 资产源仓库 |
83
+ | Formula / Cask | Agent 资产 Formula |
84
+ | Cellar | 按 Git commit 隔离的本地安装区 |
85
+ | Link | 到 Codex、Claude Code 等 target 的链接 |
86
+ | `Brewfile` | `Harnessfile` |
87
+ | Receipt | 安装来源、文件摘要与所有权记录 |
88
+
89
+ ## 创建 Tap
90
+
91
+ Tap 是普通 Git 仓库。推荐按资产集合建立 Tap,不需要为每个 skill 单独建立仓库。
92
+
93
+ ```text
94
+ my-agent-tap/
95
+ ├── tap.json
96
+ ├── skills/
97
+ │ └── code-review/
98
+ │ ├── formula.json
99
+ │ └── SKILL.md
100
+ ├── workflows/
101
+ ├── agents/
102
+ ├── instructions/
103
+ ├── prompts/
104
+ ├── mcp/
105
+ └── adapters/
106
+ ```
107
+
108
+ 最小 `tap.json`:
109
+
110
+ ```json
111
+ {
112
+ "schemaVersion": 1
113
+ }
114
+ ```
115
+
116
+ Formula 的目录名称必须与 `name` 一致,目录类型必须与 `kind` 一致:
117
+
118
+ ```json
119
+ {
120
+ "schemaVersion": 1,
121
+ "name": "code-review",
122
+ "kind": "skill",
123
+ "description": "Review code changes with a consistent rubric.",
124
+ "entry": "SKILL.md",
125
+ "targets": ["openai-codex", "claude-code"],
126
+ "dependencies": [
127
+ "xiejinheng/agents/repository-guardrails"
128
+ ],
129
+ "conflicts": [],
130
+ "tags": ["review", "quality"]
131
+ }
132
+ ```
133
+
134
+ 完整坐标为 `<owner>/<tap>/<formula>`。依赖和冲突必须使用完整坐标,以避免跨 Tap 名称歧义。
135
+
136
+ Git commit 是安装版本的唯一事实来源;Formula 不维护 `.snapshots` 或重复的 `history`。
137
+
138
+ ## Target
139
+
140
+ 当前内置:
141
+
142
+ - `openai-codex`
143
+ - `claude-code`
144
+
145
+ 可以在安装时指定 target:
146
+
147
+ ```bash
148
+ harnessbrew install code-review --target openai-codex
149
+ ```
150
+
151
+ 默认 target 根目录分别是 `~/.codex` 和 `~/.claude`。需要隔离安装时可使用:
152
+
153
+ ```bash
154
+ harnessbrew install code-review \
155
+ --target openai-codex \
156
+ --target-root /path/to/sandbox/.codex
157
+ ```
158
+
159
+ 也可以单独管理链接:
160
+
161
+ ```bash
162
+ harnessbrew link code-review --target openai-codex
163
+ harnessbrew unlink code-review --target openai-codex
164
+ ```
165
+
166
+ ## Harnessfile
167
+
168
+ `Harnessfile` 适合提交到个人 dotfiles 或项目仓库:
169
+
170
+ ```yaml
171
+ schemaVersion: 1
172
+ taps:
173
+ - name: xiejinheng/agents
174
+ git: git@github.com:xiejinheng/agent-assets.git
175
+ ref: main
176
+
177
+ assets:
178
+ - formula: xiejinheng/agents/code-review
179
+ targets: [openai-codex]
180
+ ```
181
+
182
+ 安装并生成 `Harnessfile.lock`:
183
+
184
+ ```bash
185
+ harnessbrew bundle install
186
+ ```
187
+
188
+ lockfile 会记录每个 Tap 的准确 commit、依赖闭包和 target,应与 `Harnessfile` 一起提交到 Git。
189
+
190
+ 在其他设备运行同一命令时,HarnessBrew 会检出 lockfile 固定的 commit,而不是未经确认地使用 Tap 最新版本。
191
+
192
+ 清理清单之外的受管资产:
193
+
194
+ ```bash
195
+ harnessbrew bundle cleanup
196
+ ```
197
+
198
+ 使用其他文件路径:
199
+
200
+ ```bash
201
+ harnessbrew bundle install --file ./config/Harnessfile
202
+ ```
203
+
204
+ ## CLI
205
+
206
+ ```text
207
+ harnessbrew tap add <owner/name> <git-url> [--ref <ref>]
208
+ harnessbrew tap list
209
+ harnessbrew tap update [owner/name]
210
+ harnessbrew tap remove <owner/name>
211
+ harnessbrew untap <owner/name>
212
+ harnessbrew search [query] [--kind <kind>] [--target <target>]
213
+ harnessbrew info <formula>
214
+ harnessbrew install <formula> [--target <target>] [--target-root <path>]
215
+ harnessbrew list
216
+ harnessbrew link <formula> --target <target> [--target-root <path>]
217
+ harnessbrew unlink <formula> --target <target> [--force]
218
+ harnessbrew update
219
+ harnessbrew outdated
220
+ harnessbrew upgrade [formula]
221
+ harnessbrew uninstall <formula> [--force]
222
+ harnessbrew bundle install [--file <path>]
223
+ harnessbrew bundle cleanup [--file <path>]
224
+ ```
225
+
226
+ ## 本地目录
227
+
228
+ ```text
229
+ ~/.harnessbrew/
230
+ ├── taps/ # HarnessBrew 管理的 Git 工作树
231
+ ├── cellar/ # 按 Formula 与 commit 隔离的不可变内容
232
+ ├── receipts/ # 安装、依赖、target 链接和摘要
233
+ └── state.json # Tap 注册状态
234
+ ```
235
+
236
+ Tap 工作树和 Cellar 内容都由 HarnessBrew 管理,不应直接编辑。个人资产应在原始 Tap 仓库中修改、提交和推送,再通过 `update`/`upgrade` 安装。
237
+
238
+ ## 安全边界
239
+
240
+ - Formula 是声明式 JSON;HarnessBrew 不执行 Tap 中的任意脚本。
241
+ - Formula 入口不能逃逸所属目录。
242
+ - 安装前会检查依赖、冲突和 target 兼容性。
243
+ - HarnessBrew 不覆盖未由 Receipt 管理的目标文件。
244
+ - 卸载前会检查 Cellar 文件摘要和符号链接目标。
245
+ - 私有 Tap 凭据由系统 Git/SSH credential 机制管理。
246
+
247
+ ## 开发
248
+
249
+ 项目使用 TypeScript 7.0,并启用严格类型检查。
250
+
251
+ ```bash
252
+ npm ci
253
+ npm run build
254
+ npm test
255
+ npm run check
256
+ ```
257
+
258
+ `npm run check` 会执行 TypeScript 编译、全部 Node.js 测试、安装包冒烟测试和 `npm pack --dry-run`。
259
+
260
+ ## 架构
261
+
262
+ 完整设计见 [docs/architecture.md](docs/architecture.md)。
263
+
264
+ ## License
265
+
266
+ MIT
package/dist/bin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
package/dist/bin.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from "./cli.js";
3
+ process.exitCode = await runCli(process.argv.slice(2));
4
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export interface CliIO {
2
+ stdout: (message: string) => void;
3
+ stderr: (message: string) => void;
4
+ }
5
+ export interface CliOptions {
6
+ home?: string;
7
+ }
8
+ export declare function runCli(args: readonly string[], io?: CliIO, options?: CliOptions): Promise<number>;
9
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA8OD,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,GAAE,KAAiB,EACrB,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,MAAM,CAAC,CAUjB"}
package/dist/cli.js ADDED
@@ -0,0 +1,242 @@
1
+ import path from "node:path";
2
+ import { HarnessBrewError } from "./core/errors.js";
3
+ import { formulaKinds, getFormula, searchFormulas } from "./core/formulas.js";
4
+ import { installFormula, listInstalled, uninstallFormula } from "./core/installations.js";
5
+ import { builtinTargets, installForTarget, linkFormula, unlinkFormula } from "./core/targets.js";
6
+ import { findOutdated, upgradeFormulas } from "./core/upgrades.js";
7
+ import { bundleCleanup, bundleInstall } from "./core/bundle.js";
8
+ import { resolveHarnessHome } from "./core/paths.js";
9
+ import { addTap, listTaps, removeTap, updateTaps } from "./core/taps.js";
10
+ import { VERSION } from "./version.js";
11
+ const defaultIO = {
12
+ stdout: (message) => console.log(message),
13
+ stderr: (message) => console.error(message)
14
+ };
15
+ const helpText = `HarnessBrew ${VERSION}
16
+
17
+ A Git-native package manager for AI Agent assets.
18
+
19
+ Usage:
20
+ harnessbrew <command> [options]
21
+
22
+ Commands:
23
+ help Show this help
24
+ version Show the installed version
25
+ tap Add, list, update, or remove Git taps
26
+ untap Remove a Git tap
27
+ search Search formulas across registered taps
28
+ info Show formula metadata
29
+ install Install a formula and its dependencies
30
+ list List installed formulas
31
+ uninstall Safely uninstall a formula
32
+ link Link an installed formula to an Agent target
33
+ unlink Remove a managed target link
34
+ update Fetch all registered taps
35
+ outdated List installed formulas with available changes
36
+ upgrade Upgrade formulas while preserving target links
37
+ bundle Rebuild or clean an environment from Harnessfile
38
+ `;
39
+ function optionValue(args, name) {
40
+ const index = args.indexOf(name);
41
+ if (index === -1)
42
+ return undefined;
43
+ const value = args[index + 1];
44
+ if (value === undefined)
45
+ throw new HarnessBrewError(`Missing value for ${name}.`);
46
+ return value;
47
+ }
48
+ async function runTapCommand(args, home, io) {
49
+ const [action = "list", ...rest] = args;
50
+ if (action === "list") {
51
+ const taps = await listTaps(home);
52
+ taps.forEach((tap) => io.stdout(`${tap.name}\t${tap.commit.slice(0, 12)}\t${tap.url}`));
53
+ return 0;
54
+ }
55
+ if (action === "add") {
56
+ const [name, url] = rest;
57
+ if (name === undefined || url === undefined) {
58
+ throw new HarnessBrewError("Usage: harnessbrew tap add <owner/name> <git-url> [--ref <ref>]");
59
+ }
60
+ const ref = optionValue(rest, "--ref");
61
+ const record = await addTap(home, name, url, ref === undefined ? {} : { ref });
62
+ io.stdout(`Tapped ${record.name} at ${record.commit.slice(0, 12)}.`);
63
+ return 0;
64
+ }
65
+ if (action === "update") {
66
+ const updates = await updateTaps(home, rest[0]);
67
+ updates.forEach((update) => {
68
+ io.stdout(update.changed
69
+ ? `Updated ${update.name}: ${update.before.slice(0, 12)} -> ${update.after.slice(0, 12)}.`
70
+ : `${update.name} is already up-to-date.`);
71
+ });
72
+ return 0;
73
+ }
74
+ if (action === "remove") {
75
+ const [name] = rest;
76
+ if (name === undefined)
77
+ throw new HarnessBrewError("Usage: harnessbrew tap remove <owner/name>");
78
+ await removeTap(home, name);
79
+ io.stdout(`Untapped ${name}.`);
80
+ return 0;
81
+ }
82
+ throw new HarnessBrewError(`Unknown tap action: ${action}`);
83
+ }
84
+ async function execute(args, io, options) {
85
+ const [command] = args;
86
+ if (command === undefined || command === "help" || command === "--help" || command === "-h") {
87
+ io.stdout(helpText.trimEnd());
88
+ return 0;
89
+ }
90
+ if (command === "version" || command === "--version" || command === "-v") {
91
+ io.stdout(VERSION);
92
+ return 0;
93
+ }
94
+ const home = resolveHarnessHome(options.home);
95
+ if (command === "tap") {
96
+ return runTapCommand(args.slice(1), home, io);
97
+ }
98
+ if (command === "update") {
99
+ const updates = await updateTaps(home);
100
+ updates.forEach((update) => io.stdout(update.changed
101
+ ? `Updated ${update.name}: ${update.before.slice(0, 12)} -> ${update.after.slice(0, 12)}.`
102
+ : `${update.name} is already up-to-date.`));
103
+ return 0;
104
+ }
105
+ if (command === "untap") {
106
+ const name = args[1];
107
+ if (name === undefined)
108
+ throw new HarnessBrewError("Usage: harnessbrew untap <owner/name>");
109
+ await removeTap(home, name);
110
+ io.stdout(`Untapped ${name}.`);
111
+ return 0;
112
+ }
113
+ if (command === "search") {
114
+ const kindValue = optionValue(args, "--kind");
115
+ if (kindValue !== undefined && !formulaKinds.includes(kindValue)) {
116
+ throw new HarnessBrewError(`Unsupported formula kind: ${kindValue}`);
117
+ }
118
+ const target = optionValue(args, "--target");
119
+ const query = args.slice(1).find((value, index, values) => {
120
+ if (value.startsWith("--"))
121
+ return false;
122
+ return index === 0 || !values[index - 1]?.startsWith("--");
123
+ }) ?? "";
124
+ const formulas = await searchFormulas(home, query, {
125
+ ...(kindValue === undefined ? {} : { kind: kindValue }),
126
+ ...(target === undefined ? {} : { target })
127
+ });
128
+ formulas.forEach((formula) => io.stdout(`${formula.coordinate}\t${formula.kind}\t${formula.description}`));
129
+ return 0;
130
+ }
131
+ if (command === "info") {
132
+ const name = args[1];
133
+ if (name === undefined)
134
+ throw new HarnessBrewError("Usage: harnessbrew info <formula>");
135
+ const formula = await getFormula(home, name);
136
+ io.stdout(JSON.stringify({
137
+ coordinate: formula.coordinate,
138
+ kind: formula.kind,
139
+ description: formula.description,
140
+ targets: formula.targets,
141
+ dependencies: formula.dependencies,
142
+ commit: formula.commit,
143
+ ...(formula.deprecated === undefined ? {} : { deprecated: formula.deprecated })
144
+ }, null, 2));
145
+ return 0;
146
+ }
147
+ if (command === "install") {
148
+ const name = args[1];
149
+ if (name === undefined)
150
+ throw new HarnessBrewError("Usage: harnessbrew install <formula>");
151
+ const targetValue = optionValue(args, "--target");
152
+ if (targetValue !== undefined && !builtinTargets.includes(targetValue)) {
153
+ throw new HarnessBrewError(`Unsupported built-in target: ${targetValue}`);
154
+ }
155
+ const targetRoot = optionValue(args, "--target-root");
156
+ const receipts = targetValue === undefined
157
+ ? await installFormula(home, name)
158
+ : await installForTarget(home, name, targetValue, targetRoot === undefined ? {} : { root: targetRoot });
159
+ receipts.forEach((receipt) => io.stdout(`Installed ${receipt.coordinate} at ${receipt.commit.slice(0, 12)}.`));
160
+ return 0;
161
+ }
162
+ if (command === "list") {
163
+ const receipts = await listInstalled(home);
164
+ receipts.forEach((receipt) => io.stdout(`${receipt.coordinate}\t${receipt.commit.slice(0, 12)}`));
165
+ return 0;
166
+ }
167
+ if (command === "uninstall") {
168
+ const name = args[1];
169
+ if (name === undefined)
170
+ throw new HarnessBrewError("Usage: harnessbrew uninstall <formula> [--force]");
171
+ const receipt = await uninstallFormula(home, name, { force: args.includes("--force") });
172
+ io.stdout(`Uninstalled ${receipt.coordinate}.`);
173
+ return 0;
174
+ }
175
+ if (command === "link" || command === "unlink") {
176
+ const name = args[1];
177
+ const targetValue = optionValue(args, "--target");
178
+ if (name === undefined || targetValue === undefined) {
179
+ throw new HarnessBrewError(`Usage: harnessbrew ${command} <formula> --target <target> [--target-root <path>]`);
180
+ }
181
+ if (!builtinTargets.includes(targetValue)) {
182
+ throw new HarnessBrewError(`Unsupported built-in target: ${targetValue}`);
183
+ }
184
+ if (command === "link") {
185
+ await linkFormula(home, name, targetValue, {
186
+ ...(optionValue(args, "--target-root") === undefined ? {} : { root: optionValue(args, "--target-root") })
187
+ });
188
+ io.stdout(`Linked ${name} to ${targetValue}.`);
189
+ }
190
+ else {
191
+ await unlinkFormula(home, name, targetValue, args.includes("--force"));
192
+ io.stdout(`Unlinked ${name} from ${targetValue}.`);
193
+ }
194
+ return 0;
195
+ }
196
+ if (command === "outdated") {
197
+ const outdated = await findOutdated(home);
198
+ outdated.forEach((item) => io.stdout(item.available
199
+ ? `${item.coordinate}\t${item.installedCommit.slice(0, 12)} -> ${item.availableCommit?.slice(0, 12)}`
200
+ : `${item.coordinate}\t${item.installedCommit.slice(0, 12)} -> unavailable`));
201
+ return 0;
202
+ }
203
+ if (command === "upgrade") {
204
+ const name = args[1]?.startsWith("--") === true ? undefined : args[1];
205
+ const results = await upgradeFormulas(home, name);
206
+ if (results.length === 0)
207
+ io.stdout("All installed formulas are up-to-date.");
208
+ results.forEach((result) => io.stdout(`Upgraded ${result.coordinate}: ${result.before.slice(0, 12)} -> ${result.after.slice(0, 12)}.`));
209
+ return 0;
210
+ }
211
+ if (command === "bundle") {
212
+ const action = args[1];
213
+ const filePath = optionValue(args, "--file") ?? path.resolve("Harnessfile");
214
+ if (action === "install") {
215
+ const lock = await bundleInstall(home, filePath);
216
+ io.stdout(`Bundle installed ${lock.assets.length} formulas from ${lock.taps.length} taps.`);
217
+ return 0;
218
+ }
219
+ if (action === "cleanup") {
220
+ const result = await bundleCleanup(home, filePath);
221
+ result.removed.forEach((coordinate) => io.stdout(`Removed ${coordinate}.`));
222
+ return 0;
223
+ }
224
+ throw new HarnessBrewError("Usage: harnessbrew bundle <install|cleanup> [--file <Harnessfile>]");
225
+ }
226
+ io.stderr(`Unknown command: ${command}`);
227
+ io.stderr("Run 'harnessbrew help' for usage.");
228
+ return 1;
229
+ }
230
+ export async function runCli(args, io = defaultIO, options = {}) {
231
+ try {
232
+ return await execute(args, io, options);
233
+ }
234
+ catch (error) {
235
+ if (error instanceof HarnessBrewError) {
236
+ io.stderr(error.message);
237
+ return 1;
238
+ }
239
+ throw error;
240
+ }
241
+ }
242
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}