@thebushidocollective/han 1.56.4 → 3.4.2

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.
package/README.md CHANGED
@@ -1,234 +1,29 @@
1
1
  # Han CLI
2
2
 
3
- **Sophisticated Claude Code Plugins with Superior Accuracy**
3
+ CLI for installing and managing curated Claude Code plugins from the [Han marketplace](https://han.guru).
4
4
 
5
- A curated marketplace of Claude Code plugins built on the foundation of the seven Bushido virtues. Master your craft through disciplined practice, quality craftsmanship, and continuous improvement.
6
-
7
- ## Installation
8
-
9
- ### Quick Install (Recommended)
10
-
11
- Install the han binary for fastest execution and automatic hook support:
12
-
13
- ```bash
14
- curl -fsSL https://han.guru/install.sh | bash
15
- ```
16
-
17
- This installs to `~/.claude/bin/han`, which is automatically added to PATH by Claude Code.
18
-
19
- ### Alternative: Homebrew
20
-
21
- ```bash
22
- brew install thebushidocollective/tap/han
23
- ```
24
-
25
- **Note:** The `core` plugin automatically installs the han binary when you start a Claude Code session, so manual installation is optional.
26
-
27
- ## Plugin Categories
28
-
29
- Han organizes plugins into five categories inspired by Japanese samurai traditions:
30
-
31
- - **Core** (⚙️) - **Required infrastructure** - Auto-installs han binary, provides hook system, MCP servers, and universal principles
32
- - **Bushido** (武士道) - Core principles, enforcement hooks, and foundational quality skills (strongly recommended)
33
- - **Do** (道 - The Way) - Specialized agents for development disciplines and practices
34
- - **Jutsu** (術 - Techniques) - Language and tool skills with validation hooks for quality
35
- - **Hashi** (橋 - Bridges) - MCP servers providing external knowledge and integrations
36
-
37
- > **Important:** The `core` plugin is always required and automatically included with `--auto` installation.
38
-
39
- ## Commands
40
-
41
- ### plugin install
42
-
43
- Install plugins interactively or automatically.
44
-
45
- ```bash
46
- # Interactive mode - browse and select plugins
47
- han plugin install
48
-
49
- # Auto-detect mode - AI analyzes codebase and recommends plugins
50
- han plugin install --auto
51
-
52
- # Install specific plugin by name
53
- han plugin install <plugin-name>
54
- ```
55
-
56
- **Options:**
57
-
58
- - `--auto` - Use AI to analyze your codebase and recommend plugins:
59
- - Shows installed and recommended plugins only
60
- - Recommended plugins marked with ⭐ and pre-selected
61
- - Installed but no longer recommended plugins marked as "(installed)" and deselected
62
- - Other plugins discoverable via "🔍 Search for more plugins"
63
- - Based on: Programming languages, frameworks, git platform, testing tools
64
- - `--scope <project|local>` - Installation scope (default: `project`)
65
- - `project`: Install to `.claude/settings.json` (shared via git)
66
- - `local`: Install to `.claude/settings.local.json` (git-ignored)
67
-
68
- ### plugin uninstall
69
-
70
- Remove a specific plugin.
71
-
72
- ```bash
73
- han plugin uninstall <plugin-name> [--scope <project|local>]
74
- ```
75
-
76
- ### plugin search
77
-
78
- Search for plugins in the Han marketplace.
79
-
80
- ```bash
81
- han plugin search [query]
82
- ```
83
-
84
- ### plugin update-marketplace
85
-
86
- Update the local marketplace cache from GitHub.
87
-
88
- ```bash
89
- han plugin update-marketplace
90
- ```
91
-
92
- The marketplace cache is automatically refreshed every 24 hours when using `han plugin install` or `han plugin search`. Use this command to manually force a refresh if you want to see the latest plugins immediately.
93
-
94
- **Features:**
95
-
96
- - Caches marketplace data locally in `~/.claude/cache/han-marketplace.json`
97
- - Automatically refreshes after 24 hours
98
- - Falls back to stale cache if network is unavailable
99
- - Shows cache age and available categories after update
100
-
101
- ### hook run
102
-
103
- Run a hook command defined by a plugin.
104
-
105
- ```bash
106
- # New format (recommended) - uses plugin's han-config.json
107
- han hook run <plugin-name> <hook-name> [options]
108
-
109
- # Legacy format - run arbitrary commands in matching directories
110
- han hook run --dirs-with <pattern> -- <command>
111
- ```
112
-
113
- **Options:**
114
-
115
- - `--fail-fast` - Stop on first failure (default: true)
116
- - `--cached` - Skip if no relevant files have changed since last successful run
117
- - `--only=<dir>` - Only run in the specified directory
118
- - `--verbose` - Show full command output
119
-
120
- **Examples:**
121
-
122
- ```bash
123
- # Run TypeScript type checking using plugin config
124
- han hook run jutsu-typescript typecheck
125
-
126
- # Run with caching (skip if no changes)
127
- han hook run jutsu-elixir test --cached
128
-
129
- # Run in a specific directory only
130
- han hook run jutsu-biome lint --only=packages/core
131
-
132
- # Legacy: Run npm test in all directories with package.json
133
- han hook run --dirs-with package.json -- npm test
134
- ```
135
-
136
- ### hook explain
137
-
138
- Show comprehensive information about configured hooks.
139
-
140
- ```bash
141
- han hook explain [hookType] [--all]
142
- ```
143
-
144
- **Options:**
145
-
146
- - `[hookType]` - Filter by hook type (e.g., `Stop`, `SessionStart`)
147
- - `--all` - Include hooks from Claude Code settings (not just Han plugins)
148
-
149
- **Examples:**
5
+ ## Usage
150
6
 
151
7
  ```bash
152
- # Show all Han plugin hooks
153
- han hook explain
154
-
155
- # Show only Stop hooks
156
- han hook explain Stop
8
+ # Run directly via npx
9
+ npx @thebushidocollective/han plugin install --auto
157
10
 
158
- # Show all hooks including settings
159
- han hook explain --all
11
+ # Or install globally
12
+ npm install -g @thebushidocollective/han
13
+ han plugin list
160
14
  ```
161
15
 
162
- ### hook dispatch
16
+ ## MCP Server Usage
163
17
 
164
- Dispatch hooks of a specific type across all installed Han plugins.
18
+ Configure in your Claude Code plugin:
165
19
 
166
- ```bash
167
- han hook dispatch <hookType> [--all]
20
+ ```json
21
+ {
22
+ "mcpServers": {
23
+ "han": {
24
+ "command": "npx",
25
+ "args": ["-y", "@thebushidocollective/han", "mcp"]
26
+ }
27
+ }
28
+ }
168
29
  ```
169
-
170
- This is useful for triggering hooks manually or for workarounds when plugin hook output needs to be passed to the agent.
171
-
172
- **Examples:**
173
-
174
- ```bash
175
- # Dispatch SessionStart hooks
176
- han hook dispatch SessionStart
177
-
178
- # Dispatch Stop hooks including settings hooks
179
- han hook dispatch Stop --all
180
- ```
181
-
182
- ### hook test
183
-
184
- Validate hook configurations for all installed plugins.
185
-
186
- ```bash
187
- # Validate hook structure and syntax only
188
- han hook test
189
-
190
- # Validate AND execute hooks to verify they run successfully
191
- han hook test --execute
192
- ```
193
-
194
- ### mcp
195
-
196
- Start the Han MCP server for natural language hook execution.
197
-
198
- ```bash
199
- han mcp
200
- ```
201
-
202
- The MCP server dynamically exposes tools based on your installed plugins. Once installed via `hashi-han`, you can run hooks using natural language like "run the elixir tests" instead of remembering exact commands.
203
-
204
- **Generated tools include:**
205
-
206
- - `jutsu_elixir_test` - Run tests for Elixir projects
207
- - `jutsu_typescript_typecheck` - Run TypeScript type checking
208
- - `jutsu_biome_lint` - Run Biome linting
209
-
210
- See the [hashi-han plugin](/hashi/hashi-han) for installation and configuration.
211
-
212
- ### uninstall
213
-
214
- Remove all Han plugins and marketplace configuration.
215
-
216
- ```bash
217
- han uninstall
218
- ```
219
-
220
- ## Philosophy
221
-
222
- > "Beginning is easy - continuing is hard." - Japanese Proverb
223
-
224
- Walk the way of Bushido. Practice with Discipline. Build with Honor.
225
-
226
- ## Links
227
-
228
- - [Han Marketplace](https://han.guru)
229
- - [GitHub](https://github.com/thebushidocollective/han)
230
- - [The Bushido Collective](https://thebushido.co)
231
-
232
- ## License
233
-
234
- MIT
package/bin.js ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ const { execFileSync } = require('child_process');
3
+ const { existsSync } = require('fs');
4
+ const { join } = require('path');
5
+
6
+ const platform = process.platform;
7
+ const arch = process.arch;
8
+
9
+ // Map Node.js platform/arch to our package names
10
+ const platformMap = {
11
+ 'darwin-arm64': 'darwin-arm64',
12
+ 'darwin-x64': 'darwin-x64',
13
+ 'linux-arm64': 'linux-arm64',
14
+ 'linux-x64': 'linux-x64',
15
+ 'win32-x64': 'win32-x64',
16
+ };
17
+
18
+ const key = `${platform}-${arch}`;
19
+ const pkgName = platformMap[key];
20
+
21
+ if (!pkgName) {
22
+ console.error(`Unsupported platform: ${platform}-${arch}`);
23
+ process.exit(1);
24
+ }
25
+
26
+ // Try to find the binary in node_modules
27
+ const binName = platform === 'win32' ? 'han.exe' : 'han';
28
+ const paths = [
29
+ // Installed as dependency
30
+ join(__dirname, '..', '@thebushidocollective', `han-${pkgName}`, binName),
31
+ // npx cache location
32
+ join(__dirname, 'node_modules', '@thebushidocollective', `han-${pkgName}`, binName),
33
+ ];
34
+
35
+ let binPath = paths.find(p => existsSync(p));
36
+
37
+ if (!binPath) {
38
+ // Try to install the platform package on-demand
39
+ try {
40
+ const pkg = `@thebushidocollective/han-${pkgName}`;
41
+ console.error(`Installing ${pkg}...`);
42
+ execFileSync('npm', ['install', '--no-save', pkg], {
43
+ stdio: 'inherit',
44
+ cwd: __dirname
45
+ });
46
+ binPath = join(__dirname, 'node_modules', '@thebushidocollective', `han-${pkgName}`, binName);
47
+ } catch (e) {
48
+ console.error(`Failed to install platform package: ${e.message}`);
49
+ process.exit(1);
50
+ }
51
+ }
52
+
53
+ if (!existsSync(binPath)) {
54
+ console.error(`Binary not found at ${binPath}`);
55
+ process.exit(1);
56
+ }
57
+
58
+ // Execute the binary with all arguments
59
+ try {
60
+ execFileSync(binPath, process.argv.slice(2), { stdio: 'inherit' });
61
+ } catch (e) {
62
+ process.exit(e.status || 1);
63
+ }
package/package.json CHANGED
@@ -1,78 +1,29 @@
1
1
  {
2
- "name": "@thebushidocollective/han",
3
- "version": "1.56.4",
4
- "description": "CLI for installing and managing curated Claude Code plugins from the Han marketplace",
5
- "main": "dist/lib/main.js",
6
- "types": "dist/lib/main.d.ts",
7
- "type": "module",
8
- "bin": {
9
- "han": "bin/han.js"
10
- },
11
- "scripts": {
12
- "typecheck": "tsc --noEmit",
13
- "test": "bun test test/han.test.ts",
14
- "test:source": "HAN_TEST_SOURCE=true bun test test/han.test.ts",
15
- "lint": "biome check .",
16
- "lint:fix": "biome check --write .",
17
- "prepack": "npm test",
18
- "build:binary": "bun scripts/build-bundle.js",
19
- "build:bundle": "bun scripts/build-bundle.js"
20
- },
21
- "repository": {
22
- "type": "git",
23
- "url": "git+https://github.com/TheBushidoCollective/han.git"
24
- },
25
- "homepage": "https://han.guru",
26
- "bugs": {
27
- "url": "https://github.com/TheBushidoCollective/han/issues"
28
- },
29
- "keywords": [
30
- "bushido",
31
- "validation",
32
- "hooks",
33
- "claude",
34
- "claude-code",
35
- "testing",
36
- "ci"
37
- ],
38
- "author": "The Bushido Collective",
39
- "license": "MIT",
40
- "engines": {
41
- "node": ">=20"
42
- },
43
- "files": [
44
- "bin/",
45
- "schemas/",
46
- "README.md"
47
- ],
48
- "optionalDependencies": {
49
- "@thebushidocollective/han-darwin-arm64": "1.56.4",
50
- "@thebushidocollective/han-darwin-x64": "1.56.4",
51
- "@thebushidocollective/han-linux-arm64": "1.56.4",
52
- "@thebushidocollective/han-linux-x64": "1.56.4",
53
- "@thebushidocollective/han-win32-x64": "1.56.4"
54
- },
55
- "devDependencies": {
56
- "@anthropic-ai/claude-agent-sdk": "0.1.50",
57
- "@biomejs/biome": "2.3.7",
58
- "@types/marked-terminal": "6.1.1",
59
- "@types/node": "24.10.1",
60
- "@types/react": "19.2.6",
61
- "@types/sentiment": "^5.0.4",
62
- "commander": "14.0.2",
63
- "dotenv": "^17.2.3",
64
- "esbuild": "^0.27.0",
65
- "ink": "6.5.1",
66
- "ink-select-input": "^6.2.0",
67
- "ink-spinner": "5.0.0",
68
- "ink-text-input": "^6.0.0",
69
- "marked-terminal": "7.3.0",
70
- "react": "19.2.0",
71
- "react-devtools-core": "^6.1.5",
72
- "typescript": "5.9.3",
73
- "yaml": "^2.8.1"
74
- },
75
- "dependencies": {
76
- "sentiment": "^5.0.2"
77
- }
2
+ "name": "@thebushidocollective/han",
3
+ "version": "3.4.2",
4
+ "description": "CLI for installing and managing curated Claude Code plugins from the Han marketplace",
5
+ "homepage": "https://han.guru",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/TheBushidoCollective/han"
10
+ },
11
+ "bin": {
12
+ "han": "bin.js"
13
+ },
14
+ "optionalDependencies": {
15
+ "@thebushidocollective/han-darwin-arm64": "3.4.2",
16
+ "@thebushidocollective/han-darwin-x64": "3.4.2",
17
+ "@thebushidocollective/han-linux-arm64": "3.4.2",
18
+ "@thebushidocollective/han-linux-x64": "3.4.2",
19
+ "@thebushidocollective/han-win32-x64": "3.4.2"
20
+ },
21
+ "keywords": [
22
+ "claude",
23
+ "claude-code",
24
+ "plugins",
25
+ "mcp",
26
+ "han",
27
+ "bushido"
28
+ ]
78
29
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 The Bushido Collective
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/bin/han.js DELETED
@@ -1,261 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { execSync, spawnSync } from "node:child_process";
4
- import { existsSync, readFileSync } from "node:fs";
5
- import { createRequire } from "node:module";
6
- import { dirname, join } from "node:path";
7
- import { fileURLToPath } from "node:url";
8
-
9
- const __dirname = dirname(fileURLToPath(import.meta.url));
10
-
11
- // Self-repair: detect stale npx cache and fix it
12
- async function selfRepairIfNeeded() {
13
- // Skip if already in repair mode (prevent infinite loops)
14
- if (process.env.HAN_SELF_REPAIR === "1") {
15
- return;
16
- }
17
-
18
- // Skip for version/help commands (let user see current version)
19
- const args = process.argv.slice(2);
20
- if (
21
- args.includes("--version") ||
22
- args.includes("-V") ||
23
- args.includes("--help") ||
24
- args.includes("-h") ||
25
- args.length === 0
26
- ) {
27
- return;
28
- }
29
-
30
- // Only run for npx invocations (check if in _npx cache directory)
31
- const scriptPath = fileURLToPath(import.meta.url);
32
- if (!scriptPath.includes("_npx")) {
33
- return;
34
- }
35
-
36
- try {
37
- // Get current version
38
- const packageJsonPath = join(__dirname, "..", "package.json");
39
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
40
- const currentVersion = packageJson.version;
41
-
42
- // Fetch latest version from npm (with short timeout)
43
- const controller = new AbortController();
44
- const timeout = setTimeout(() => controller.abort(), 3000);
45
-
46
- const response = await fetch(
47
- "https://registry.npmjs.org/@thebushidocollective/han",
48
- { signal: controller.signal },
49
- );
50
- clearTimeout(timeout);
51
-
52
- if (!response.ok) {
53
- return;
54
- }
55
-
56
- const data = await response.json();
57
- const latestVersion = data["dist-tags"]?.latest;
58
-
59
- if (!latestVersion || currentVersion === latestVersion) {
60
- return;
61
- }
62
-
63
- // Compare versions (simple semver comparison)
64
- const current = currentVersion.split(".").map(Number);
65
- const latest = latestVersion.split(".").map(Number);
66
-
67
- const isBehind =
68
- current[0] < latest[0] ||
69
- (current[0] === latest[0] && current[1] < latest[1]) ||
70
- (current[0] === latest[0] &&
71
- current[1] === latest[1] &&
72
- current[2] < latest[2]);
73
-
74
- if (!isBehind) {
75
- return;
76
- }
77
-
78
- console.error(
79
- `\x1b[33m⚠ Stale npx cache detected (v${currentVersion} < v${latestVersion}), repairing...\x1b[0m`,
80
- );
81
-
82
- // Clear npx cache
83
- try {
84
- execSync("npx clear-npx-cache", { stdio: "pipe" });
85
- } catch {
86
- // Try manual clear if clear-npx-cache not available
87
- const { homedir } = await import("node:os");
88
- const npxCachePath = join(homedir(), ".npm", "_npx");
89
- if (existsSync(npxCachePath)) {
90
- const { rmSync } = await import("node:fs");
91
- rmSync(npxCachePath, { recursive: true, force: true });
92
- }
93
- }
94
-
95
- // Re-exec with the exact version we fetched
96
- const result = spawnSync(
97
- "npx",
98
- ["-y", `@thebushidocollective/han@${latestVersion}`, ...args],
99
- {
100
- stdio: "inherit",
101
- env: { ...process.env, HAN_SELF_REPAIR: "1" },
102
- shell: true,
103
- },
104
- );
105
-
106
- process.exit(result.status ?? 0);
107
- } catch {
108
- // Silently continue if self-repair fails (network issues, etc.)
109
- }
110
- }
111
-
112
- await selfRepairIfNeeded();
113
- const require = createRequire(import.meta.url);
114
-
115
- // Platform package mapping
116
- const platformPackages = {
117
- "darwin-arm64": "@thebushidocollective/han-darwin-arm64",
118
- "darwin-x64": "@thebushidocollective/han-darwin-x64",
119
- "linux-x64": "@thebushidocollective/han-linux-x64",
120
- "linux-arm64": "@thebushidocollective/han-linux-arm64",
121
- "win32-x64": "@thebushidocollective/han-win32-x64",
122
- };
123
-
124
- function getPlatformKey() {
125
- return `${process.platform}-${process.arch}`;
126
- }
127
-
128
- function tryRunBinary() {
129
- const platformKey = getPlatformKey();
130
- const packageName = platformPackages[platformKey];
131
-
132
- if (!packageName) {
133
- return false;
134
- }
135
-
136
- try {
137
- // Try to resolve the platform package
138
- const pkgPath = require.resolve(`${packageName}/package.json`);
139
- const pkgDir = dirname(pkgPath);
140
- const binaryName = process.platform === "win32" ? "han.exe" : "han";
141
- const binaryPath = join(pkgDir, binaryName);
142
-
143
- if (!existsSync(binaryPath)) {
144
- return false;
145
- }
146
-
147
- // Run the binary
148
- const result = spawnSync(binaryPath, process.argv.slice(2), {
149
- stdio: "inherit",
150
- windowsHide: true,
151
- });
152
-
153
- if (result.error) {
154
- return false;
155
- }
156
-
157
- process.exit(result.status ?? 0);
158
- } catch {
159
- return false;
160
- }
161
- }
162
-
163
- // Retry logic for CDN propagation delays
164
- async function waitForPackageAvailability(packageName, maxRetries = 5) {
165
- const baseDelay = 2000; // 2 seconds
166
-
167
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
168
- try {
169
- const controller = new AbortController();
170
- const timeout = setTimeout(() => controller.abort(), 5000);
171
-
172
- const response = await fetch(
173
- `https://registry.npmjs.org/${packageName}`,
174
- { signal: controller.signal },
175
- );
176
- clearTimeout(timeout);
177
-
178
- if (response.ok) {
179
- const data = await response.json();
180
- if (data["dist-tags"]?.latest) {
181
- return true;
182
- }
183
- }
184
- } catch {
185
- // Network error, continue retrying
186
- }
187
-
188
- if (attempt < maxRetries) {
189
- const delay = baseDelay * 2 ** (attempt - 1); // Exponential backoff
190
- console.error(
191
- `\x1b[33m⏳ Waiting for package availability (attempt ${attempt}/${maxRetries})...\x1b[0m`,
192
- );
193
- await new Promise((resolve) => setTimeout(resolve, delay));
194
- }
195
- }
196
-
197
- return false;
198
- }
199
-
200
- // Run binary - no JS fallback in production
201
- if (!tryRunBinary()) {
202
- const platformKey = getPlatformKey();
203
- const packageName = platformPackages[platformKey];
204
-
205
- if (!packageName) {
206
- console.error(`\x1b[31mError: Unsupported platform: ${platformKey}\x1b[0m`);
207
- console.error(
208
- "Supported platforms: darwin-arm64, darwin-x64, linux-x64, linux-arm64, win32-x64",
209
- );
210
- process.exit(1);
211
- }
212
-
213
- // Check if this might be a CDN propagation issue and retry
214
- const scriptPath = fileURLToPath(import.meta.url);
215
- if (scriptPath.includes("_npx") && !process.env.HAN_NO_RETRY) {
216
- console.error(
217
- `\x1b[33m⚠ Platform binary not found, checking for CDN propagation delay...\x1b[0m`,
218
- );
219
-
220
- const isAvailable = await waitForPackageAvailability(packageName);
221
-
222
- if (isAvailable) {
223
- // Clear cache and retry once more
224
- try {
225
- execSync("npx clear-npx-cache", { stdio: "pipe" });
226
- } catch {
227
- const { homedir } = await import("node:os");
228
- const npxCachePath = join(homedir(), ".npm", "_npx");
229
- if (existsSync(npxCachePath)) {
230
- const { rmSync } = await import("node:fs");
231
- rmSync(npxCachePath, { recursive: true, force: true });
232
- }
233
- }
234
-
235
- console.error(`\x1b[32m✓ Package available, retrying...\x1b[0m`);
236
-
237
- const args = process.argv.slice(2);
238
- const result = spawnSync(
239
- "npx",
240
- ["-y", "@thebushidocollective/han@latest", ...args],
241
- {
242
- stdio: "inherit",
243
- env: { ...process.env, HAN_NO_RETRY: "1" },
244
- shell: true,
245
- },
246
- );
247
-
248
- process.exit(result.status ?? 0);
249
- }
250
- }
251
-
252
- console.error(
253
- `\x1b[31mError: Platform binary not found for ${platformKey}\x1b[0m`,
254
- );
255
- console.error(`Expected package: ${packageName}`);
256
- console.error("\nTry reinstalling:");
257
- console.error(" npm cache clean --force");
258
- console.error(" npx clear-npx-cache");
259
- console.error(" han@latest --version");
260
- process.exit(1);
261
- }
@@ -1,62 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$id": "https://han.guru/schemas/han-config-override.schema.json",
4
- "title": "Han User Override Configuration",
5
- "description": "Configuration schema for han-config.yml files that override plugin defaults",
6
- "type": "object",
7
- "additionalProperties": {
8
- "$ref": "#/definitions/pluginOverrides"
9
- },
10
- "definitions": {
11
- "pluginOverrides": {
12
- "type": "object",
13
- "description": "Overrides for a specific plugin (keyed by plugin name, e.g., 'jutsu-biome')",
14
- "additionalProperties": {
15
- "$ref": "#/definitions/hookOverride"
16
- }
17
- },
18
- "hookOverride": {
19
- "type": "object",
20
- "description": "Override settings for a specific hook",
21
- "properties": {
22
- "enabled": {
23
- "type": "boolean",
24
- "description": "Whether this hook is enabled for this directory. Set to false to disable.",
25
- "default": true
26
- },
27
- "command": {
28
- "type": "string",
29
- "description": "Override the command to execute for this hook"
30
- },
31
- "if_changed": {
32
- "type": "array",
33
- "items": {
34
- "type": "string"
35
- },
36
- "description": "Additional glob patterns for change detection. These patterns are merged with (added to) the plugin's ifChanged patterns."
37
- },
38
- "idle_timeout": {
39
- "oneOf": [
40
- {
41
- "type": "integer",
42
- "minimum": 1,
43
- "description": "Override the idle timeout in milliseconds"
44
- },
45
- {
46
- "type": "boolean",
47
- "const": false,
48
- "description": "Set to false to disable idle timeout checking"
49
- },
50
- {
51
- "type": "integer",
52
- "const": 0,
53
- "description": "Set to 0 to disable idle timeout checking"
54
- }
55
- ],
56
- "description": "Override the idle timeout. Set to a number (milliseconds), false, or 0 to disable."
57
- }
58
- },
59
- "additionalProperties": false
60
- }
61
- }
62
- }
@@ -1,55 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$id": "https://han.guru/schemas/han-config.schema.json",
4
- "title": "Han Plugin Configuration",
5
- "description": "Configuration schema for han-config.json files in Han plugins",
6
- "type": "object",
7
- "properties": {
8
- "hooks": {
9
- "type": "object",
10
- "description": "Hook definitions for the plugin",
11
- "additionalProperties": {
12
- "$ref": "#/definitions/hookDefinition"
13
- }
14
- }
15
- },
16
- "required": ["hooks"],
17
- "additionalProperties": false,
18
- "definitions": {
19
- "hookDefinition": {
20
- "type": "object",
21
- "description": "Definition for a single hook",
22
- "properties": {
23
- "command": {
24
- "type": "string",
25
- "description": "The command to execute for this hook"
26
- },
27
- "dirsWith": {
28
- "type": "array",
29
- "items": {
30
- "type": "string"
31
- },
32
- "description": "Glob patterns for marker files. The hook runs in directories containing these files."
33
- },
34
- "dirTest": {
35
- "type": "string",
36
- "description": "Shell command that must exit 0 for a directory to be included"
37
- },
38
- "ifChanged": {
39
- "type": "array",
40
- "items": {
41
- "type": "string"
42
- },
43
- "description": "Glob patterns relative to each target directory. When --cache is enabled, the hook will only run if files matching these patterns have changed."
44
- },
45
- "idleTimeout": {
46
- "type": "integer",
47
- "minimum": 0,
48
- "description": "Maximum time in milliseconds to wait for output before considering the hook as hanging. If no output is received within this period, the hook will be terminated and reported as failed."
49
- }
50
- },
51
- "required": ["command"],
52
- "additionalProperties": false
53
- }
54
- }
55
- }