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 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
- try {
97
- // Try 'code' command first (VS Code), then 'cursor' for Cursor
98
- let installed = false;
189
+ let installed = false;
99
190
 
100
- // Try VS Code
191
+ // Try VS Code
192
+ const vscodeCLI = findVSCodeCLI();
193
+ if (vscodeCLI) {
101
194
  try {
102
- execSync(`code --install-extension "${extensionPath}" --force`, {
195
+ execSync(`"${vscodeCLI}" --install-extension "${extensionPath}" --force`, {
103
196
  stdio: 'pipe',
104
- timeout: 30000
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
- // VS Code not available or failed
202
+ } catch (err) {
203
+ console.log(theme.dim(` VS Code install failed: ${err.message}`));
110
204
  }
205
+ }
111
206
 
112
- // Try Cursor if selected
113
- if (selectedToolKeys.includes('cursor')) {
207
+ // Try Cursor if selected
208
+ if (selectedToolKeys.includes('cursor')) {
209
+ const cursorCLI = findCursorCLI();
210
+ if (cursorCLI) {
114
211
  try {
115
- execSync(`cursor --install-extension "${extensionPath}" --force`, {
212
+ execSync(`"${cursorCLI}" --install-extension "${extensionPath}" --force`, {
116
213
  stdio: 'pipe',
117
- timeout: 30000
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
- // Cursor not available or failed
219
+ } catch (err) {
220
+ console.log(theme.dim(` Cursor install failed: ${err.message}`));
123
221
  }
124
222
  }
223
+ }
125
224
 
126
- if (!installed) {
127
- console.log(theme.dim(' Could not auto-install extension. Install manually:'));
128
- console.log(theme.dim(` code --install-extension "${extensionPath}"`));
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
- return installed;
132
- } catch (error) {
133
- console.log(theme.dim(` Extension install skipped: ${error.message}`));
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.0",
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 -->