project-iris 0.2.0 → 0.2.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/lib/installer.js +160 -21
- package/package.json +2 -1
- package/templates/CLAUDE.md +88 -0
package/lib/installer.js
CHANGED
|
@@ -71,6 +71,99 @@ async function detectTools() {
|
|
|
71
71
|
// VS Code-based tools that can use the iris Dashboard extension
|
|
72
72
|
const VSCODE_TOOLS = ['claude', 'cursor', 'copilot', 'windsurf', 'cline', 'roo', 'antigravity'];
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Find VS Code CLI executable
|
|
76
|
+
* @returns {string|null} Path to VS Code CLI or null if not found
|
|
77
|
+
*/
|
|
78
|
+
function findVSCodeCLI() {
|
|
79
|
+
const platform = process.platform;
|
|
80
|
+
|
|
81
|
+
// Possible CLI paths by platform
|
|
82
|
+
const paths = [];
|
|
83
|
+
|
|
84
|
+
if (platform === 'darwin') {
|
|
85
|
+
// macOS - check common application locations
|
|
86
|
+
paths.push(
|
|
87
|
+
'/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code',
|
|
88
|
+
'/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code',
|
|
89
|
+
`${process.env.HOME}/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code`
|
|
90
|
+
);
|
|
91
|
+
} else if (platform === 'win32') {
|
|
92
|
+
// Windows
|
|
93
|
+
const localAppData = process.env.LOCALAPPDATA || '';
|
|
94
|
+
const programFiles = process.env['ProgramFiles'] || 'C:\\Program Files';
|
|
95
|
+
paths.push(
|
|
96
|
+
`${localAppData}\\Programs\\Microsoft VS Code\\bin\\code.cmd`,
|
|
97
|
+
`${programFiles}\\Microsoft VS Code\\bin\\code.cmd`
|
|
98
|
+
);
|
|
99
|
+
} else {
|
|
100
|
+
// Linux
|
|
101
|
+
paths.push(
|
|
102
|
+
'/usr/bin/code',
|
|
103
|
+
'/usr/local/bin/code',
|
|
104
|
+
'/snap/bin/code'
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Check each path
|
|
109
|
+
for (const p of paths) {
|
|
110
|
+
try {
|
|
111
|
+
if (fs.existsSync(p)) {
|
|
112
|
+
return p;
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
// Ignore errors
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Fall back to trying 'code' from PATH
|
|
120
|
+
try {
|
|
121
|
+
execSync('which code || where code', { stdio: 'pipe' });
|
|
122
|
+
return 'code';
|
|
123
|
+
} catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Find Cursor CLI executable
|
|
130
|
+
* @returns {string|null} Path to Cursor CLI or null if not found
|
|
131
|
+
*/
|
|
132
|
+
function findCursorCLI() {
|
|
133
|
+
const platform = process.platform;
|
|
134
|
+
|
|
135
|
+
const paths = [];
|
|
136
|
+
|
|
137
|
+
if (platform === 'darwin') {
|
|
138
|
+
paths.push(
|
|
139
|
+
'/Applications/Cursor.app/Contents/Resources/app/bin/cursor',
|
|
140
|
+
`${process.env.HOME}/Applications/Cursor.app/Contents/Resources/app/bin/cursor`
|
|
141
|
+
);
|
|
142
|
+
} else if (platform === 'win32') {
|
|
143
|
+
const localAppData = process.env.LOCALAPPDATA || '';
|
|
144
|
+
paths.push(
|
|
145
|
+
`${localAppData}\\Programs\\Cursor\\resources\\app\\bin\\cursor.cmd`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (const p of paths) {
|
|
150
|
+
try {
|
|
151
|
+
if (fs.existsSync(p)) {
|
|
152
|
+
return p;
|
|
153
|
+
}
|
|
154
|
+
} catch {
|
|
155
|
+
// Ignore errors
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
execSync('which cursor || where cursor', { stdio: 'pipe' });
|
|
161
|
+
return 'cursor';
|
|
162
|
+
} catch {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
74
167
|
/**
|
|
75
168
|
* Install VS Code extension if any VS Code-based tool is selected
|
|
76
169
|
* @param {string[]} selectedToolKeys - Selected tool keys
|
|
@@ -93,46 +186,89 @@ async function installVSCodeExtension(selectedToolKeys) {
|
|
|
93
186
|
|
|
94
187
|
console.log(theme.dim(' Installing iris Dashboard VS Code extension...'));
|
|
95
188
|
|
|
96
|
-
|
|
97
|
-
// Try 'code' command first (VS Code), then 'cursor' for Cursor
|
|
98
|
-
let installed = false;
|
|
189
|
+
let installed = false;
|
|
99
190
|
|
|
100
|
-
|
|
191
|
+
// Try VS Code
|
|
192
|
+
const vscodeCLI = findVSCodeCLI();
|
|
193
|
+
if (vscodeCLI) {
|
|
101
194
|
try {
|
|
102
|
-
execSync(`
|
|
195
|
+
execSync(`"${vscodeCLI}" --install-extension "${extensionPath}" --force`, {
|
|
103
196
|
stdio: 'pipe',
|
|
104
|
-
timeout:
|
|
197
|
+
timeout: 60000,
|
|
198
|
+
shell: true
|
|
105
199
|
});
|
|
106
200
|
installed = true;
|
|
107
201
|
CLIUtils.displayStatus('', 'Installed iris Dashboard extension for VS Code', 'success');
|
|
108
|
-
} catch {
|
|
109
|
-
|
|
202
|
+
} catch (err) {
|
|
203
|
+
console.log(theme.dim(` VS Code install failed: ${err.message}`));
|
|
110
204
|
}
|
|
205
|
+
}
|
|
111
206
|
|
|
112
|
-
|
|
113
|
-
|
|
207
|
+
// Try Cursor if selected
|
|
208
|
+
if (selectedToolKeys.includes('cursor')) {
|
|
209
|
+
const cursorCLI = findCursorCLI();
|
|
210
|
+
if (cursorCLI) {
|
|
114
211
|
try {
|
|
115
|
-
execSync(`
|
|
212
|
+
execSync(`"${cursorCLI}" --install-extension "${extensionPath}" --force`, {
|
|
116
213
|
stdio: 'pipe',
|
|
117
|
-
timeout:
|
|
214
|
+
timeout: 60000,
|
|
215
|
+
shell: true
|
|
118
216
|
});
|
|
119
217
|
installed = true;
|
|
120
218
|
CLIUtils.displayStatus('', 'Installed iris Dashboard extension for Cursor', 'success');
|
|
121
|
-
} catch {
|
|
122
|
-
|
|
219
|
+
} catch (err) {
|
|
220
|
+
console.log(theme.dim(` Cursor install failed: ${err.message}`));
|
|
123
221
|
}
|
|
124
222
|
}
|
|
223
|
+
}
|
|
125
224
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
225
|
+
if (!installed) {
|
|
226
|
+
console.log(theme.dim(' Could not auto-install extension. Install manually:'));
|
|
227
|
+
console.log(theme.dim(` code --install-extension "${extensionPath}"`));
|
|
228
|
+
}
|
|
130
229
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
230
|
+
return installed;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Install CLAUDE.md to .claude/ folder
|
|
235
|
+
* This provides Claude with project-agnostic quality guidelines
|
|
236
|
+
* @returns {boolean} Whether file was installed
|
|
237
|
+
*/
|
|
238
|
+
async function installClaudeMd() {
|
|
239
|
+
const sourcePath = path.join(__dirname, '..', 'templates', 'CLAUDE.md');
|
|
240
|
+
const targetDir = '.claude';
|
|
241
|
+
const targetPath = path.join(targetDir, 'CLAUDE.md');
|
|
242
|
+
|
|
243
|
+
// Check if source exists
|
|
244
|
+
if (!await fs.pathExists(sourcePath)) {
|
|
245
|
+
console.log(theme.dim(' CLAUDE.md template not found, skipping...'));
|
|
134
246
|
return false;
|
|
135
247
|
}
|
|
248
|
+
|
|
249
|
+
// Ensure .claude directory exists
|
|
250
|
+
await fs.ensureDir(targetDir);
|
|
251
|
+
|
|
252
|
+
// Check if CLAUDE.md already exists
|
|
253
|
+
if (await fs.pathExists(targetPath)) {
|
|
254
|
+
// Read existing content to check if it's ours
|
|
255
|
+
const existing = await fs.readFile(targetPath, 'utf8');
|
|
256
|
+
if (existing.includes('installed by iris') || existing.includes('project-iris')) {
|
|
257
|
+
// Our file, safe to overwrite
|
|
258
|
+
await fs.copy(sourcePath, targetPath, { overwrite: true });
|
|
259
|
+
CLIUtils.displayStatus('', 'Updated CLAUDE.md', 'success');
|
|
260
|
+
return true;
|
|
261
|
+
} else {
|
|
262
|
+
// User's own CLAUDE.md, don't overwrite
|
|
263
|
+
console.log(theme.dim(' Existing CLAUDE.md found, skipping (won\'t overwrite user file)'));
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Install fresh
|
|
269
|
+
await fs.copy(sourcePath, targetPath);
|
|
270
|
+
CLIUtils.displayStatus('', 'Installed CLAUDE.md with quality guidelines', 'success');
|
|
271
|
+
return true;
|
|
136
272
|
}
|
|
137
273
|
|
|
138
274
|
async function install() {
|
|
@@ -221,6 +357,9 @@ async function install() {
|
|
|
221
357
|
try {
|
|
222
358
|
const filesCreated = await installFlow(selectedFlow, selectedToolKeys);
|
|
223
359
|
|
|
360
|
+
// Install CLAUDE.md with quality guidelines
|
|
361
|
+
await installClaudeMd();
|
|
362
|
+
|
|
224
363
|
// Install VS Code extension if applicable
|
|
225
364
|
await installVSCodeExtension(selectedToolKeys);
|
|
226
365
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "project-iris",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Multi-agent orchestration system for AI-native software development. Delivers AI-DLC, Agile, and custom SDLC flows as markdown-based agent systems.",
|
|
5
5
|
"main": "lib/installer.js",
|
|
6
6
|
"bin": {
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"flows/",
|
|
39
39
|
"lib/",
|
|
40
40
|
"scripts/",
|
|
41
|
+
"templates/",
|
|
41
42
|
"README.md"
|
|
42
43
|
],
|
|
43
44
|
"dependencies": {
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Claude Instructions
|
|
2
|
+
|
|
3
|
+
## Core Principles
|
|
4
|
+
|
|
5
|
+
1. **Read before writing** - Understand existing code before modifying
|
|
6
|
+
2. **Minimal changes** - Solve the problem, nothing more
|
|
7
|
+
3. **Follow existing patterns** - Match the codebase style exactly
|
|
8
|
+
4. **Ask when unclear** - Don't guess at requirements
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Before Writing Code
|
|
13
|
+
|
|
14
|
+
- Read the files you'll modify - understand the patterns used
|
|
15
|
+
- Search for existing utilities before creating new ones
|
|
16
|
+
- Check if similar problems are solved elsewhere in the codebase
|
|
17
|
+
- Understand the "why" behind existing code, not just the "what"
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Code Quality
|
|
22
|
+
|
|
23
|
+
### Keep It Simple
|
|
24
|
+
|
|
25
|
+
- Solve the current problem, not hypothetical future ones
|
|
26
|
+
- No abstractions for single-use cases
|
|
27
|
+
- Three similar lines > premature helper function
|
|
28
|
+
- Delete unused code completely (no `_unused` prefixes)
|
|
29
|
+
|
|
30
|
+
### Only Add What's Needed
|
|
31
|
+
|
|
32
|
+
- No feature flags for simple changes
|
|
33
|
+
- No backwards-compatibility shims when you can just change code
|
|
34
|
+
- No defensive programming against impossible scenarios
|
|
35
|
+
- No gold-plating or "while I'm here" improvements
|
|
36
|
+
|
|
37
|
+
### Error Handling
|
|
38
|
+
|
|
39
|
+
- Validate at system boundaries only (user input, APIs, file I/O)
|
|
40
|
+
- Trust internal code - don't defensively check everything
|
|
41
|
+
- No empty catch blocks
|
|
42
|
+
- Let errors propagate when callers should handle them
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## What NOT To Do
|
|
47
|
+
|
|
48
|
+
- Don't add comments explaining obvious code
|
|
49
|
+
- Don't add types/docstrings to code you didn't change
|
|
50
|
+
- Don't refactor surrounding code when fixing a bug
|
|
51
|
+
- Don't create utils/helpers for one-time operations
|
|
52
|
+
- Don't add tests for trivial code (getters, pass-through)
|
|
53
|
+
- Don't "improve" working code that isn't part of the task
|
|
54
|
+
- Don't guess at missing requirements - ask first
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Security Essentials
|
|
59
|
+
|
|
60
|
+
- Never hardcode secrets, keys, or credentials
|
|
61
|
+
- Validate and sanitize all user input
|
|
62
|
+
- Use parameterized queries (no string concatenation for SQL)
|
|
63
|
+
- Escape output in templates to prevent XSS
|
|
64
|
+
- Check file paths to prevent directory traversal
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Testing
|
|
69
|
+
|
|
70
|
+
- Test behavior, not implementation
|
|
71
|
+
- One assertion per test when possible
|
|
72
|
+
- Name tests by what they verify: `test_returns_empty_list_when_no_items`
|
|
73
|
+
- Don't mock what you don't own
|
|
74
|
+
- Skip tests for trivial code
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Communication
|
|
79
|
+
|
|
80
|
+
- Be direct and concise
|
|
81
|
+
- State what you're doing before doing it
|
|
82
|
+
- If blocked, explain why and ask for guidance
|
|
83
|
+
- Confirm destructive operations before executing
|
|
84
|
+
- Summarize changes after completing a task
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
<!-- installed by iris (project-iris) - safe to update with: npx project-iris install -->
|