istd-init 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Theerasak Duangkaew
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,56 @@
1
+ # istd-init
2
+
3
+ > One-command BMAD-METHOD project initializer
4
+
5
+ Initialize any folder as a BMAD-powered project with a single command.
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ mkdir my-project
11
+ cd my-project
12
+ npx istd-init
13
+ ```
14
+
15
+ That's it. BMAD is installed, git is initialized, README is created.
16
+
17
+ ## Usage
18
+
19
+ ```bash
20
+ # Interactive mode (asks questions)
21
+ npx istd-init
22
+
23
+ # Quick mode (uses defaults)
24
+ npx istd-init --yes
25
+
26
+ # Skip specific steps
27
+ npx istd-init --no-git --no-readme
28
+ ```
29
+
30
+ ## Options
31
+
32
+ | Flag | Description |
33
+ |------|-------------|
34
+ | `-y, --yes` | Skip all prompts, use defaults |
35
+ | `--no-bmad` | Skip BMAD installation |
36
+ | `--no-git` | Skip git initialization |
37
+ | `--no-readme` | Skip README creation |
38
+ | `-h, --help` | Show help |
39
+ | `-v, --version` | Show version |
40
+
41
+ ## What Gets Installed
42
+
43
+ - **BMAD-METHOD** with modules: `bmm`, `bmb`, `cis` (configurable)
44
+ - **`.gitignore`** with sensible defaults
45
+ - **`README.md`** template
46
+ - **Git repo** initialized on `main` branch
47
+
48
+ ## Requirements
49
+
50
+ - Node.js 20+
51
+ - Git
52
+ - An AI IDE (Claude Code recommended)
53
+
54
+ ## License
55
+
56
+ MIT © Theerasak Duangkaew
package/bin/cli.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { run } from '../src/index.js';
4
+
5
+ run(process.argv.slice(2)).catch((err) => {
6
+ console.error('\n❌ Error:', err.message);
7
+ if (process.env.DEBUG) {
8
+ console.error(err.stack);
9
+ }
10
+ process.exit(1);
11
+ });
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "istd-init",
3
+ "version": "0.1.0",
4
+ "description": "Initialize a project with BMAD-METHOD pre-configured in one command",
5
+ "type": "module",
6
+ "bin": {
7
+ "istd-init": "./bin/cli.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "src",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "engines": {
16
+ "node": ">=20"
17
+ },
18
+ "keywords": [
19
+ "bmad",
20
+ "bmad-method",
21
+ "init",
22
+ "scaffold",
23
+ "cli",
24
+ "ai-agile"
25
+ ],
26
+ "author": "Theerasak Duangkaew",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/iAmStarter/istd-init.git"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/iAmStarter/istd-init/issues"
34
+ },
35
+ "homepage": "https://github.com/iAmStarter/istd-init#readme",
36
+ "dependencies": {
37
+ "execa": "^9.5.1",
38
+ "ora": "^8.1.1",
39
+ "picocolors": "^1.1.1",
40
+ "prompts": "^2.4.2"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
44
+ }
45
+ }
package/src/checks.js ADDED
@@ -0,0 +1,44 @@
1
+ import { execa } from 'execa';
2
+ import { ui } from './ui.js';
3
+
4
+ async function checkNode() {
5
+ const major = parseInt(process.versions.node.split('.')[0], 10);
6
+ if (major < 20) {
7
+ throw new Error(
8
+ `Node.js 20+ is required. You have v${process.versions.node}.\n` +
9
+ ` Install from: https://nodejs.org`
10
+ );
11
+ }
12
+ }
13
+
14
+ async function checkGit() {
15
+ try {
16
+ await execa('git', ['--version']);
17
+ } catch {
18
+ throw new Error(
19
+ 'Git is required but not found.\n' +
20
+ ' Install from: https://git-scm.com'
21
+ );
22
+ }
23
+ }
24
+
25
+ async function checkNpx() {
26
+ try {
27
+ await execa('npx', ['--version']);
28
+ } catch {
29
+ throw new Error('npx not found. It should come with Node.js.');
30
+ }
31
+ }
32
+
33
+ export async function checkEnvironment() {
34
+ const spinner = ui.spinner('Checking environment...').start();
35
+ try {
36
+ await checkNode();
37
+ await checkGit();
38
+ await checkNpx();
39
+ spinner.succeed(' Environment OK');
40
+ } catch (err) {
41
+ spinner.fail(' Environment check failed');
42
+ throw err;
43
+ }
44
+ }
package/src/index.js ADDED
@@ -0,0 +1,130 @@
1
+ import { checkEnvironment } from './checks.js';
2
+ import { askQuestions } from './prompts.js';
3
+ import { installBmad } from './installers/bmad.js';
4
+ import { initGit, isGitRepo } from './installers/git.js';
5
+ import { createGitignore, createReadme } from './installers/files.js';
6
+ import { ui } from './ui.js';
7
+
8
+ const VERSION = '0.1.0';
9
+
10
+ function parseArgs(args) {
11
+ const opts = {
12
+ yes: false,
13
+ skipBmad: false,
14
+ skipGit: false,
15
+ skipReadme: false,
16
+ help: false,
17
+ version: false,
18
+ };
19
+
20
+ for (const arg of args) {
21
+ switch (arg) {
22
+ case '-y':
23
+ case '--yes':
24
+ opts.yes = true;
25
+ break;
26
+ case '--no-bmad':
27
+ opts.skipBmad = true;
28
+ break;
29
+ case '--no-git':
30
+ opts.skipGit = true;
31
+ break;
32
+ case '--no-readme':
33
+ opts.skipReadme = true;
34
+ break;
35
+ case '-h':
36
+ case '--help':
37
+ opts.help = true;
38
+ break;
39
+ case '-v':
40
+ case '--version':
41
+ opts.version = true;
42
+ break;
43
+ }
44
+ }
45
+
46
+ return opts;
47
+ }
48
+
49
+ function showHelp() {
50
+ console.log(`
51
+ ${ui.bold('istd-init')} v${VERSION}
52
+
53
+ Initialize a project with BMAD-METHOD pre-configured.
54
+
55
+ ${ui.bold('Usage:')}
56
+ npx istd-init [options]
57
+
58
+ ${ui.bold('Options:')}
59
+ -y, --yes Skip all prompts, use defaults
60
+ --no-bmad Skip BMAD installation
61
+ --no-git Skip git initialization
62
+ --no-readme Skip README creation
63
+ -h, --help Show this help
64
+ -v, --version Show version
65
+
66
+ ${ui.bold('Examples:')}
67
+ ${ui.dim('# Interactive mode')}
68
+ npx istd-init
69
+
70
+ ${ui.dim('# Quick setup with defaults')}
71
+ npx istd-init --yes
72
+
73
+ ${ui.dim('# BMAD only, no git/readme')}
74
+ npx istd-init -y --no-git --no-readme
75
+ `);
76
+ }
77
+
78
+ export async function run(args) {
79
+ const opts = parseArgs(args);
80
+
81
+ if (opts.help) {
82
+ showHelp();
83
+ return;
84
+ }
85
+
86
+ if (opts.version) {
87
+ console.log(`v${VERSION}`);
88
+ return;
89
+ }
90
+
91
+ // Header
92
+ ui.header('🚀 istd-init', 'Initialize project with BMAD-METHOD');
93
+
94
+ // 1. Environment checks
95
+ await checkEnvironment();
96
+
97
+ // 2. Show current directory info
98
+ const cwd = process.cwd();
99
+ ui.info(`📁 Working directory: ${ui.cyan(cwd)}`);
100
+
101
+ // 3. Get user preferences
102
+ const config = await askQuestions(opts);
103
+
104
+ // 4. Install BMAD
105
+ if (!opts.skipBmad) {
106
+ await installBmad(config);
107
+ } else {
108
+ ui.skip('BMAD installation skipped');
109
+ }
110
+
111
+ // 5. Create README
112
+ if (!opts.skipReadme) {
113
+ await createReadme(config);
114
+ }
115
+
116
+ // 6. Create .gitignore
117
+ await createGitignore();
118
+
119
+ // 7. Init git
120
+ if (!opts.skipGit) {
121
+ if (await isGitRepo()) {
122
+ ui.skip('Git repo already exists');
123
+ } else {
124
+ await initGit();
125
+ }
126
+ }
127
+
128
+ // 8. Success message
129
+ ui.success(config);
130
+ }
@@ -0,0 +1,33 @@
1
+ import { execa } from 'execa';
2
+ import { ui } from '../ui.js';
3
+
4
+ export async function installBmad(config) {
5
+ const spinner = ui.spinner('Installing BMAD-METHOD (this may take a minute)...').start();
6
+
7
+ try {
8
+ const args = [
9
+ 'bmad-method',
10
+ 'install',
11
+ '--yes',
12
+ '--modules',
13
+ config.modules.join(','),
14
+ '--tools',
15
+ 'claude-code',
16
+ ];
17
+
18
+ if (config.userName) {
19
+ args.push('--user-name', config.userName);
20
+ }
21
+
22
+ await execa('npx', args, {
23
+ stdio: process.env.DEBUG ? 'inherit' : 'pipe',
24
+ });
25
+
26
+ spinner.succeed(` BMAD installed (${config.modules.join(', ')})`);
27
+ } catch (err) {
28
+ spinner.fail(' BMAD installation failed');
29
+ throw new Error(
30
+ `BMAD install failed. Run with DEBUG=1 to see details.\n ${err.message}`
31
+ );
32
+ }
33
+ }
@@ -0,0 +1,117 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { ui } from '../ui.js';
5
+
6
+ const GITIGNORE_CONTENT = `# Dependencies
7
+ node_modules/
8
+ .pnp
9
+ .pnp.js
10
+
11
+ # Environment
12
+ .env
13
+ .env.local
14
+ .env.*.local
15
+
16
+ # Build output
17
+ dist/
18
+ build/
19
+ out/
20
+ *.log
21
+
22
+ # IDE
23
+ .vscode/
24
+ .idea/
25
+ *.swp
26
+ *.swo
27
+ .DS_Store
28
+ Thumbs.db
29
+
30
+ # BMAD - keep _bmad/ committed (config), ignore output cache only if you want
31
+ # _bmad-output/.cache/
32
+
33
+ # OS
34
+ .DS_Store
35
+ Thumbs.db
36
+ `;
37
+
38
+ export async function createGitignore() {
39
+ const path = join(process.cwd(), '.gitignore');
40
+ if (existsSync(path)) {
41
+ ui.skip('.gitignore already exists');
42
+ return;
43
+ }
44
+ await writeFile(path, GITIGNORE_CONTENT);
45
+ ui.ok('.gitignore created');
46
+ }
47
+
48
+ export async function createReadme(config) {
49
+ const path = join(process.cwd(), 'README.md');
50
+ if (existsSync(path)) {
51
+ ui.skip('README.md already exists');
52
+ return;
53
+ }
54
+
55
+ const content = `# ${config.projectName}
56
+
57
+ > Built with [BMAD-METHOD](https://github.com/bmad-code-org/BMAD-METHOD) — AI-driven agile development
58
+
59
+ ## Getting Started
60
+
61
+ ### Prerequisites
62
+
63
+ - Node.js 20+
64
+ - [Claude Code](https://claude.com/claude-code) (or another supported AI IDE)
65
+
66
+ ### Installation
67
+
68
+ \`\`\`bash
69
+ # Clone & enter
70
+ git clone <your-repo-url>
71
+ cd ${config.projectName}
72
+
73
+ # (BMAD is already configured in this repo via _bmad/ folder)
74
+ \`\`\`
75
+
76
+ ### Using BMAD
77
+
78
+ Open Claude Code in this folder, then type:
79
+
80
+ \`\`\`
81
+ bmad-help
82
+ \`\`\`
83
+
84
+ BMAD-Help will inspect your project and tell you exactly what to do next.
85
+
86
+ ## Project Structure
87
+
88
+ \`\`\`
89
+ ${config.projectName}/
90
+ ├── _bmad/ # BMAD configuration & runtime
91
+ ├── _bmad-output/ # Generated artifacts (PRD, architecture, stories)
92
+ │ └── planning-artifacts/
93
+ ├── .claude/ # Claude Code slash commands
94
+ └── README.md
95
+ \`\`\`
96
+
97
+ ## Development Workflow
98
+
99
+ 1. **Plan** — \`bmad-create-prd\` → produces PRD.md
100
+ 2. **Design** — \`bmad-create-architecture\` → produces architecture.md
101
+ 3. **Break down** — \`bmad-create-epics-and-stories\` → produces epics
102
+ 4. **Build** — \`bmad-create-story\` → \`bmad-dev-story\` → \`bmad-code-review\`
103
+
104
+ See [BMAD docs](https://docs.bmad-method.org/) for full reference.
105
+
106
+ ## Modules Installed
107
+
108
+ ${config.modules.map((m) => `- \`${m}\``).join('\n')}
109
+
110
+ ## License
111
+
112
+ MIT
113
+ `;
114
+
115
+ await writeFile(path, content);
116
+ ui.ok('README.md created');
117
+ }
@@ -0,0 +1,20 @@
1
+ import { execa } from 'execa';
2
+ import { existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { ui } from '../ui.js';
5
+
6
+ export async function isGitRepo() {
7
+ return existsSync(join(process.cwd(), '.git'));
8
+ }
9
+
10
+ export async function initGit() {
11
+ const spinner = ui.spinner('Initializing git repository...').start();
12
+ try {
13
+ await execa('git', ['init']);
14
+ await execa('git', ['branch', '-M', 'main']);
15
+ spinner.succeed(' Git initialized (branch: main)');
16
+ } catch (err) {
17
+ spinner.fail(' Git init failed');
18
+ throw err;
19
+ }
20
+ }
package/src/prompts.js ADDED
@@ -0,0 +1,69 @@
1
+ import prompts from 'prompts';
2
+ import { basename } from 'node:path';
3
+ import { ui } from './ui.js';
4
+
5
+ const DEFAULT_MODULES = ['bmm', 'bmb', 'cis'];
6
+ const ALL_MODULES = [
7
+ { title: 'bmm - BMad Method (core, required)', value: 'bmm', selected: true, disabled: true },
8
+ { title: 'bmb - BMad Builder', value: 'bmb', selected: true },
9
+ { title: 'cis - Creative Intelligence Suite', value: 'cis', selected: true },
10
+ { title: 'gds - Game Dev Studio', value: 'gds', selected: false },
11
+ { title: 'tea - Test Architect', value: 'tea', selected: false },
12
+ ];
13
+
14
+ export async function askQuestions(opts) {
15
+ const folderName = basename(process.cwd());
16
+
17
+ // --yes mode: ใช้ defaults ทั้งหมด
18
+ if (opts.yes) {
19
+ ui.step(`Using defaults (--yes mode)`);
20
+ return {
21
+ projectName: folderName,
22
+ modules: DEFAULT_MODULES,
23
+ userName: process.env.USER || process.env.USERNAME || 'Developer',
24
+ };
25
+ }
26
+
27
+ // Interactive mode
28
+ const responses = await prompts(
29
+ [
30
+ {
31
+ type: 'text',
32
+ name: 'projectName',
33
+ message: 'Project name:',
34
+ initial: folderName,
35
+ validate: (v) =>
36
+ v.length > 0 && /^[a-zA-Z0-9-_]+$/.test(v)
37
+ ? true
38
+ : 'Use only letters, numbers, dash, underscore',
39
+ },
40
+ {
41
+ type: 'text',
42
+ name: 'userName',
43
+ message: 'Your name (for BMAD config):',
44
+ initial: process.env.USER || process.env.USERNAME || '',
45
+ },
46
+ {
47
+ type: 'multiselect',
48
+ name: 'modules',
49
+ message: 'BMAD modules to install:',
50
+ choices: ALL_MODULES,
51
+ instructions: false,
52
+ hint: 'Space to toggle, Enter to confirm',
53
+ },
54
+ ],
55
+ {
56
+ onCancel: () => {
57
+ ui.warn('Cancelled by user');
58
+ process.exit(0);
59
+ },
60
+ }
61
+ );
62
+
63
+ // ensure bmm is always included
64
+ if (!responses.modules.includes('bmm')) {
65
+ responses.modules.unshift('bmm');
66
+ }
67
+
68
+ return responses;
69
+ }
package/src/ui.js ADDED
@@ -0,0 +1,70 @@
1
+ import pc from 'picocolors';
2
+ import ora from 'ora';
3
+
4
+ export const ui = {
5
+ // Colors
6
+ bold: pc.bold,
7
+ cyan: pc.cyan,
8
+ green: pc.green,
9
+ yellow: pc.yellow,
10
+ red: pc.red,
11
+ dim: pc.dim,
12
+ gray: pc.gray,
13
+
14
+ // Headers
15
+ header(title, subtitle) {
16
+ console.log('');
17
+ console.log(pc.bold(pc.cyan(` ${title}`)));
18
+ if (subtitle) {
19
+ console.log(pc.dim(` ${subtitle}`));
20
+ }
21
+ console.log('');
22
+ },
23
+
24
+ // Status messages
25
+ info(msg) {
26
+ console.log(` ${msg}`);
27
+ },
28
+
29
+ step(msg) {
30
+ console.log(` ${pc.cyan('→')} ${msg}`);
31
+ },
32
+
33
+ ok(msg) {
34
+ console.log(` ${pc.green('✓')} ${msg}`);
35
+ },
36
+
37
+ skip(msg) {
38
+ console.log(` ${pc.gray('○')} ${pc.dim(msg)}`);
39
+ },
40
+
41
+ warn(msg) {
42
+ console.log(` ${pc.yellow('⚠')} ${msg}`);
43
+ },
44
+
45
+ error(msg) {
46
+ console.log(` ${pc.red('✗')} ${msg}`);
47
+ },
48
+
49
+ // Spinner
50
+ spinner(text) {
51
+ return ora({ text: ` ${text}`, spinner: 'dots' });
52
+ },
53
+
54
+ // Final success message
55
+ success(config) {
56
+ console.log('');
57
+ console.log(pc.green(pc.bold(' ✨ All done!')));
58
+ console.log('');
59
+ console.log(pc.bold(' Next steps:'));
60
+ console.log('');
61
+ console.log(` ${pc.cyan('1.')} Open Claude Code in this folder:`);
62
+ console.log(` ${pc.dim('$')} ${pc.bold('claude')}`);
63
+ console.log('');
64
+ console.log(` ${pc.cyan('2.')} Inside Claude Code, type:`);
65
+ console.log(` ${pc.bold('bmad-help')}`);
66
+ console.log('');
67
+ console.log(` ${pc.cyan('3.')} Start building! 🎉`);
68
+ console.log('');
69
+ },
70
+ };