agents-scrum-master 1.0.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.
@@ -0,0 +1,51 @@
1
+ # Contributing to agent-scrum-master
2
+
3
+ Thank you for your interest in contributing! This is an open-source project and we welcome all contributions.
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ git clone https://github.com/ashishdogra/agent-scrum-master.git
9
+ cd agent-scrum-master
10
+ npm install
11
+ ```
12
+
13
+ ## Development
14
+
15
+ ```bash
16
+ # Test locally in watch mode
17
+ node bin/cli.js --verbose
18
+
19
+ # Test in a real project
20
+ cd /path/to/test-project
21
+ node /path/to/agent-scrum-master/bin/cli.js --verbose
22
+ ```
23
+
24
+ ## Publishing to npm
25
+
26
+ 1. Update version in `package.json`
27
+ 2. Create a git tag: `git tag v1.0.0`
28
+ 3. Push: `git push origin main && git push origin --tags`
29
+ 4. Publish: `npm publish`
30
+
31
+ ## Areas for Contribution
32
+
33
+ - Additional ticket system integrations (Linear, GitHub Projects, etc.)
34
+ - Enhanced error messages
35
+ - Test coverage
36
+ - Documentation improvements
37
+ - Feature suggestions (via issues)
38
+
39
+ ## Code Style
40
+
41
+ - ESM modules only
42
+ - No external dependencies (keep it lightweight)
43
+ - Node.js 18+ compatibility
44
+
45
+ ## Reporting Issues
46
+
47
+ Please open an issue with:
48
+ - Node version
49
+ - OS
50
+ - Steps to reproduce
51
+ - Expected vs actual behavior
package/DEPLOYMENT.md ADDED
@@ -0,0 +1,121 @@
1
+ # Deployment Guide: agent-scrum-master
2
+
3
+ ## Step 1: Create GitHub Repository
4
+
5
+ 1. Go to https://github.com/new
6
+ 2. Create public repo: `agent-scrum-master`
7
+ 3. Initialize with no README (we have one)
8
+
9
+ ## Step 2: Push to GitHub
10
+
11
+ ```bash
12
+ cd /path/to/agent-scrum-master
13
+ git init
14
+ git add .
15
+ git commit -m "chore: initial commit"
16
+ git remote add origin https://github.com/YOUR_USERNAME/agent-scrum-master.git
17
+ git branch -M main
18
+ git push -u origin main
19
+ ```
20
+
21
+ ## Step 3: Setup npm (one-time only)
22
+
23
+ 1. Create npm account: https://www.npmjs.com/signup
24
+ 2. Verify email
25
+ 3. Login locally:
26
+ ```bash
27
+ npm login
28
+ ```
29
+ - Username: your npm username
30
+ - Password: your npm password
31
+ - Email: your email
32
+
33
+ ## Step 4: Publish to npm
34
+
35
+ ```bash
36
+ # Ensure package.json has correct name (agent-scrum-master)
37
+ # Ensure version bumped: 1.0.0
38
+ npm publish
39
+
40
+ # Verify it's published
41
+ npm view agent-scrum-master
42
+ ```
43
+
44
+ ## Step 5: Test Installation
45
+
46
+ In a fresh project:
47
+
48
+ ```bash
49
+ cd /tmp/test-project
50
+ mkdir -p /tmp/test-project
51
+ cd /tmp/test-project
52
+ git init
53
+ npx agent-scrum-master
54
+ ```
55
+
56
+ Should see:
57
+ ```
58
+ āœ… agent-scrum-master initialized!
59
+ ```
60
+
61
+ ## Step 6: Add GitHub Release
62
+
63
+ ```bash
64
+ git tag v1.0.0
65
+ git push origin v1.0.0
66
+
67
+ # Then create release on GitHub:
68
+ # https://github.com/YOUR_USERNAME/agent-scrum-master/releases/new
69
+ ```
70
+
71
+ ## Future Updates
72
+
73
+ 1. Update version in `package.json`:
74
+ ```json
75
+ "version": "1.0.1"
76
+ ```
77
+
78
+ 2. Commit and tag:
79
+ ```bash
80
+ git add package.json
81
+ git commit -m "chore: bump to 1.0.1"
82
+ git tag v1.0.1
83
+ git push origin main && git push origin v1.0.1
84
+ ```
85
+
86
+ 3. Publish:
87
+ ```bash
88
+ npm publish
89
+ ```
90
+
91
+ ## Troubleshooting
92
+
93
+ ### Package name taken
94
+ - Choose alternative: `agent-tasks-setup`, `agent-workspace-init`, etc.
95
+ - Update in `package.json` and `.npmrc`
96
+
97
+ ### npm login issues
98
+ - Clear cache: `npm cache clean --force`
99
+ - Re-login: `npm logout && npm login`
100
+
101
+ ### Publish failed
102
+ - Check version is higher than previous: `npm view agent-scrum-master versions`
103
+ - Ensure `.npmrc` is configured or logged in
104
+
105
+ ## Verification Commands
106
+
107
+ ```bash
108
+ # Check if published
109
+ npm search agent-scrum-master
110
+
111
+ # Install globally
112
+ npm install -g agent-scrum-master
113
+ agent-scrum-master --help
114
+
115
+ # Install from npx
116
+ npx agent-scrum-master --help
117
+ ```
118
+
119
+ ---
120
+
121
+ That's it! Your npm package is live and ready for anyone to use.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Ashish Dogra
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/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # agent-scrum-master
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
+ [![npm](https://img.shields.io/npm/v/agent-scrum-master)](https://www.npmjs.com/package/agent-scrum-master)
5
+
6
+ **One command to auto-configure agent-tasks pipeline for any project.**
7
+
8
+ Bootstraps [agent-tasks](https://github.com/keshrath/agent-tasks) — a pipeline task manager for AI agents — with a single `npx` call. Sets up MCP integration, project structure, and gitignore automatically. Works with Claude Code, Cursor, Windsurf, and any MCP client.
9
+
10
+ ---
11
+
12
+ ## Features
13
+
14
+ - ✨ **One-command setup** — `npx agent-scrum-master`
15
+ - šŸ“ **Project-scoped** — isolated task database per project (not global)
16
+ - šŸ¤– **Agent-agnostic** — works with Claude Code, Cursor, Windsurf, any MCP client
17
+ - šŸ”— **Ticket system ready** — optional Jira integration flags
18
+ - 🧹 **Automatic cleanup** — handles .gitignore and directory structure
19
+ - šŸ“Š **Dashboard included** — real-time kanban at `localhost:3422`
20
+
21
+ ---
22
+
23
+ ## Quick Start
24
+
25
+ ### Option 1: npx (one-liner, no install)
26
+
27
+ ```bash
28
+ cd /path/to/your/project
29
+ npx agent-scrum-master
30
+ ```
31
+
32
+ ### Option 2: npm install (global)
33
+
34
+ ```bash
35
+ npm install -g agent-scrum-master
36
+ cd /path/to/your/project
37
+ agent-scrum-master
38
+ ```
39
+
40
+ ---
41
+
42
+ ## What It Does
43
+
44
+ Runs in your project root and:
45
+
46
+ 1. āœ“ Creates `.claude/settings.json` with MCP server config
47
+ 2. āœ“ Creates `.agent-tasks/` directory for local task database
48
+ 3. āœ“ Adds `.agent-tasks/` to `.gitignore`
49
+ 4. āœ“ Ready for Claude Code, Cursor, or any MCP client
50
+
51
+ **Result:** Open the project in your agent and the task pipeline is live.
52
+
53
+ ---
54
+
55
+ ## Commands
56
+
57
+ ```bash
58
+ # Initialize (default)
59
+ npx agent-scrum-master
60
+
61
+ # Open dashboard in browser
62
+ npx agent-scrum-master dashboard
63
+
64
+ # With Jira integration
65
+ npx agent-scrum-master --jira-url=https://jira.company.com --jira-project=GROWTH
66
+
67
+ # Check status
68
+ npx agent-scrum-master status
69
+
70
+ # Remove setup
71
+ npx agent-scrum-master reset
72
+
73
+ # Verbose output
74
+ npx agent-scrum-master --verbose
75
+
76
+ # Overwrite existing config
77
+ npx agent-scrum-master --force
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Usage in Your Agent
83
+
84
+ Once initialized, open the project in Claude Code or Cursor:
85
+
86
+ ### View dashboard
87
+ Open in browser with one command:
88
+ ```bash
89
+ npx agent-scrum-master dashboard
90
+ ```
91
+
92
+ Or navigate manually to `http://localhost:3422`
93
+
94
+ ### Create a task
95
+ ```
96
+ Use the MCP tool: task_create(title: "Build login flow", description: "...", project: "MyProject")
97
+ ```
98
+
99
+ ### Advance stages
100
+ ```
101
+ Use task_stage(id: "task-123", stage: "implement")
102
+ ```
103
+
104
+ See [agent-tasks API docs](https://github.com/keshrath/agent-tasks/blob/main/docs/API.md) for full tool reference.
105
+
106
+ ---
107
+
108
+ ## Project Structure
109
+
110
+ After running `agent-scrum-master`:
111
+
112
+ ```
113
+ your-project/
114
+ ā”œā”€ā”€ .claude/
115
+ │ └── settings.json # MCP config (auto-created)
116
+ ā”œā”€ā”€ .agent-tasks/ # Task database (git-ignored)
117
+ │ └── tasks.db
118
+ ā”œā”€ā”€ .gitignore # Updated with .agent-tasks/
119
+ └── ... (your code)
120
+ ```
121
+
122
+ `.claude/settings.json` is **committed to git** — other team members inherit the setup automatically.
123
+
124
+ ---
125
+
126
+ ## Jira Integration (Optional)
127
+
128
+ Add Jira sync to your project:
129
+
130
+ ```bash
131
+ npx agent-scrum-master \
132
+ --jira-url=https://jira.company.com \
133
+ --jira-project=GROWTH
134
+ ```
135
+
136
+ This sets environment variables in `.claude/settings.json`. Agent-tasks can then sync task completions to Jira.
137
+
138
+ ---
139
+
140
+ ## Multi-Project Setup
141
+
142
+ Each project gets its own isolated database:
143
+
144
+ ```
145
+ project-a/
146
+ └── .agent-tasks/tasks.db # Isolated to project-a
147
+
148
+ project-b/
149
+ └── .agent-tasks/tasks.db # Isolated to project-b
150
+ ```
151
+
152
+ No cross-project bleed — dashboards run on the same port but serve different DBs by project.
153
+
154
+ ---
155
+
156
+ ## Requirements
157
+
158
+ - Node.js >= 18
159
+ - Agent supporting MCP (Claude Code, Cursor, Windsurf, etc.)
160
+
161
+ ---
162
+
163
+ ## Troubleshooting
164
+
165
+ ### Dashboard doesn't start
166
+
167
+ ```bash
168
+ # Check if agent-tasks is installed
169
+ npx agent-tasks --help
170
+
171
+ # Manually start dashboard
172
+ cd your-project
173
+ npx agent-tasks
174
+ ```
175
+
176
+ ### Reset and reinitialize
177
+
178
+ ```bash
179
+ npx agent-scrum-master reset
180
+ npx agent-scrum-master --force
181
+ ```
182
+
183
+ ### Check status
184
+
185
+ ```bash
186
+ npx agent-scrum-master status
187
+ ```
188
+
189
+ ---
190
+
191
+ ## Development
192
+
193
+ ```bash
194
+ # Clone
195
+ git clone https://github.com/ashishdogra/agent-scrum-master.git
196
+ cd agent-scrum-master
197
+
198
+ # Test locally
199
+ node bin/cli.js --verbose
200
+
201
+ # Publish to npm
202
+ npm publish
203
+ ```
204
+
205
+ ---
206
+
207
+ ## License
208
+
209
+ MIT — see [LICENSE](LICENSE)
210
+
211
+ ---
212
+
213
+ ## See Also
214
+
215
+ - [agent-tasks](https://github.com/keshrath/agent-tasks) — The pipeline engine this bootstraps
216
+ - [agent-comm](https://github.com/keshrath/agent-comm) — Agent heartbeat & messaging
217
+ - [agent-knowledge](https://github.com/keshrath/agent-knowledge) — Knowledge persistence
package/bin/cli.js ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { setup, openDashboard } from '../src/setup.js';
4
+
5
+ const args = process.argv.slice(2);
6
+ const command = args[0] || 'init';
7
+ const options = {
8
+ projectRoot: process.cwd(),
9
+ verbose: args.includes('--verbose') || args.includes('-v'),
10
+ force: args.includes('--force') || args.includes('-f'),
11
+ jiraUrl: args.find(a => a.startsWith('--jira-url='))?.split('=')[1],
12
+ jiraProject: args.find(a => a.startsWith('--jira-project='))?.split('=')[1],
13
+ };
14
+
15
+ if (args.includes('--help') || args.includes('-h')) {
16
+ console.log(`
17
+ agent-scrum-master - Setup agent-tasks pipeline for your project
18
+
19
+ Usage:
20
+ npx agent-scrum-master [command] [options]
21
+
22
+ Commands:
23
+ init Initialize agent-tasks (default)
24
+ reset Remove agent-tasks setup from project
25
+ status Check if agent-tasks is initialized
26
+ dashboard Open the task dashboard in browser
27
+
28
+ Options:
29
+ --verbose, -v Show detailed output
30
+ --force, -f Overwrite existing configuration
31
+ --jira-url=<url> Jira instance URL (optional)
32
+ --jira-project=<key> Jira project key (optional)
33
+ --help, -h Show this help
34
+
35
+ Examples:
36
+ npx agent-scrum-master
37
+ npx agent-scrum-master --verbose
38
+ npx agent-scrum-master init --jira-url=https://jira.company.com --jira-project=GROWTH
39
+ npx agent-scrum-master reset
40
+ npx agent-scrum-master status
41
+ npx agent-scrum-master dashboard
42
+ `);
43
+ process.exit(0);
44
+ }
45
+
46
+ try {
47
+ if (command === 'init') {
48
+ await setup(options);
49
+ } else if (command === 'reset') {
50
+ await setup({ ...options, reset: true });
51
+ } else if (command === 'status') {
52
+ await setup({ ...options, statusOnly: true });
53
+ } else if (command === 'dashboard') {
54
+ await openDashboard(options);
55
+ } else {
56
+ console.error(`Unknown command: ${command}`);
57
+ process.exit(1);
58
+ }
59
+ } catch (error) {
60
+ console.error('\nāŒ Error:', error.message);
61
+ if (options.verbose) {
62
+ console.error(error);
63
+ }
64
+ process.exit(1);
65
+ }
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "agents-scrum-master",
3
+ "version": "1.0.0",
4
+ "description": "Auto-setup agent-tasks pipeline for any project. One command to initialize agent-driven workflow management.",
5
+ "main": "src/setup.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "agents-scrum-master": "./bin/cli.js"
9
+ },
10
+ "scripts": {
11
+ "test": "node --test tests/*.test.js",
12
+ "lint": "eslint .",
13
+ "format": "prettier --write ."
14
+ },
15
+ "keywords": [
16
+ "agent-tasks",
17
+ "ai-agents",
18
+ "task-pipeline",
19
+ "workflow",
20
+ "claude-code",
21
+ "cursor",
22
+ "mcp",
23
+ "initialization"
24
+ ],
25
+ "author": "Ashish Dogra",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/ashishdogra/agent-scrum-master.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/ashishdogra/agent-scrum-master/issues"
33
+ },
34
+ "homepage": "https://github.com/ashishdogra/agent-scrum-master#readme",
35
+ "engines": {
36
+ "node": ">=18.0.0"
37
+ }
38
+ }
package/src/setup.js ADDED
@@ -0,0 +1,186 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { spawn } from 'child_process';
5
+ import os from 'os';
6
+
7
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+
9
+ export async function setup(options = {}) {
10
+ const {
11
+ projectRoot = process.cwd(),
12
+ verbose = false,
13
+ force = false,
14
+ reset = false,
15
+ statusOnly = false,
16
+ jiraUrl = null,
17
+ jiraProject = null,
18
+ } = options;
19
+
20
+ const log = (msg) => verbose && console.log(msg);
21
+ const claudeDir = path.join(projectRoot, '.claude');
22
+ const settingsPath = path.join(claudeDir, 'settings.json');
23
+ const agentTasksDir = path.join(projectRoot, '.agent-tasks');
24
+ const gitignorePath = path.join(projectRoot, '.gitignore');
25
+
26
+ // Status check
27
+ if (statusOnly) {
28
+ const hasSettings = fs.existsSync(settingsPath);
29
+ const hasDir = fs.existsSync(agentTasksDir);
30
+ console.log(`\nšŸ“Š agent-scrum-master status in ${projectRoot}\n`);
31
+ console.log(` .claude/settings.json: ${hasSettings ? 'āœ“' : 'āœ—'}`);
32
+ console.log(` .agent-tasks/: ${hasDir ? 'āœ“' : 'āœ—'}`);
33
+ console.log(
34
+ `\n Status: ${hasSettings && hasDir ? 'āœ… Initialized' : 'āš ļø Not initialized'}\n`
35
+ );
36
+ return;
37
+ }
38
+
39
+ // Reset
40
+ if (reset) {
41
+ log('Removing agent-scrum-master setup...');
42
+ if (fs.existsSync(settingsPath)) {
43
+ fs.unlinkSync(settingsPath);
44
+ console.log('āœ“ Removed .claude/settings.json');
45
+ }
46
+ if (fs.existsSync(agentTasksDir)) {
47
+ fs.rmSync(agentTasksDir, { recursive: true, force: true });
48
+ console.log('āœ“ Removed .agent-tasks/');
49
+ }
50
+ console.log('āœ… agent-scrum-master reset complete');
51
+ return;
52
+ }
53
+
54
+ // Init
55
+ console.log('\nšŸš€ Initializing agent-scrum-master...\n');
56
+
57
+ // Ensure .claude directory exists
58
+ if (!fs.existsSync(claudeDir)) {
59
+ fs.mkdirSync(claudeDir, { recursive: true });
60
+ log('Created .claude/');
61
+ }
62
+
63
+ // Create settings.json
64
+ if (!fs.existsSync(settingsPath) || force) {
65
+ const settings = buildSettings(jiraUrl, jiraProject);
66
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
67
+ console.log('āœ“ Created .claude/settings.json');
68
+ log(` → MCP server: agent-tasks`);
69
+ log(` → Database: .agent-tasks/tasks.db`);
70
+ if (jiraUrl) log(` → Jira integration: ${jiraUrl}`);
71
+ } else {
72
+ console.log('āœ“ .claude/settings.json already exists');
73
+ if (!force) {
74
+ log(' (use --force to overwrite)');
75
+ }
76
+ }
77
+
78
+ // Ensure .agent-tasks directory exists
79
+ if (!fs.existsSync(agentTasksDir)) {
80
+ fs.mkdirSync(agentTasksDir, { recursive: true });
81
+ console.log('āœ“ Created .agent-tasks/');
82
+ } else {
83
+ log('āœ“ .agent-tasks/ already exists');
84
+ }
85
+
86
+ // Add to .gitignore
87
+ if (fs.existsSync(gitignorePath)) {
88
+ const gitignore = fs.readFileSync(gitignorePath, 'utf-8');
89
+ if (!gitignore.includes('.agent-tasks/')) {
90
+ fs.appendFileSync(gitignorePath, '\n.agent-tasks/\n');
91
+ console.log('āœ“ Added .agent-tasks/ to .gitignore');
92
+ } else {
93
+ log('āœ“ .agent-tasks/ already in .gitignore');
94
+ }
95
+ } else {
96
+ fs.writeFileSync(gitignorePath, '.agent-tasks/\n');
97
+ console.log('āœ“ Created .gitignore and added .agent-tasks/');
98
+ }
99
+
100
+ // Create .claude/.gitignore
101
+ const claudeGitignore = path.join(claudeDir, '.gitignore');
102
+ if (!fs.existsSync(claudeGitignore)) {
103
+ fs.writeFileSync(claudeGitignore, '');
104
+ log('Created .claude/.gitignore');
105
+ }
106
+
107
+ console.log(`
108
+ āœ… agent-scrum-master initialized!
109
+
110
+ Next steps:
111
+ 1. Commit: git add .claude/settings.json && git commit -m "chore: enable agent-scrum-master"
112
+ 2. Start: Open this project in Claude Code or Cursor
113
+ 3. Dashboard: http://localhost:3422 (auto-starts on first connection)
114
+ 4. Create tasks: Use 'task_create' MCP tool in your agent
115
+
116
+ Learn more: https://github.com/keshrath/agent-tasks
117
+ `);
118
+ }
119
+
120
+ export async function openDashboard(options = {}) {
121
+ const { projectRoot = process.cwd(), verbose = false } = options;
122
+
123
+ const log = (msg) => verbose && console.log(msg);
124
+ const claudeDir = path.join(projectRoot, '.claude');
125
+ const settingsPath = path.join(claudeDir, 'settings.json');
126
+
127
+ // Check if project is initialized
128
+ if (!fs.existsSync(settingsPath)) {
129
+ console.error('\nāŒ Project not initialized');
130
+ console.error(' Run: npx agent-scrum-master init\n');
131
+ process.exit(1);
132
+ }
133
+
134
+ // Read settings to get port
135
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
136
+ const port = settings.environmentVariables?.AGENT_TASKS_PORT || 3422;
137
+ const url = `http://localhost:${port}`;
138
+
139
+ console.log(`\n🌐 Opening dashboard at ${url}...\n`);
140
+
141
+ try {
142
+ // Open URL in default browser (cross-platform)
143
+ const platform = os.platform();
144
+ const openCommand =
145
+ platform === 'darwin'
146
+ ? 'open'
147
+ : platform === 'win32'
148
+ ? 'start'
149
+ : 'xdg-open';
150
+
151
+ spawn(openCommand, [url], {
152
+ stdio: 'ignore',
153
+ detached: true,
154
+ }).unref();
155
+
156
+ log(`āœ“ Dashboard should open shortly`);
157
+ console.log(`šŸ’” Make sure agent-tasks is running. Open your project in Claude Code or Cursor.`);
158
+ } catch (error) {
159
+ console.error(`\nāš ļø Could not open browser automatically`);
160
+ console.error(` Please visit: ${url}\n`);
161
+ }
162
+ }
163
+
164
+ function buildSettings(jiraUrl, jiraProject) {
165
+ const env = {
166
+ AGENT_TASKS_DB: '.agent-tasks/tasks.db',
167
+ AGENT_TASKS_PORT: '3422',
168
+ };
169
+
170
+ if (jiraUrl) {
171
+ env.AGENT_TASKS_JIRA_URL = jiraUrl;
172
+ }
173
+ if (jiraProject) {
174
+ env.AGENT_TASKS_JIRA_PROJECT = jiraProject;
175
+ }
176
+
177
+ return {
178
+ mcpServers: {
179
+ 'agent-tasks': {
180
+ command: 'npx',
181
+ args: ['agent-tasks'],
182
+ },
183
+ },
184
+ environmentVariables: env,
185
+ };
186
+ }
@@ -0,0 +1,98 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { setup } from '../src/setup.js';
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const testDir = path.join(__dirname, '../tmp-test-project');
10
+
11
+ // Cleanup helper
12
+ function cleanupTest() {
13
+ if (fs.existsSync(testDir)) {
14
+ fs.rmSync(testDir, { recursive: true, force: true });
15
+ }
16
+ }
17
+
18
+ // Ensure test directory exists
19
+ function setupTest() {
20
+ cleanupTest();
21
+ fs.mkdirSync(testDir, { recursive: true });
22
+ }
23
+
24
+ test('creates .claude directory', async () => {
25
+ setupTest();
26
+ await setup({ projectRoot: testDir });
27
+ const claudeDir = path.join(testDir, '.claude');
28
+ assert.ok(fs.existsSync(claudeDir), '.claude directory should exist');
29
+ cleanupTest();
30
+ });
31
+
32
+ test('creates .claude/settings.json with MCP config', async () => {
33
+ setupTest();
34
+ await setup({ projectRoot: testDir });
35
+ const settingsPath = path.join(testDir, '.claude', 'settings.json');
36
+ assert.ok(fs.existsSync(settingsPath), 'settings.json should exist');
37
+
38
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
39
+ assert.ok(settings.mcpServers, 'mcpServers should exist');
40
+ assert.ok(settings.mcpServers['agent-tasks'], 'agent-tasks MCP server should be configured');
41
+ assert.equal(settings.environmentVariables.AGENT_TASKS_DB, '.agent-tasks/tasks.db');
42
+ cleanupTest();
43
+ });
44
+
45
+ test('creates .agent-tasks directory', async () => {
46
+ setupTest();
47
+ await setup({ projectRoot: testDir });
48
+ const agentTasksDir = path.join(testDir, '.agent-tasks');
49
+ assert.ok(fs.existsSync(agentTasksDir), '.agent-tasks directory should exist');
50
+ cleanupTest();
51
+ });
52
+
53
+ test('adds .agent-tasks to .gitignore', async () => {
54
+ setupTest();
55
+ await setup({ projectRoot: testDir });
56
+ const gitignorePath = path.join(testDir, '.gitignore');
57
+ assert.ok(fs.existsSync(gitignorePath), '.gitignore should exist');
58
+ const gitignore = fs.readFileSync(gitignorePath, 'utf-8');
59
+ assert.ok(gitignore.includes('.agent-tasks/'), '.agent-tasks should be in .gitignore');
60
+ cleanupTest();
61
+ });
62
+
63
+ test('respects --force flag to overwrite settings', async () => {
64
+ setupTest();
65
+ const settingsPath = path.join(testDir, '.claude', 'settings.json');
66
+
67
+ // First setup
68
+ await setup({ projectRoot: testDir });
69
+ const firstSettings = fs.readFileSync(settingsPath, 'utf-8');
70
+
71
+ // Second setup without force (should not overwrite)
72
+ await setup({ projectRoot: testDir, force: false });
73
+ const secondSettings = fs.readFileSync(settingsPath, 'utf-8');
74
+ assert.equal(firstSettings, secondSettings, 'settings should not change without --force');
75
+
76
+ // Third setup with force (should update)
77
+ await setup({ projectRoot: testDir, force: true, jiraUrl: 'https://jira.example.com' });
78
+ const thirdSettings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
79
+ assert.ok(
80
+ thirdSettings.environmentVariables.AGENT_TASKS_JIRA_URL,
81
+ 'Jira URL should be added with --force'
82
+ );
83
+ cleanupTest();
84
+ });
85
+
86
+ test('includes Jira config when flags provided', async () => {
87
+ setupTest();
88
+ await setup({
89
+ projectRoot: testDir,
90
+ jiraUrl: 'https://jira.company.com',
91
+ jiraProject: 'GROWTH',
92
+ });
93
+ const settingsPath = path.join(testDir, '.claude', 'settings.json');
94
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
95
+ assert.equal(settings.environmentVariables.AGENT_TASKS_JIRA_URL, 'https://jira.company.com');
96
+ assert.equal(settings.environmentVariables.AGENT_TASKS_JIRA_PROJECT, 'GROWTH');
97
+ cleanupTest();
98
+ });