@thebushidocollective/han 1.4.0 → 1.6.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.
- package/README.md +15 -5
- package/dist/lib/align-progress.d.ts +1 -1
- package/dist/lib/align-progress.d.ts.map +1 -1
- package/dist/lib/align.d.ts +1 -10
- package/dist/lib/align.d.ts.map +1 -1
- package/dist/lib/align.js +24 -116
- package/dist/lib/align.js.map +1 -1
- package/dist/lib/install-progress.d.ts +1 -1
- package/dist/lib/install-progress.d.ts.map +1 -1
- package/dist/lib/install.d.ts +0 -10
- package/dist/lib/install.d.ts.map +1 -1
- package/dist/lib/install.js +1 -115
- package/dist/lib/install.js.map +1 -1
- package/dist/lib/main.js +8 -5
- package/dist/lib/main.js.map +1 -1
- package/dist/lib/shared.d.ts +53 -0
- package/dist/lib/shared.d.ts.map +1 -0
- package/dist/lib/shared.js +134 -0
- package/dist/lib/shared.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,9 +82,12 @@ npx @thebushidocollective/han align [--scope <project|local>]
|
|
|
82
82
|
|
|
83
83
|
**Options:**
|
|
84
84
|
|
|
85
|
-
- `--scope <project|local>` - Alignment scope (
|
|
85
|
+
- `--scope <project|local>` - Alignment scope (optional, auto-detects if not specified)
|
|
86
86
|
- `project`: Align plugins in `.claude/settings.json` (shared via git)
|
|
87
87
|
- `local`: Align plugins in `.claude/settings.local.json` (git-ignored, machine-specific)
|
|
88
|
+
- If not specified, automatically detects which scope(s) have Han installed and aligns those
|
|
89
|
+
- If Han is installed in both scopes, aligns both
|
|
90
|
+
- If Han is not installed anywhere, defaults to `project`
|
|
88
91
|
|
|
89
92
|
**How it works:**
|
|
90
93
|
|
|
@@ -99,19 +102,26 @@ npx @thebushidocollective/han align [--scope <project|local>]
|
|
|
99
102
|
- After adding new dependencies or frameworks
|
|
100
103
|
- After removing technologies from your project
|
|
101
104
|
- Periodically to keep plugins in sync with your codebase
|
|
102
|
-
- Automatically via
|
|
105
|
+
- Automatically via Stop and PreCompact hooks (see below)
|
|
103
106
|
|
|
104
107
|
**Automatic Alignment:**
|
|
105
108
|
|
|
106
|
-
The bushido plugin includes
|
|
109
|
+
The bushido plugin includes hooks that automatically run `han align`:
|
|
110
|
+
- **Stop hook**: Runs at the end of each Claude Code session
|
|
111
|
+
- **PreCompact hook**: Runs before compacting conversation history
|
|
112
|
+
|
|
113
|
+
This ensures your plugins stay synchronized with your codebase as it evolves.
|
|
107
114
|
|
|
108
115
|
**Examples:**
|
|
109
116
|
|
|
110
117
|
```bash
|
|
111
|
-
#
|
|
118
|
+
# Auto-detect and align all scopes where Han is installed
|
|
112
119
|
npx @thebushidocollective/han align
|
|
113
120
|
|
|
114
|
-
#
|
|
121
|
+
# Explicitly align project settings only
|
|
122
|
+
npx @thebushidocollective/han align --scope project
|
|
123
|
+
|
|
124
|
+
# Explicitly align local settings only
|
|
115
125
|
npx @thebushidocollective/han align --scope local
|
|
116
126
|
```
|
|
117
127
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"align-progress.d.ts","sourceRoot":"","sources":["../../lib/align-progress.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAe,sBAAsB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"align-progress.d.ts","sourceRoot":"","sources":["../../lib/align-progress.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAe,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGvE,UAAU,kBAAkB;IAC1B,aAAa,EAAE,CAAC,SAAS,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC7C,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA+MtD,CAAC"}
|
package/dist/lib/align.d.ts
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
|
-
export interface AgentUpdate {
|
|
2
|
-
type: 'text' | 'tool';
|
|
3
|
-
content: string;
|
|
4
|
-
toolName?: string;
|
|
5
|
-
}
|
|
6
1
|
export interface AlignResult {
|
|
7
2
|
added: string[];
|
|
8
3
|
removed: string[];
|
|
9
4
|
unchanged: string[];
|
|
10
5
|
}
|
|
11
|
-
export interface DetectPluginsCallbacks {
|
|
12
|
-
onUpdate: (update: AgentUpdate) => void;
|
|
13
|
-
onComplete: (plugins: string[], fullText: string) => void;
|
|
14
|
-
onError: (error: Error) => void;
|
|
15
|
-
}
|
|
16
6
|
/**
|
|
17
7
|
* SDK-based align command with Ink UI
|
|
8
|
+
* If scope is not provided, auto-detects which scope(s) have Han installed
|
|
18
9
|
*/
|
|
19
10
|
export declare function align(scope?: 'project' | 'local'): Promise<void>;
|
|
20
11
|
//# sourceMappingURL=align.d.ts.map
|
package/dist/lib/align.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"align.d.ts","sourceRoot":"","sources":["../../lib/align.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"align.d.ts","sourceRoot":"","sources":["../../lib/align.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAoDD;;;GAGG;AACH,wBAAsB,KAAK,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBtE"}
|
package/dist/lib/align.js
CHANGED
|
@@ -1,120 +1,6 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
4
1
|
import { render } from 'ink';
|
|
5
2
|
import React from 'react';
|
|
6
|
-
import {
|
|
7
|
-
const HAN_MARKETPLACE_REPO = 'thebushidocollective/han';
|
|
8
|
-
function getClaudeSettingsPath(scope = 'project') {
|
|
9
|
-
const filename = scope === 'local' ? 'settings.local.json' : 'settings.json';
|
|
10
|
-
return join(process.cwd(), '.claude', filename);
|
|
11
|
-
}
|
|
12
|
-
function ensureClaudeDirectory() {
|
|
13
|
-
const settingsPath = getClaudeSettingsPath();
|
|
14
|
-
const claudeDir = join(settingsPath, '..');
|
|
15
|
-
if (!existsSync(claudeDir)) {
|
|
16
|
-
mkdirSync(claudeDir, { recursive: true });
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function readOrCreateSettings(scope = 'project') {
|
|
20
|
-
const settingsPath = getClaudeSettingsPath(scope);
|
|
21
|
-
if (existsSync(settingsPath)) {
|
|
22
|
-
try {
|
|
23
|
-
return JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
24
|
-
}
|
|
25
|
-
catch (_error) {
|
|
26
|
-
console.error(`Error reading ${scope === 'local' ? 'settings.local.json' : 'settings.json'}, creating new one`);
|
|
27
|
-
return {};
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return {};
|
|
31
|
-
}
|
|
32
|
-
function writeSettings(settings, scope = 'project') {
|
|
33
|
-
const settingsPath = getClaudeSettingsPath(scope);
|
|
34
|
-
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Get currently installed Han plugins
|
|
38
|
-
*/
|
|
39
|
-
function getInstalledPlugins(scope = 'project') {
|
|
40
|
-
const settings = readOrCreateSettings(scope);
|
|
41
|
-
const enabledPlugins = settings.enabledPlugins || {};
|
|
42
|
-
return Object.keys(enabledPlugins)
|
|
43
|
-
.filter((key) => key.endsWith('@han') && enabledPlugins[key])
|
|
44
|
-
.map((key) => key.replace('@han', ''));
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Use Claude Agent SDK to intelligently analyze codebase and recommend plugins
|
|
48
|
-
*/
|
|
49
|
-
async function detectPluginsWithAgent(callbacks) {
|
|
50
|
-
// Define allowed tools - only read-only operations
|
|
51
|
-
const allowedTools = ['web_fetch', 'read_file', 'glob', 'grep'];
|
|
52
|
-
const agent = query({
|
|
53
|
-
prompt: detectPluginsPrompt,
|
|
54
|
-
options: {
|
|
55
|
-
model: 'claude-haiku-4-20250514',
|
|
56
|
-
includePartialMessages: true,
|
|
57
|
-
allowedTools,
|
|
58
|
-
permissionMode: 'bypassPermissions',
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
let responseContent = '';
|
|
62
|
-
try {
|
|
63
|
-
// Collect all messages from the agent with live updates
|
|
64
|
-
for await (const sdkMessage of agent) {
|
|
65
|
-
if (sdkMessage.type === 'assistant' && sdkMessage.message.content) {
|
|
66
|
-
for (const block of sdkMessage.message.content) {
|
|
67
|
-
if (block.type === 'text') {
|
|
68
|
-
// Send text updates
|
|
69
|
-
callbacks.onUpdate({ type: 'text', content: block.text });
|
|
70
|
-
responseContent += block.text;
|
|
71
|
-
}
|
|
72
|
-
else if (block.type === 'tool_use') {
|
|
73
|
-
// Send tool usage updates
|
|
74
|
-
callbacks.onUpdate({
|
|
75
|
-
type: 'tool',
|
|
76
|
-
content: `Using ${block.name}`,
|
|
77
|
-
toolName: block.name,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
// Extract plugin recommendations from agent response
|
|
84
|
-
const plugins = parsePluginRecommendations(responseContent);
|
|
85
|
-
const finalPlugins = plugins.length > 0 ? plugins : ['bushido'];
|
|
86
|
-
callbacks.onComplete(finalPlugins, responseContent);
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
callbacks.onError(error);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Parse plugin recommendations from agent response
|
|
94
|
-
*/
|
|
95
|
-
function parsePluginRecommendations(content) {
|
|
96
|
-
try {
|
|
97
|
-
// Try to find JSON array in the response
|
|
98
|
-
const jsonMatch = content.match(/\[[\s\S]*?\]/);
|
|
99
|
-
if (jsonMatch) {
|
|
100
|
-
const plugins = JSON.parse(jsonMatch[0]);
|
|
101
|
-
if (Array.isArray(plugins)) {
|
|
102
|
-
plugins.push('bushido');
|
|
103
|
-
return plugins.filter((p) => typeof p === 'string');
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// Fallback: look for plugin names mentioned
|
|
107
|
-
const pluginPattern = /(buki-[\w-]+|do-[\w-]+|sensei-[\w-]+|bushido)/g;
|
|
108
|
-
const matches = content.match(pluginPattern);
|
|
109
|
-
if (matches) {
|
|
110
|
-
return [...new Set(matches)];
|
|
111
|
-
}
|
|
112
|
-
return [];
|
|
113
|
-
}
|
|
114
|
-
catch (_error) {
|
|
115
|
-
return [];
|
|
116
|
-
}
|
|
117
|
-
}
|
|
3
|
+
import { HAN_MARKETPLACE_REPO, ensureClaudeDirectory, readOrCreateSettings, writeSettings, getInstalledPlugins, detectPluginsWithAgent, detectHanScopes, } from './shared.js';
|
|
118
4
|
/**
|
|
119
5
|
* Compare current plugins with recommended plugins and update settings
|
|
120
6
|
*/
|
|
@@ -159,8 +45,30 @@ function alignPluginsInSettings(recommendedPlugins, scope = 'project') {
|
|
|
159
45
|
}
|
|
160
46
|
/**
|
|
161
47
|
* SDK-based align command with Ink UI
|
|
48
|
+
* If scope is not provided, auto-detects which scope(s) have Han installed
|
|
49
|
+
*/
|
|
50
|
+
export async function align(scope) {
|
|
51
|
+
// Auto-detect scopes if not explicitly provided
|
|
52
|
+
let scopesToAlign;
|
|
53
|
+
if (scope) {
|
|
54
|
+
scopesToAlign = [scope];
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
scopesToAlign = detectHanScopes();
|
|
58
|
+
// Default to project if Han not installed anywhere
|
|
59
|
+
if (scopesToAlign.length === 0) {
|
|
60
|
+
scopesToAlign = ['project'];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Align each detected scope
|
|
64
|
+
for (const currentScope of scopesToAlign) {
|
|
65
|
+
await alignSingleScope(currentScope);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Align plugins for a single scope
|
|
162
70
|
*/
|
|
163
|
-
|
|
71
|
+
async function alignSingleScope(scope) {
|
|
164
72
|
// Import Ink UI component dynamically
|
|
165
73
|
const { AlignProgress } = await import('./align-progress.js');
|
|
166
74
|
let resolveCompletion;
|
package/dist/lib/align.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"align.js","sourceRoot":"","sources":["../../lib/align.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"align.js","sourceRoot":"","sources":["../../lib/align.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DetectPluginsCallbacks } from './
|
|
1
|
+
import type { DetectPluginsCallbacks } from './shared.js';
|
|
2
2
|
interface InstallProgressProps {
|
|
3
3
|
detectPlugins: (callbacks: DetectPluginsCallbacks) => Promise<void>;
|
|
4
4
|
onInstallComplete: (plugins: string[]) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-progress.d.ts","sourceRoot":"","sources":["../../lib/install-progress.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAe,sBAAsB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"install-progress.d.ts","sourceRoot":"","sources":["../../lib/install-progress.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAe,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGvE,UAAU,oBAAoB;IAC5B,aAAa,EAAE,CAAC,SAAS,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA8M1D,CAAC"}
|
package/dist/lib/install.d.ts
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
export interface AgentUpdate {
|
|
2
|
-
type: 'text' | 'tool';
|
|
3
|
-
content: string;
|
|
4
|
-
toolName?: string;
|
|
5
|
-
}
|
|
6
|
-
export interface DetectPluginsCallbacks {
|
|
7
|
-
onUpdate: (update: AgentUpdate) => void;
|
|
8
|
-
onComplete: (plugins: string[], fullText: string) => void;
|
|
9
|
-
onError: (error: Error) => void;
|
|
10
|
-
}
|
|
11
1
|
/**
|
|
12
2
|
* SDK-based install command with Ink UI
|
|
13
3
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../lib/install.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../lib/install.ts"],"names":[],"mappings":"AA8CA;;GAEG;AACH,wBAAsB,OAAO,CAAC,KAAK,GAAE,SAAS,GAAG,OAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CnF"}
|
package/dist/lib/install.js
CHANGED
|
@@ -1,120 +1,6 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
4
1
|
import { render } from 'ink';
|
|
5
2
|
import React from 'react';
|
|
6
|
-
import {
|
|
7
|
-
const HAN_MARKETPLACE_REPO = 'thebushidocollective/han';
|
|
8
|
-
function getClaudeSettingsPath(scope = 'project') {
|
|
9
|
-
const filename = scope === 'local' ? 'settings.local.json' : 'settings.json';
|
|
10
|
-
return join(process.cwd(), '.claude', filename);
|
|
11
|
-
}
|
|
12
|
-
function ensureClaudeDirectory() {
|
|
13
|
-
const settingsPath = getClaudeSettingsPath();
|
|
14
|
-
const claudeDir = join(settingsPath, '..');
|
|
15
|
-
if (!existsSync(claudeDir)) {
|
|
16
|
-
mkdirSync(claudeDir, { recursive: true });
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function readOrCreateSettings(scope = 'project') {
|
|
20
|
-
const settingsPath = getClaudeSettingsPath(scope);
|
|
21
|
-
if (existsSync(settingsPath)) {
|
|
22
|
-
try {
|
|
23
|
-
return JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
24
|
-
}
|
|
25
|
-
catch (_error) {
|
|
26
|
-
console.error(`Error reading ${scope === 'local' ? 'settings.local.json' : 'settings.json'}, creating new one`);
|
|
27
|
-
return {};
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return {};
|
|
31
|
-
}
|
|
32
|
-
function writeSettings(settings, scope = 'project') {
|
|
33
|
-
const settingsPath = getClaudeSettingsPath(scope);
|
|
34
|
-
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Use Claude Agent SDK to intelligently analyze codebase and recommend plugins
|
|
38
|
-
*/
|
|
39
|
-
async function detectPluginsWithAgent(callbacks) {
|
|
40
|
-
// Define allowed tools - only read-only operations
|
|
41
|
-
const allowedTools = ['web_fetch', 'read_file', 'glob', 'grep'];
|
|
42
|
-
const agent = query({
|
|
43
|
-
prompt: detectPluginsPrompt,
|
|
44
|
-
options: {
|
|
45
|
-
model: 'claude-haiku-4-20250514',
|
|
46
|
-
includePartialMessages: true,
|
|
47
|
-
allowedTools,
|
|
48
|
-
permissionMode: 'bypassPermissions',
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
let responseContent = '';
|
|
52
|
-
try {
|
|
53
|
-
// Collect all messages from the agent with live updates
|
|
54
|
-
for await (const sdkMessage of agent) {
|
|
55
|
-
if (sdkMessage.type === 'assistant' && sdkMessage.message.content) {
|
|
56
|
-
for (const block of sdkMessage.message.content) {
|
|
57
|
-
if (block.type === 'text') {
|
|
58
|
-
// Send text updates
|
|
59
|
-
callbacks.onUpdate({ type: 'text', content: block.text });
|
|
60
|
-
responseContent += block.text;
|
|
61
|
-
}
|
|
62
|
-
else if (block.type === 'tool_use') {
|
|
63
|
-
// Send tool usage updates
|
|
64
|
-
callbacks.onUpdate({
|
|
65
|
-
type: 'tool',
|
|
66
|
-
content: `Using ${block.name}`,
|
|
67
|
-
toolName: block.name,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// Extract plugin recommendations from agent response
|
|
74
|
-
const plugins = parsePluginRecommendations(responseContent);
|
|
75
|
-
const finalPlugins = plugins.length > 0 ? plugins : ['bushido'];
|
|
76
|
-
callbacks.onComplete(finalPlugins, responseContent);
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
callbacks.onError(error);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Parse plugin recommendations from agent response
|
|
84
|
-
*/
|
|
85
|
-
function parsePluginRecommendations(content) {
|
|
86
|
-
try {
|
|
87
|
-
// Try to find JSON array in the response
|
|
88
|
-
const jsonMatch = content.match(/\[[\s\S]*?\]/);
|
|
89
|
-
if (jsonMatch) {
|
|
90
|
-
const plugins = JSON.parse(jsonMatch[0]);
|
|
91
|
-
if (Array.isArray(plugins)) {
|
|
92
|
-
plugins.push('bushido');
|
|
93
|
-
return plugins.filter((p) => typeof p === 'string');
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// Fallback: look for plugin names mentioned
|
|
97
|
-
const pluginPattern = /(buki-[\w-]+|do-[\w-]+|sensei-[\w-]+|bushido)/g;
|
|
98
|
-
const matches = content.match(pluginPattern);
|
|
99
|
-
if (matches) {
|
|
100
|
-
return [...new Set(matches)];
|
|
101
|
-
}
|
|
102
|
-
return [];
|
|
103
|
-
}
|
|
104
|
-
catch (_error) {
|
|
105
|
-
return [];
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Get currently installed Han plugins
|
|
110
|
-
*/
|
|
111
|
-
function getInstalledPlugins(scope = 'project') {
|
|
112
|
-
const settings = readOrCreateSettings(scope);
|
|
113
|
-
const enabledPlugins = settings.enabledPlugins || {};
|
|
114
|
-
return Object.keys(enabledPlugins)
|
|
115
|
-
.filter((key) => key.endsWith('@han') && enabledPlugins[key])
|
|
116
|
-
.map((key) => key.replace('@han', ''));
|
|
117
|
-
}
|
|
3
|
+
import { HAN_MARKETPLACE_REPO, ensureClaudeDirectory, readOrCreateSettings, writeSettings, getInstalledPlugins, detectPluginsWithAgent, } from './shared.js';
|
|
118
4
|
/**
|
|
119
5
|
* Install plugins to Claude settings and return list of added plugins
|
|
120
6
|
*/
|
package/dist/lib/install.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../lib/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../lib/install.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/main.js
CHANGED
|
@@ -44,13 +44,16 @@ program
|
|
|
44
44
|
program
|
|
45
45
|
.command('align')
|
|
46
46
|
.description('Align plugins with current codebase state in Claude Code settings')
|
|
47
|
-
.option('--scope <scope>', 'Installation scope: "project" (.claude/settings.json)
|
|
47
|
+
.option('--scope <scope>', 'Installation scope: "project" (.claude/settings.json), "local" (.claude/settings.local.json), or auto-detect if not specified')
|
|
48
48
|
.action(async (options) => {
|
|
49
49
|
try {
|
|
50
|
-
|
|
51
|
-
if (scope
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
let scope;
|
|
51
|
+
if (options.scope) {
|
|
52
|
+
if (options.scope !== 'project' && options.scope !== 'local') {
|
|
53
|
+
console.error('Error: --scope must be either "project" or "local"');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
scope = options.scope;
|
|
54
57
|
}
|
|
55
58
|
const { align } = await import('./align.js');
|
|
56
59
|
await align(scope);
|
package/dist/lib/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../lib/main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CACnE,CAAC;AAEF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,6DAA6D,CAAC;KAC1E,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,kBAAkB;AAClB,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,6DAA6D,CAAC;KAC1E,MAAM,CACL,iBAAiB,EACjB,gGAAgG,EAChG,SAAS,CACV;KACA,MAAM,CAAC,KAAK,EAAE,OAA2B,EAAE,EAAE;IAC5C,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC;QACzC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACjD,MAAM,OAAO,CAAC,KAA4B,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CACX,4BAA4B,EAC5B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC/C,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,oBAAoB;AACpB,OAAO;KACJ,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACrD,SAAS,EAAE,CAAC;IACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEL,gBAAgB;AAChB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,mEAAmE,CAAC;KAChF,MAAM,CACL,iBAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../lib/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export declare const HAN_MARKETPLACE_REPO = "thebushidocollective/han";
|
|
2
|
+
export type MarketplaceSource = {
|
|
3
|
+
source: 'directory';
|
|
4
|
+
path: string;
|
|
5
|
+
} | {
|
|
6
|
+
source: 'git';
|
|
7
|
+
url: string;
|
|
8
|
+
} | {
|
|
9
|
+
source: 'github';
|
|
10
|
+
repo: string;
|
|
11
|
+
};
|
|
12
|
+
export type Marketplace = {
|
|
13
|
+
source: MarketplaceSource;
|
|
14
|
+
};
|
|
15
|
+
export type Marketplaces = Record<string, Marketplace>;
|
|
16
|
+
export type Plugins = Record<string, boolean>;
|
|
17
|
+
export interface ClaudeSettings {
|
|
18
|
+
extraKnownMarketplaces?: Marketplaces;
|
|
19
|
+
enabledPlugins?: Plugins;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
export interface AgentUpdate {
|
|
23
|
+
type: 'text' | 'tool';
|
|
24
|
+
content: string;
|
|
25
|
+
toolName?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface DetectPluginsCallbacks {
|
|
28
|
+
onUpdate: (update: AgentUpdate) => void;
|
|
29
|
+
onComplete: (plugins: string[], fullText: string) => void;
|
|
30
|
+
onError: (error: Error) => void;
|
|
31
|
+
}
|
|
32
|
+
export declare function getClaudeSettingsPath(scope?: 'project' | 'local'): string;
|
|
33
|
+
export declare function ensureClaudeDirectory(): void;
|
|
34
|
+
export declare function readOrCreateSettings(scope?: 'project' | 'local'): ClaudeSettings;
|
|
35
|
+
export declare function writeSettings(settings: ClaudeSettings, scope?: 'project' | 'local'): void;
|
|
36
|
+
/**
|
|
37
|
+
* Detect which scope(s) have Han marketplace configured
|
|
38
|
+
* Returns array of scopes where Han is installed
|
|
39
|
+
*/
|
|
40
|
+
export declare function detectHanScopes(): Array<'project' | 'local'>;
|
|
41
|
+
/**
|
|
42
|
+
* Get currently installed Han plugins
|
|
43
|
+
*/
|
|
44
|
+
export declare function getInstalledPlugins(scope?: 'project' | 'local'): string[];
|
|
45
|
+
/**
|
|
46
|
+
* Use Claude Agent SDK to intelligently analyze codebase and recommend plugins
|
|
47
|
+
*/
|
|
48
|
+
export declare function detectPluginsWithAgent(callbacks: DetectPluginsCallbacks): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Parse plugin recommendations from agent response
|
|
51
|
+
*/
|
|
52
|
+
export declare function parsePluginRecommendations(content: string): string[];
|
|
53
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../lib/shared.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAE/D,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AACvC,MAAM,MAAM,WAAW,GAAG;IAAE,MAAM,EAAE,iBAAiB,CAAA;CAAE,CAAC;AACxD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACvD,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,sBAAsB,CAAC,EAAE,YAAY,CAAC;IACtC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACjC;AAED,wBAAgB,qBAAqB,CAAC,KAAK,GAAE,SAAS,GAAG,OAAmB,GAAG,MAAM,CAGpF;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAM5C;AAED,wBAAgB,oBAAoB,CAAC,KAAK,GAAE,SAAS,GAAG,OAAmB,GAAG,cAAc,CAa3F;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,GAAE,SAAS,GAAG,OAAmB,GAAG,IAAI,CAGpG;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,CAgB5D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,SAAS,GAAG,OAAmB,GAAG,MAAM,EAAE,CAOpF;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,sBAAsB,GAChC,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBpE"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
4
|
+
import { detectPluginsPrompt } from './detect-plugins-prompt.js';
|
|
5
|
+
export const HAN_MARKETPLACE_REPO = 'thebushidocollective/han';
|
|
6
|
+
export function getClaudeSettingsPath(scope = 'project') {
|
|
7
|
+
const filename = scope === 'local' ? 'settings.local.json' : 'settings.json';
|
|
8
|
+
return join(process.cwd(), '.claude', filename);
|
|
9
|
+
}
|
|
10
|
+
export function ensureClaudeDirectory() {
|
|
11
|
+
const settingsPath = getClaudeSettingsPath();
|
|
12
|
+
const claudeDir = join(settingsPath, '..');
|
|
13
|
+
if (!existsSync(claudeDir)) {
|
|
14
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function readOrCreateSettings(scope = 'project') {
|
|
18
|
+
const settingsPath = getClaudeSettingsPath(scope);
|
|
19
|
+
if (existsSync(settingsPath)) {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
22
|
+
}
|
|
23
|
+
catch (_error) {
|
|
24
|
+
console.error(`Error reading ${scope === 'local' ? 'settings.local.json' : 'settings.json'}, creating new one`);
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
export function writeSettings(settings, scope = 'project') {
|
|
31
|
+
const settingsPath = getClaudeSettingsPath(scope);
|
|
32
|
+
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Detect which scope(s) have Han marketplace configured
|
|
36
|
+
* Returns array of scopes where Han is installed
|
|
37
|
+
*/
|
|
38
|
+
export function detectHanScopes() {
|
|
39
|
+
const scopes = [];
|
|
40
|
+
// Check project scope
|
|
41
|
+
const projectSettings = readOrCreateSettings('project');
|
|
42
|
+
if (projectSettings.extraKnownMarketplaces?.han) {
|
|
43
|
+
scopes.push('project');
|
|
44
|
+
}
|
|
45
|
+
// Check local scope
|
|
46
|
+
const localSettings = readOrCreateSettings('local');
|
|
47
|
+
if (localSettings.extraKnownMarketplaces?.han) {
|
|
48
|
+
scopes.push('local');
|
|
49
|
+
}
|
|
50
|
+
return scopes;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get currently installed Han plugins
|
|
54
|
+
*/
|
|
55
|
+
export function getInstalledPlugins(scope = 'project') {
|
|
56
|
+
const settings = readOrCreateSettings(scope);
|
|
57
|
+
const enabledPlugins = settings.enabledPlugins || {};
|
|
58
|
+
return Object.keys(enabledPlugins)
|
|
59
|
+
.filter((key) => key.endsWith('@han') && enabledPlugins[key])
|
|
60
|
+
.map((key) => key.replace('@han', ''));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Use Claude Agent SDK to intelligently analyze codebase and recommend plugins
|
|
64
|
+
*/
|
|
65
|
+
export async function detectPluginsWithAgent(callbacks) {
|
|
66
|
+
// Define allowed tools - only read-only operations
|
|
67
|
+
const allowedTools = ['web_fetch', 'read_file', 'glob', 'grep'];
|
|
68
|
+
const agent = query({
|
|
69
|
+
prompt: detectPluginsPrompt,
|
|
70
|
+
options: {
|
|
71
|
+
model: 'haiku',
|
|
72
|
+
includePartialMessages: true,
|
|
73
|
+
allowedTools,
|
|
74
|
+
permissionMode: 'bypassPermissions',
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
let responseContent = '';
|
|
78
|
+
try {
|
|
79
|
+
// Collect all messages from the agent with live updates
|
|
80
|
+
for await (const sdkMessage of agent) {
|
|
81
|
+
if (sdkMessage.type === 'assistant' && sdkMessage.message.content) {
|
|
82
|
+
for (const block of sdkMessage.message.content) {
|
|
83
|
+
if (block.type === 'text') {
|
|
84
|
+
// Send text updates
|
|
85
|
+
callbacks.onUpdate({ type: 'text', content: block.text });
|
|
86
|
+
responseContent += block.text;
|
|
87
|
+
}
|
|
88
|
+
else if (block.type === 'tool_use') {
|
|
89
|
+
// Send tool usage updates
|
|
90
|
+
callbacks.onUpdate({
|
|
91
|
+
type: 'tool',
|
|
92
|
+
content: `Using ${block.name}`,
|
|
93
|
+
toolName: block.name,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Extract plugin recommendations from agent response
|
|
100
|
+
const plugins = parsePluginRecommendations(responseContent);
|
|
101
|
+
const finalPlugins = plugins.length > 0 ? plugins : ['bushido'];
|
|
102
|
+
callbacks.onComplete(finalPlugins, responseContent);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
callbacks.onError(error);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Parse plugin recommendations from agent response
|
|
110
|
+
*/
|
|
111
|
+
export function parsePluginRecommendations(content) {
|
|
112
|
+
try {
|
|
113
|
+
// Try to find JSON array in the response
|
|
114
|
+
const jsonMatch = content.match(/\[[\s\S]*?\]/);
|
|
115
|
+
if (jsonMatch) {
|
|
116
|
+
const plugins = JSON.parse(jsonMatch[0]);
|
|
117
|
+
if (Array.isArray(plugins)) {
|
|
118
|
+
plugins.push('bushido');
|
|
119
|
+
return plugins.filter((p) => typeof p === 'string');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Fallback: look for plugin names mentioned
|
|
123
|
+
const pluginPattern = /(buki-[\w-]+|do-[\w-]+|sensei-[\w-]+|bushido)/g;
|
|
124
|
+
const matches = content.match(pluginPattern);
|
|
125
|
+
if (matches) {
|
|
126
|
+
return [...new Set(matches)];
|
|
127
|
+
}
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
catch (_error) {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../lib/shared.ts"],"names":[],"mappings":"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"}
|