bmad-stella 1.0.0 → 1.0.1
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 +3 -2
- package/bmad-core/agents/dev.md +7 -5
- package/bmad-core/agents/planner.md +5 -5
- package/bmad-core/agents/qa.md +1 -1
- package/bmad-core/tasks/create-implementation-plan.md +4 -3
- package/docs/stella-user-guide.md +13 -3
- package/package.json +1 -1
- package/tools/installer/lib/claude-permissions-manager.js +380 -0
- package/tools/installer/lib/ide-setup.js +2465 -2461
- package/tools/installer/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,8 +52,9 @@ npx bmad-stella install
|
|
|
52
52
|
3. Enter Confluence URL for architecture docs
|
|
53
53
|
4. Select **Claude Code** as IDE
|
|
54
54
|
5. Skip web bundles installation (enter `n`)
|
|
55
|
-
6.
|
|
56
|
-
7.
|
|
55
|
+
6. Allow Claude Code Permissions Setup (enter `y`)
|
|
56
|
+
7. Configure Atlassian MCP Server (enter `y`)
|
|
57
|
+
8. Provide JIRA instance URL (e.g., `https://stellaint.atlassian.net`)
|
|
57
58
|
|
|
58
59
|
**📖 [Detailed Installation Guide](docs/stella-user-guide.md#bmad-stella-installation-process)**
|
|
59
60
|
|
package/bmad-core/agents/dev.md
CHANGED
|
@@ -58,12 +58,14 @@ core_principles:
|
|
|
58
58
|
|
|
59
59
|
# All commands require * prefix when used (e.g., *help)
|
|
60
60
|
commands:
|
|
61
|
-
- help: Show numbered list of the following commands to allow selection
|
|
61
|
+
- help: Show numbered list of the following commands to allow selection. Format each as "{number}. *{command-name} {parameters} - {description}"
|
|
62
62
|
- implement-task:
|
|
63
|
-
- order-of-execution: 'Read (first or next) task from implementation plan→Implement Task and its subtasks→
|
|
63
|
+
- order-of-execution: 'Read (first or next) task from implementation plan→Implement Task and its subtasks→Update the task checkbox with [x] in plan→Update plan file `File List` subsection in `Dev Agent Record` section to ensure it lists any new or modified or deleted source file→HALT and ask user: "Proceed to next task, build project, or stop?"→If next task: repeat order-of-execution→If build: run build command and report result then ask "Proceed to next task or stop?"→If stop: remain HALTED'
|
|
64
64
|
- plan-file-updates-ONLY:
|
|
65
65
|
- CRITICAL: ONLY UPDATE THE IMPLEMENTATION PLAN FILE WITH UPDATES TO SECTIONS INDICATED BELOW. DO NOT MODIFY ANY OTHER SECTIONS.
|
|
66
|
-
- CRITICAL:
|
|
66
|
+
- CRITICAL: Don't ask for user permission for plan file update.
|
|
67
|
+
- CRITICAL: MUST UPDATE `Agent Model Used` and `File List` SUBSECTION IN `Dev Agent Record` SECTION OF IMPLEMENTATION PLAN
|
|
68
|
+
- CRITICAL: You are ONLY authorized to edit these specific sections of implementation plan files - Tasks / Subtasks Checkboxes, `Dev Agent Record` section (Agent Model Used, Debug Log References, Completion Notes List, File List), Change Log, Status
|
|
67
69
|
- CRITICAL: DO NOT modify Ticket Information, Requirements, Acceptance Criteria, Technical Approach, Technical Context / Dev Notes, Files to Change, Dependencies and Risks, Feedback, or any other sections not listed above
|
|
68
70
|
- interaction-rules:
|
|
69
71
|
- Don't perform DB Migrations and manual tests automatically. Ask user to perform these and wait for confirmation before going to the next step
|
|
@@ -74,8 +76,8 @@ commands:
|
|
|
74
76
|
- ready-for-review: 'Code matches requirements + All validations pass + Follows standards + File List complete in Dev Agent Record'
|
|
75
77
|
- completion: "All Tasks and Subtasks marked [x] and have tests→Validations and full regression passes (DON'T BE LAZY, EXECUTE ALL TESTS and CONFIRM)→Ensure Dev Agent Record File List is Complete→run the task execute-checklist for the checklist task-dod-checklist→set plan status: 'Ready for Review'→HALT"
|
|
76
78
|
- explain: teach me what and why you did whatever you just did in detail so I can learn. Explain to me as if you were training a junior engineer.
|
|
77
|
-
- comment-plan {plan-file}:
|
|
78
|
-
- order-of-execution: Extract Jira ticket number/URL from plan file Ticket Information section→
|
|
79
|
+
- comment-plan {plan-file}:
|
|
80
|
+
- order-of-execution: 'Extract Jira ticket number/URL from plan file Ticket Information section→Attempt to fetch Jira ticket using atlassian MCP→If fetch fails, notify user: "Atlassian MCP not connected. Please reauthenticate."→If connected, check if Acceptance Criteria already exists in Jira ticket description→Format comment according to comment-structure rules using Jira markdown formatting→Display formatted comment to user and request permission to post→Post comment to Jira ticket→Display Jira ticket URL and confirm successful posting'
|
|
79
81
|
- comment-structure:
|
|
80
82
|
- Section 1 - Tasks Completed: Copy all tasks and subtasks from Tasks/Subtasks section exactly as written with their checkbox status ([x] or [ ])
|
|
81
83
|
- Section 2 - Technical Summary: Write a 5-10 sentence summary describing what was implemented based on Technical Approach section content
|
|
@@ -20,7 +20,7 @@ activation-instructions:
|
|
|
20
20
|
- STEP 1: Read THIS ENTIRE FILE - it contains your complete persona definition
|
|
21
21
|
- STEP 2: Adopt the persona defined in the 'agent' and 'persona' sections below
|
|
22
22
|
- STEP 3: Load and read `.bmad-core/core-config.yaml` (project configuration) before any greeting
|
|
23
|
-
- STEP 4:
|
|
23
|
+
- STEP 4: Before any greeting, fetch documentation from the `architectureFolderUrl` in `.bmad-core/core-config.yaml`. Delete and recreate the `architecture/` folder inside `bmad-docs/` if it exists. Use "Bash(rm -rf **/bmad-docs/architecture)" OR "Bash(rm -rf bmad-docs/architecture)" to delete architecture folder. Save content into files named coding-standards, tech-stack, git-workflow, and project-structure based on content meaning rather than page names, and save any additional pages as separate files if present. Number of files should be same as number of child pages in provided url. If attempt to fetch pages fail using atlassian MCP, notify user - "Atlassian MCP not connected. Please reauthenticate.", then retry STEP 4. Do NOT proceed to STEP 5 until architecture docs are successfully loaded.
|
|
24
24
|
- STEP 5: Greet user with your name/role and immediately run `*help` to display available commands
|
|
25
25
|
- DO NOT: Load any other agent files during activation
|
|
26
26
|
- ONLY load dependency files when user selects them for execution via command or request of a task
|
|
@@ -60,10 +60,10 @@ persona:
|
|
|
60
60
|
- Standards & Patterns Adherence - Ensure plans align with project conventions
|
|
61
61
|
# All commands require * prefix when used (e.g., *help)
|
|
62
62
|
commands:
|
|
63
|
-
- help: Show numbered list of the following commands to allow selection
|
|
64
|
-
- retrieve-ticket-information {ticket-number-or-url}:
|
|
65
|
-
- order-of-execution:
|
|
66
|
-
- attachment-rules:
|
|
63
|
+
- help: Show numbered list of the following commands to allow selection. Format each as "{number}. *{command-name} {parameters} - {description}"
|
|
64
|
+
- retrieve-ticket-information {ticket-number-or-url}:
|
|
65
|
+
- order-of-execution: 'Fetch ticket information (title, description, comments, attachments) using ticket number/URL with `atlassian` MCP→If fetch fails, notify user: "Atlassian MCP not connected. Please reauthenticate." and HALT until user confirms reconnection, then retry fetch→Check for Requirements or Acceptance Criteria in ticket description→If absent, check for attached images and request user to provide them via copy/paste (alt+v) or file path if downloaded→Prepare Acceptance Criteria text based on ticket description, comments, and provided attachments→Display ticket contents with prepared Acceptance Criteria and request user validation→Prompt user to proceed with draft-plan command. If no ticket identifier provided, ask for one'
|
|
66
|
+
- attachment-rules: If there exists any attachments in the ticket request user to provide them via copy/paste (alt+v) or file path if downloaded
|
|
67
67
|
- acceptance-criteria-rules: Prepare criteria only if Requirements AND Acceptance Criteria sections are both absent. Request attachments first if present. Format as testable, numbered list based on ticket description and attachments. Do not create any files - only compose text for display
|
|
68
68
|
- output-format: Display ticket title, description, comments, attachments list, and prepared Acceptance Criteria (if created) with clear validation prompt
|
|
69
69
|
- draft-plan {ticket-file-or-description}: Analyze JIRA ticket (feature/bug/migration) information with description having `Acceptance Criteria`/ `Requirements` and create detailed implementation plan with step-by-step tasks executing create-implementation-plan
|
package/bmad-core/agents/qa.md
CHANGED
|
@@ -62,7 +62,7 @@ task-file-permissions:
|
|
|
62
62
|
- Assessment documents include: test-design-*.md, trace-*.md files
|
|
63
63
|
# All commands require * prefix when used (e.g., *help)
|
|
64
64
|
commands:
|
|
65
|
-
- help: Show numbered list of the following commands to allow selection
|
|
65
|
+
- help: Show numbered list of the following commands to allow selection. Format each as "{number}. *{command-name} {parameters} - {description}"
|
|
66
66
|
- test-design {task-file}: Execute test-design task to create comprehensive test scenarios
|
|
67
67
|
- implement-test {task-file}: Execute implement-test task to write test code from test design scenarios
|
|
68
68
|
- trace {task-file}: Execute trace-requirements task to map requirements to tests using Given-When-Then
|
|
@@ -16,6 +16,7 @@ To transform JIRA tickets (features, bugs, migrations) into comprehensive, actio
|
|
|
16
16
|
- **Get search hints first:** Ask user for helpful hints to narrow the search (e.g., "Look in services folder", "Related to authentication", "Files with 'payment' in name", "Backend API files")
|
|
17
17
|
- **Check project structure docs:** ALWAYS read `bmad-docs/architecture/project-structure.md` (or `project-structure.md`) FIRST to understand file locations and naming conventions
|
|
18
18
|
- **Perform targeted search:** Use hints + structure knowledge to create focused Glob/Grep searches instead of broad codebase scans
|
|
19
|
+
- **Identify impacted files:** When modifying a function, component, or interface, search for its usages across codebase using targeted Glob/Grep before making changes. Update all impacted files accordingly.
|
|
19
20
|
|
|
20
21
|
## SEQUENTIAL Task Execution (Do not proceed until current Task is complete)
|
|
21
22
|
|
|
@@ -84,14 +85,14 @@ If critical information is missing, ask the user targeted questions:
|
|
|
84
85
|
|
|
85
86
|
**For Database Changes (All Ticket Types):**
|
|
86
87
|
|
|
87
|
-
- Does this work require any database table updates or creation?
|
|
88
|
-
- **If uncertain, ASK the user** - better to clarify than assume
|
|
88
|
+
- Analyze Does this work require any database table updates or creation?
|
|
89
|
+
- **If not mentioned in ticket and uncertain, ASK the user** - better to clarify than assume
|
|
89
90
|
- If YES:
|
|
90
91
|
- **Database migration tasks must be handled by the user** (add in tasks list but tell user to do this)
|
|
91
92
|
- If specific fields to add to a model or a new model structure are NOT specified in the ticket info/requirements:
|
|
92
93
|
- **Ask the user to specify the fields to be added or the model structure** (field names, types, constraints, relationships)
|
|
93
94
|
- **If uncertain about any database-related details, ALWAYS ask the user** - do not make assumptions or proceed silently
|
|
94
|
-
- Document the model/table changes needed in the Technical Approach
|
|
95
|
+
- Document the model/table changes needed in the Technical Approach section
|
|
95
96
|
|
|
96
97
|
**CRITICAL:** Only ask essential questions. Use your senior developer judgment to infer reasonable details when possible.
|
|
97
98
|
|
|
@@ -28,7 +28,7 @@ Before installing BMad-Stella, ensure you have:
|
|
|
28
28
|
Open your terminal and run:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
npx
|
|
31
|
+
npx bmad-stella install
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
#### Step 2: Provide Project Directory
|
|
@@ -87,7 +87,17 @@ When prompted about web bundles:
|
|
|
87
87
|
|
|
88
88
|
Enter: **n**
|
|
89
89
|
|
|
90
|
-
#### Step 7:
|
|
90
|
+
#### Step 7: Allow Claude Code Permissions Setup
|
|
91
|
+
|
|
92
|
+
When prompted about permission setup:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Add 32 missing BMAD permissions to existing settings.local.json? (Y/n)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Enter: **y**
|
|
99
|
+
|
|
100
|
+
#### Step 8: Configure Atlassian MCP Server
|
|
91
101
|
|
|
92
102
|
If Atlassian MCP is not already configured, you'll see:
|
|
93
103
|
|
|
@@ -110,7 +120,7 @@ Enter: `https://stellaint.atlassian.net` (or your organization's JIRA URL)
|
|
|
110
120
|
- MCP server configuration is created
|
|
111
121
|
- Authentication is required to connect with JIRA instance
|
|
112
122
|
|
|
113
|
-
#### Step
|
|
123
|
+
#### Step 9: Complete Installation
|
|
114
124
|
|
|
115
125
|
You should see:
|
|
116
126
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const chalk = require('chalk').default || require('chalk');
|
|
4
|
+
const inquirer = require('inquirer').default || require('inquirer');
|
|
5
|
+
const cjson = require('comment-json');
|
|
6
|
+
|
|
7
|
+
class ClaudePermissionsManager {
|
|
8
|
+
constructor() {
|
|
9
|
+
// Define BMAD required permissions for Claude Code
|
|
10
|
+
this.bmadPermissions = [
|
|
11
|
+
// Atlassian MCP tools
|
|
12
|
+
'mcp__atlassian__getConfluencePage',
|
|
13
|
+
'mcp__atlassian__getConfluencePageDescendants',
|
|
14
|
+
'mcp__atlassian__getJiraIssue',
|
|
15
|
+
'mcp__atlassian__searchJiraIssuesUsingJql',
|
|
16
|
+
'mcp__atlassian__fetch',
|
|
17
|
+
'mcp__atlassian__addCommentToJiraIssue',
|
|
18
|
+
|
|
19
|
+
'WebFetch(domain:stellaint.atlassian.net)',
|
|
20
|
+
|
|
21
|
+
// File operations for markdown files
|
|
22
|
+
'Write(bmad-docs/**)',
|
|
23
|
+
'Write(*bmad-docs*)',
|
|
24
|
+
'Edit(bmad-docs/**)',
|
|
25
|
+
'Edit(*bmad-docs*)',
|
|
26
|
+
|
|
27
|
+
// Bash commands for directory operations (Unix)
|
|
28
|
+
'Bash(mkdir -p bmad-docs/**)',
|
|
29
|
+
'Bash(mkdir -p **/bmad-docs/**)',
|
|
30
|
+
'Bash(mkdir bmad-docs/**)',
|
|
31
|
+
'Bash(mkdir **/bmad-docs/**)',
|
|
32
|
+
'Bash(rm -rf *bmad-docs*)',
|
|
33
|
+
'Bash(rm -rf */bmad-docs/architecture*)',
|
|
34
|
+
'Bash(rm *bmad-docs*)',
|
|
35
|
+
'Bash(rm */bmad-docs/architecture*)',
|
|
36
|
+
'Bash(rm bmad-docs/temporary/*.md)',
|
|
37
|
+
'Bash(rm **/bmad-docs/temporary/*.md)',
|
|
38
|
+
|
|
39
|
+
// Bash commands for directory operations (Windows)
|
|
40
|
+
'Bash(if exist *bmad-docs* rmdir /s /q *bmad-docs*)',
|
|
41
|
+
String.raw`Bash(if exist *bmad-docs\architecture* rmdir /s /q *bmad-docs\architecture*)`,
|
|
42
|
+
'Bash(mkdir *bmad-docs*)',
|
|
43
|
+
|
|
44
|
+
// Directory listing and existence checks (Unix)
|
|
45
|
+
'Bash(ls bmad-docs/**)',
|
|
46
|
+
'Bash(ls **/bmad-docs/**)',
|
|
47
|
+
'Bash(test -f bmad-docs/**)',
|
|
48
|
+
'Bash(test -f **/bmad-docs/**)',
|
|
49
|
+
'Bash(test -d bmad-docs/**)',
|
|
50
|
+
'Bash(test -d **/bmad-docs/**)',
|
|
51
|
+
'Bash([ -f bmad-docs/** ])',
|
|
52
|
+
'Bash([ -d bmad-docs/** ])',
|
|
53
|
+
|
|
54
|
+
// Directory listing (Windows)
|
|
55
|
+
'Bash(dir bmad-docs/**)',
|
|
56
|
+
'Bash(dir **/bmad-docs/**)',
|
|
57
|
+
'Bash(dir *bmad-docs*)',
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get the path to settings.local.json
|
|
63
|
+
* @param {string} installDir - Target installation directory
|
|
64
|
+
* @returns {string} Path to settings.local.json
|
|
65
|
+
*/
|
|
66
|
+
getSettingsPath(installDir) {
|
|
67
|
+
return path.join(installDir, '.claude', 'settings.local.json');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if settings.local.json exists
|
|
72
|
+
* @param {string} installDir - Target installation directory
|
|
73
|
+
* @returns {Promise<boolean>}
|
|
74
|
+
*/
|
|
75
|
+
async settingsExists(installDir) {
|
|
76
|
+
const settingsPath = this.getSettingsPath(installDir);
|
|
77
|
+
return fs.pathExists(settingsPath);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Read existing settings.local.json
|
|
82
|
+
* @param {string} installDir - Target installation directory
|
|
83
|
+
* @returns {Promise<object|null>} Parsed settings or null if not found
|
|
84
|
+
*/
|
|
85
|
+
async readSettings(installDir) {
|
|
86
|
+
const settingsPath = this.getSettingsPath(installDir);
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
if (!(await fs.pathExists(settingsPath))) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const content = await fs.readFile(settingsPath, 'utf8');
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
// Try parsing with comment-json to preserve comments
|
|
97
|
+
return cjson.parse(content);
|
|
98
|
+
} catch {
|
|
99
|
+
// Fallback to standard JSON
|
|
100
|
+
return JSON.parse(content);
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.warn(chalk.yellow(`Warning: Could not read settings.local.json: ${error.message}`));
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Write settings.local.json
|
|
110
|
+
* @param {string} installDir - Target installation directory
|
|
111
|
+
* @param {object} settings - Settings object to write
|
|
112
|
+
* @returns {Promise<boolean>}
|
|
113
|
+
*/
|
|
114
|
+
async writeSettings(installDir, settings) {
|
|
115
|
+
const claudeDir = path.join(installDir, '.claude');
|
|
116
|
+
const settingsPath = this.getSettingsPath(installDir);
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
// Ensure .claude directory exists
|
|
120
|
+
await fs.ensureDir(claudeDir);
|
|
121
|
+
|
|
122
|
+
// Write with pretty formatting
|
|
123
|
+
const output = cjson.stringify(settings, null, 2);
|
|
124
|
+
await fs.writeFile(settingsPath, output, 'utf8');
|
|
125
|
+
return true;
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error(chalk.red(`Failed to write settings.local.json: ${error.message}`));
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get list of missing BMAD permissions from current settings
|
|
134
|
+
* @param {object} settings - Current settings object
|
|
135
|
+
* @returns {string[]} Array of missing permission strings
|
|
136
|
+
*/
|
|
137
|
+
getMissingPermissions(settings) {
|
|
138
|
+
const existingPermissions = new Set(settings?.permissions?.allow || []);
|
|
139
|
+
return this.bmadPermissions.filter((perm) => !existingPermissions.has(perm));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Check and setup Claude Code permissions
|
|
144
|
+
* @param {string} installDir - Target installation directory
|
|
145
|
+
* @param {object} spinner - Ora spinner instance (optional)
|
|
146
|
+
* @returns {Promise<object>} Results object with status
|
|
147
|
+
*/
|
|
148
|
+
async checkAndSetupPermissions(installDir, spinner = null) {
|
|
149
|
+
const results = {
|
|
150
|
+
settingsExisted: false,
|
|
151
|
+
created: false,
|
|
152
|
+
updated: false,
|
|
153
|
+
skipped: false,
|
|
154
|
+
permissionsAdded: 0,
|
|
155
|
+
error: null,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
const settingsPath = this.getSettingsPath(installDir);
|
|
160
|
+
results.settingsExisted = await this.settingsExists(installDir);
|
|
161
|
+
|
|
162
|
+
if (spinner) spinner.stop();
|
|
163
|
+
|
|
164
|
+
// Always show permissions setup prompt
|
|
165
|
+
console.log(chalk.cyan('\n🔧 Claude Code Permissions Setup'));
|
|
166
|
+
console.log(
|
|
167
|
+
chalk.dim('BMAD agents require certain permissions to work without repeated prompts.'),
|
|
168
|
+
);
|
|
169
|
+
console.log(
|
|
170
|
+
chalk.dim(
|
|
171
|
+
'(Only for bmad-docs/ and Atlassian MCP - does NOT include source code changes)\n',
|
|
172
|
+
),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
if (results.settingsExisted) {
|
|
176
|
+
// Settings file exists - check for missing permissions
|
|
177
|
+
const settings = await this.readSettings(installDir);
|
|
178
|
+
|
|
179
|
+
if (!settings) {
|
|
180
|
+
results.error = 'Could not parse existing settings.local.json';
|
|
181
|
+
console.log(chalk.yellow(`⚠️ ${results.error}`));
|
|
182
|
+
if (spinner) spinner.start();
|
|
183
|
+
return results;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Ensure permissions.allow array exists
|
|
187
|
+
if (!settings.permissions) {
|
|
188
|
+
settings.permissions = {};
|
|
189
|
+
}
|
|
190
|
+
if (!settings.permissions.allow) {
|
|
191
|
+
settings.permissions.allow = [];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Find missing permissions
|
|
195
|
+
const missingPermissions = this.getMissingPermissions(settings);
|
|
196
|
+
|
|
197
|
+
if (missingPermissions.length > 0) {
|
|
198
|
+
// Ask user before adding permissions
|
|
199
|
+
const { updateSettings } = await inquirer.prompt([
|
|
200
|
+
{
|
|
201
|
+
type: 'confirm',
|
|
202
|
+
name: 'updateSettings',
|
|
203
|
+
message: `Add ${missingPermissions.length} missing BMAD permissions to existing settings.local.json?`,
|
|
204
|
+
default: true,
|
|
205
|
+
},
|
|
206
|
+
]);
|
|
207
|
+
|
|
208
|
+
if (!updateSettings) {
|
|
209
|
+
console.log(chalk.yellow('⚠️ Skipping Claude Code permissions update.'));
|
|
210
|
+
results.skipped = true;
|
|
211
|
+
if (spinner) spinner.start();
|
|
212
|
+
return results;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Add missing permissions
|
|
216
|
+
settings.permissions.allow.push(...missingPermissions);
|
|
217
|
+
|
|
218
|
+
const success = await this.writeSettings(installDir, settings);
|
|
219
|
+
|
|
220
|
+
if (success) {
|
|
221
|
+
results.updated = true;
|
|
222
|
+
results.permissionsAdded = missingPermissions.length;
|
|
223
|
+
console.log(chalk.green('✓ Updated .claude/settings.local.json with BMAD permissions'));
|
|
224
|
+
console.log(chalk.dim(` - Added ${missingPermissions.length} new permission rules`));
|
|
225
|
+
} else {
|
|
226
|
+
results.error = 'Failed to update settings file';
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
console.log(chalk.green('✓ BMAD permissions already present in settings.local.json'));
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
// Ask user if they want to create settings.local.json
|
|
233
|
+
const { createSettings } = await inquirer.prompt([
|
|
234
|
+
{
|
|
235
|
+
type: 'confirm',
|
|
236
|
+
name: 'createSettings',
|
|
237
|
+
message: 'Grant Claude Code with BMAD related permissions? (Recommended)',
|
|
238
|
+
default: true,
|
|
239
|
+
},
|
|
240
|
+
]);
|
|
241
|
+
|
|
242
|
+
if (!createSettings) {
|
|
243
|
+
console.log(chalk.yellow('⚠️ Skipping Claude Code permissions setup.'));
|
|
244
|
+
console.log(
|
|
245
|
+
chalk.dim(' You may be prompted for permissions when using BMAD agents.\n'),
|
|
246
|
+
);
|
|
247
|
+
results.skipped = true;
|
|
248
|
+
if (spinner) spinner.start();
|
|
249
|
+
return results;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Create new settings file
|
|
253
|
+
const settings = {
|
|
254
|
+
permissions: {
|
|
255
|
+
allow: [...this.bmadPermissions],
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const success = await this.writeSettings(installDir, settings);
|
|
260
|
+
|
|
261
|
+
if (success) {
|
|
262
|
+
results.created = true;
|
|
263
|
+
results.permissionsAdded = this.bmadPermissions.length;
|
|
264
|
+
console.log(chalk.green('✓ Created .claude/settings.local.json with BMAD permissions'));
|
|
265
|
+
console.log(chalk.dim(` - Added ${this.bmadPermissions.length} permission rules`));
|
|
266
|
+
} else {
|
|
267
|
+
results.error = 'Failed to create settings file';
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (spinner) spinner.start();
|
|
272
|
+
return results;
|
|
273
|
+
} catch (error) {
|
|
274
|
+
results.error = error.message;
|
|
275
|
+
console.log(chalk.yellow(`⚠️ Could not setup Claude Code permissions: ${error.message}`));
|
|
276
|
+
if (spinner) spinner.start();
|
|
277
|
+
return results;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Show summary of permissions setup
|
|
283
|
+
* @param {object} results - Results from checkAndSetupPermissions
|
|
284
|
+
*/
|
|
285
|
+
showSetupSummary(results) {
|
|
286
|
+
if (results.error) {
|
|
287
|
+
console.log(chalk.red(`\n✗ Claude Code permissions setup failed: ${results.error}`));
|
|
288
|
+
console.log(chalk.yellow('You may need to add BMAD permissions manually.'));
|
|
289
|
+
this.showManualInstructions();
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (results.skipped) {
|
|
294
|
+
console.log(chalk.yellow('\n⚠️ Claude Code permissions were not configured.'));
|
|
295
|
+
console.log(chalk.dim(' Run the installer again or add permissions manually.'));
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (results.created) {
|
|
300
|
+
console.log(chalk.green('\n✓ Claude Code permissions configured successfully!'));
|
|
301
|
+
console.log(chalk.dim(` ${results.permissionsAdded} permission rules added.`));
|
|
302
|
+
} else if (results.updated) {
|
|
303
|
+
console.log(chalk.green('\n✓ Claude Code permissions updated successfully!'));
|
|
304
|
+
console.log(chalk.dim(` ${results.permissionsAdded} new permission rules added.`));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Show manual setup instructions
|
|
310
|
+
*/
|
|
311
|
+
showManualInstructions() {
|
|
312
|
+
console.log(chalk.cyan('\n📋 Manual Setup Instructions:'));
|
|
313
|
+
console.log(chalk.dim('1. Create .claude/settings.local.json in your project root'));
|
|
314
|
+
console.log(chalk.dim('2. Add the following content:\n'));
|
|
315
|
+
|
|
316
|
+
const exampleSettings = {
|
|
317
|
+
permissions: {
|
|
318
|
+
allow: [...this.bmadPermissions.slice(0, 5), '... (see full list in docs)'],
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
console.log(chalk.dim(JSON.stringify(exampleSettings, null, 2)));
|
|
323
|
+
console.log(
|
|
324
|
+
chalk.dim('\nSee BMAD documentation for the complete list of required permissions.'),
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Add custom permissions to an existing or new settings file
|
|
330
|
+
* @param {string} installDir - Target installation directory
|
|
331
|
+
* @param {string[]} customPermissions - Array of custom permission strings
|
|
332
|
+
* @returns {Promise<boolean>}
|
|
333
|
+
*/
|
|
334
|
+
async addCustomPermissions(installDir, customPermissions) {
|
|
335
|
+
try {
|
|
336
|
+
let settings = await this.readSettings(installDir);
|
|
337
|
+
|
|
338
|
+
if (!settings) {
|
|
339
|
+
settings = { permissions: { allow: [] } };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (!settings.permissions) {
|
|
343
|
+
settings.permissions = {};
|
|
344
|
+
}
|
|
345
|
+
if (!settings.permissions.allow) {
|
|
346
|
+
settings.permissions.allow = [];
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const existingPermissions = new Set(settings.permissions.allow);
|
|
350
|
+
let addedCount = 0;
|
|
351
|
+
|
|
352
|
+
for (const permission of customPermissions) {
|
|
353
|
+
if (!existingPermissions.has(permission)) {
|
|
354
|
+
settings.permissions.allow.push(permission);
|
|
355
|
+
addedCount++;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (addedCount > 0) {
|
|
360
|
+
await this.writeSettings(installDir, settings);
|
|
361
|
+
console.log(chalk.green(`✓ Added ${addedCount} custom permissions`));
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return true;
|
|
365
|
+
} catch (error) {
|
|
366
|
+
console.error(chalk.red(`Failed to add custom permissions: ${error.message}`));
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Get all BMAD permissions
|
|
373
|
+
* @returns {string[]} Array of all BMAD permission strings
|
|
374
|
+
*/
|
|
375
|
+
getAllPermissions() {
|
|
376
|
+
return [...this.bmadPermissions];
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
module.exports = new ClaudePermissionsManager();
|