productkit 1.7.0 → 1.8.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 Douno
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 CHANGED
@@ -4,6 +4,8 @@ Slash-command-driven product thinking toolkit for [Claude Code](https://claude.c
4
4
 
5
5
  Product Kit gives PMs a structured workflow for validating product ideas — user personas, problem statements, assumptions mapping — all through guided AI conversations.
6
6
 
7
+ **[Read the full guide →](https://iamquechua.github.io/product-kit/)**
8
+
7
9
  ## Prerequisites
8
10
 
9
11
  - **Node.js** 18 or later
@@ -43,6 +45,19 @@ cd my-project
43
45
 
44
46
  This scaffolds a project with slash commands, a `CLAUDE.md` context file, and a `.productkit/` config directory.
45
47
 
48
+ For existing projects:
49
+
50
+ ```bash
51
+ cd my-existing-project
52
+ productkit init --existing
53
+ ```
54
+
55
+ To keep artifacts out of the project root (recommended for busy codebases):
56
+
57
+ ```bash
58
+ productkit init --existing --artifact-dir docs/product
59
+ ```
60
+
46
61
  ### 2. Open Claude Code
47
62
 
48
63
  ```bash
@@ -64,12 +79,13 @@ Each command starts a guided conversation. Claude asks questions, pushes back on
64
79
  | 7 | `/productkit.spec` | Generate a complete product spec | `spec.md` |
65
80
  | — | `/productkit.clarify` | Resolve ambiguities and contradictions across artifacts | Updates existing files |
66
81
  | — | `/productkit.analyze` | Run a consistency and completeness check | Analysis in chat |
82
+ | — | `/productkit.bootstrap` | Auto-draft all artifacts from existing codebase | All missing artifacts |
67
83
 
68
84
  Commands build on each other — `/productkit.problem` reads your `users.md`, `/productkit.solution` reads your problem and users, and `/productkit.spec` synthesizes everything into a single document. You can run `/productkit.clarify` and `/productkit.analyze` at any stage to check your work.
69
85
 
70
86
  ### 4. Review your artifacts
71
87
 
72
- After running the commands, your project root contains:
88
+ After running the commands, your project contains:
73
89
 
74
90
  ```
75
91
  my-project/
@@ -87,6 +103,8 @@ my-project/
87
103
  └── .gitignore
88
104
  ```
89
105
 
106
+ If you used `--artifact-dir docs/product`, artifacts live in `docs/product/` instead of the project root.
107
+
90
108
  These markdown files are your product foundation — share them with your team, commit them to git, or hand `spec.md` to engineering.
91
109
 
92
110
  ## CLI Commands
@@ -95,13 +113,30 @@ These markdown files are your product foundation — share them with your team,
95
113
  |---------|-------------|
96
114
  | `productkit init <name>` | Scaffold a new project |
97
115
  | `productkit init --existing` | Add Product Kit to the current directory |
116
+ | `productkit init --minimal` | Skip constitution, start with users/problem |
117
+ | `productkit init --artifact-dir <dir>` | Store artifacts in a custom directory |
98
118
  | `productkit status` | Show progress — which artifacts exist and what's next |
119
+ | `productkit export` | Export all artifacts as a single combined markdown file |
120
+ | `productkit export --output <file>` | Export to a custom filename |
121
+ | `productkit diff` | Show what changed in artifacts since last commit |
122
+ | `productkit diff --staged` | Show staged artifact changes |
123
+ | `productkit doctor` | Check project health (missing files, outdated commands) |
99
124
  | `productkit update` | Refresh slash commands to the latest version |
100
125
  | `productkit reset` | Remove all artifacts and start over |
101
126
  | `productkit list` | Show available slash commands with descriptions |
102
127
  | `productkit completion` | Output shell completion script (bash/zsh) |
103
128
  | `productkit check` | Verify Claude Code is installed |
104
129
 
130
+ ## Cowork Plugin (No CLI Required)
131
+
132
+ If you prefer Claude Cowork over the command line, Product Kit is also available as a Cowork plugin. Same guided workflows, no terminal needed.
133
+
134
+ 1. Download [`product-kit-plugin.zip`](https://github.com/iamquechua/product-kit/releases/download/latest-plugin/product-kit-plugin.zip) from [GitHub Releases](https://github.com/iamquechua/product-kit/releases/tag/latest-plugin)
135
+ 2. In Cowork, go to **Plugins → + → Upload plugin**
136
+ 3. Select the zip file
137
+
138
+ Once installed, type `/product-kit:users`, `/product-kit:problem`, etc. in Cowork's chat. See [plugin/README.md](plugin/README.md) for details.
139
+
105
140
  ## How It Works
106
141
 
107
142
  Product Kit is a thin scaffolding tool. The real work happens in slash commands — markdown prompt files that live in `.claude/commands/`. When you type `/productkit.users` in Claude Code, it reads the prompt file and starts a guided conversation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "productkit",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Slash-command-driven product thinking toolkit for Claude Code",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -9,18 +9,23 @@ const updateCommand = require('./commands/update');
9
9
  const resetCommand = require('./commands/reset');
10
10
  const listCommand = require('./commands/list');
11
11
  const completionCommand = require('./commands/completion');
12
+ const exportCommand = require('./commands/export');
13
+ const diffCommand = require('./commands/diff');
14
+ const doctorCommand = require('./commands/doctor');
12
15
 
13
16
  const program = new Command();
14
17
 
15
18
  program
16
19
  .name('productkit')
17
20
  .description(chalk.cyan.bold('Product thinking toolkit for Claude Code'))
18
- .version('1.7.0');
21
+ .version('1.8.0');
19
22
 
20
23
  program
21
24
  .command('init [projectName]')
22
25
  .description('Initialize a new product research project')
23
26
  .option('--existing', 'Add Product Kit to the current directory')
27
+ .option('--minimal', 'Skip constitution, start with users/problem')
28
+ .option('--artifact-dir <dir>', 'Directory for artifacts (default: project root)')
24
29
  .action(initCommand);
25
30
 
26
31
  program
@@ -55,6 +60,23 @@ program
55
60
  .option('--shell <shell>', 'Shell type (bash or zsh)')
56
61
  .action(completionCommand);
57
62
 
63
+ program
64
+ .command('export')
65
+ .description('Export all artifacts as a single combined markdown file')
66
+ .option('--output <file>', 'Output filename', 'export.md')
67
+ .action(exportCommand);
68
+
69
+ program
70
+ .command('diff')
71
+ .description('Show what changed since last commit across artifacts')
72
+ .option('--staged', 'Show staged changes instead of unstaged')
73
+ .action(diffCommand);
74
+
75
+ program
76
+ .command('doctor')
77
+ .description('Check project health (missing files, outdated commands, etc.)')
78
+ .action(doctorCommand);
79
+
58
80
  program.parse(process.argv);
59
81
 
60
82
  if (process.argv.length === 2) {
@@ -0,0 +1,68 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { execSync } = require('child_process');
5
+ const { getArtifactDir } = require('../utils/fileUtils');
6
+
7
+ const ARTIFACT_FILES = [
8
+ 'constitution.md',
9
+ 'users.md',
10
+ 'problem.md',
11
+ 'assumptions.md',
12
+ 'solution.md',
13
+ 'priorities.md',
14
+ 'spec.md',
15
+ ];
16
+
17
+ async function diff(options) {
18
+ const root = process.cwd();
19
+ const configPath = path.join(root, '.productkit', 'config.json');
20
+
21
+ if (!fs.existsSync(configPath)) {
22
+ console.error(chalk.red('Not a Product Kit project.'));
23
+ console.log('Run: productkit init <name>');
24
+ process.exit(1);
25
+ }
26
+
27
+ // Check if git is available
28
+ try {
29
+ execSync('git rev-parse --git-dir', { cwd: root, stdio: 'ignore' });
30
+ } catch {
31
+ console.error(chalk.red('Not a git repository. The diff command requires git.'));
32
+ process.exit(1);
33
+ }
34
+
35
+ const artifactDir = getArtifactDir(root);
36
+ const relDir = path.relative(root, artifactDir);
37
+ const existing = ARTIFACT_FILES
38
+ .map(f => relDir && relDir !== '.' ? path.join(relDir, f) : f)
39
+ .filter(f => fs.existsSync(path.join(root, f)));
40
+
41
+ if (existing.length === 0) {
42
+ console.error(chalk.red('No artifacts found. Run some slash commands first.'));
43
+ process.exit(1);
44
+ }
45
+
46
+ const gitArgs = options.staged ? ['diff', '--cached'] : ['diff'];
47
+ const cmd = ['git', ...gitArgs, '--', ...existing].join(' ');
48
+
49
+ let output;
50
+ try {
51
+ output = execSync(cmd, { cwd: root, encoding: 'utf-8' });
52
+ } catch (err) {
53
+ // git diff returns exit code 1 when there are differences in some configs
54
+ output = err.stdout || '';
55
+ }
56
+
57
+ if (!output) {
58
+ console.log(chalk.yellow('No changes to artifacts since last commit.'));
59
+ if (!options.staged) {
60
+ console.log(chalk.dim('Tip: use --staged to see staged changes.'));
61
+ }
62
+ return;
63
+ }
64
+
65
+ console.log(output);
66
+ }
67
+
68
+ module.exports = diff;
@@ -0,0 +1,115 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { execSync } = require('child_process');
5
+
6
+ async function doctor() {
7
+ const root = process.cwd();
8
+ const configPath = path.join(root, '.productkit', 'config.json');
9
+
10
+ if (!fs.existsSync(configPath)) {
11
+ console.error(chalk.red('Not a Product Kit project.'));
12
+ console.log('Run: productkit init <name>');
13
+ process.exit(1);
14
+ }
15
+
16
+ const results = { pass: 0, warn: 0, fail: 0 };
17
+
18
+ function pass(msg) { results.pass++; console.log(chalk.green(` pass ${msg}`)); }
19
+ function warn(msg) { results.warn++; console.log(chalk.yellow(` warn ${msg}`)); }
20
+ function fail(msg) { results.fail++; console.log(chalk.red(` fail ${msg}`)); }
21
+
22
+ console.log();
23
+ console.log(chalk.bold('Project health check'));
24
+ console.log();
25
+
26
+ // 1. Config file
27
+ try {
28
+ const config = fs.readJsonSync(configPath);
29
+ if (config.version) {
30
+ pass('Config file is valid');
31
+ } else {
32
+ warn('Config file missing version field');
33
+ }
34
+ } catch {
35
+ fail('Config file is not valid JSON');
36
+ }
37
+
38
+ // 2. Commands directory
39
+ const commandsDir = path.join(root, '.claude', 'commands');
40
+ if (fs.existsSync(commandsDir)) {
41
+ pass('Commands directory exists');
42
+ } else {
43
+ fail('Commands directory missing (.claude/commands/)');
44
+ }
45
+
46
+ // 3. Check for expected command templates
47
+ const templatesDir = path.join(__dirname, '..', '..', 'templates', 'commands');
48
+ const expectedCommands = fs.readdirSync(templatesDir);
49
+
50
+ // Account for minimal mode
51
+ let config = {};
52
+ try { config = fs.readJsonSync(configPath); } catch {}
53
+ const skippable = config.minimal ? ['productkit.constitution.md'] : [];
54
+
55
+ const missing = [];
56
+ for (const cmd of expectedCommands) {
57
+ if (skippable.includes(cmd)) continue;
58
+ if (!fs.existsSync(path.join(commandsDir, cmd))) {
59
+ missing.push(cmd);
60
+ }
61
+ }
62
+
63
+ if (missing.length === 0) {
64
+ pass('All expected command templates present');
65
+ } else {
66
+ for (const m of missing) {
67
+ fail(`Missing command template: ${m}`);
68
+ }
69
+ }
70
+
71
+ // 4. Check for outdated commands
72
+ const outdated = [];
73
+ for (const cmd of expectedCommands) {
74
+ if (skippable.includes(cmd)) continue;
75
+ const installedPath = path.join(commandsDir, cmd);
76
+ if (!fs.existsSync(installedPath)) continue;
77
+
78
+ const installed = fs.readFileSync(installedPath, 'utf-8');
79
+ const bundled = fs.readFileSync(path.join(templatesDir, cmd), 'utf-8');
80
+ if (installed !== bundled) {
81
+ outdated.push(cmd);
82
+ }
83
+ }
84
+
85
+ if (outdated.length === 0) {
86
+ pass('All command templates up to date');
87
+ } else {
88
+ for (const o of outdated) {
89
+ warn(`Outdated command: ${o} — run productkit update`);
90
+ }
91
+ }
92
+
93
+ // 5. Git initialized
94
+ try {
95
+ execSync('git rev-parse --git-dir', { cwd: root, stdio: 'ignore' });
96
+ pass('Git repository initialized');
97
+ } catch {
98
+ warn('No git repository — consider running git init');
99
+ }
100
+
101
+ // Summary
102
+ console.log();
103
+ const parts = [];
104
+ if (results.pass > 0) parts.push(chalk.green(`${results.pass} passed`));
105
+ if (results.warn > 0) parts.push(chalk.yellow(`${results.warn} warning(s)`));
106
+ if (results.fail > 0) parts.push(chalk.red(`${results.fail} failed`));
107
+ console.log(chalk.bold('Result: ') + parts.join(', '));
108
+ console.log();
109
+
110
+ if (results.fail > 0) {
111
+ process.exit(1);
112
+ }
113
+ }
114
+
115
+ module.exports = doctor;
@@ -0,0 +1,50 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { getArtifactDir } = require('../utils/fileUtils');
5
+
6
+ const ARTIFACTS = [
7
+ { file: 'constitution.md', label: 'Constitution' },
8
+ { file: 'users.md', label: 'Users' },
9
+ { file: 'problem.md', label: 'Problem' },
10
+ { file: 'assumptions.md', label: 'Assumptions' },
11
+ { file: 'solution.md', label: 'Solution' },
12
+ { file: 'priorities.md', label: 'Priorities' },
13
+ { file: 'spec.md', label: 'Spec' },
14
+ ];
15
+
16
+ async function exportCommand(options) {
17
+ const root = process.cwd();
18
+ const configPath = path.join(root, '.productkit', 'config.json');
19
+
20
+ if (!fs.existsSync(configPath)) {
21
+ console.error(chalk.red('Not a Product Kit project.'));
22
+ console.log('Run: productkit init <name>');
23
+ process.exit(1);
24
+ }
25
+
26
+ const artifactDir = getArtifactDir(root);
27
+ const existing = ARTIFACTS.filter(a => fs.existsSync(path.join(artifactDir, a.file)));
28
+
29
+ if (existing.length === 0) {
30
+ console.error(chalk.red('No artifacts found. Run some slash commands first.'));
31
+ process.exit(1);
32
+ }
33
+
34
+ const sections = [];
35
+ for (const artifact of existing) {
36
+ const content = fs.readFileSync(path.join(artifactDir, artifact.file), 'utf-8');
37
+ sections.push(content);
38
+ }
39
+
40
+ const projectName = path.basename(root);
41
+ const header = `# ${projectName} — Product Kit Export\n\n_Exported: ${new Date().toISOString().split('T')[0]}_\n\n---\n`;
42
+ const combined = header + sections.join('\n\n---\n\n') + '\n';
43
+
44
+ const outputFile = options.output || 'export.md';
45
+ fs.writeFileSync(path.join(root, outputFile), combined);
46
+
47
+ console.log(chalk.green.bold(`Exported ${existing.length} artifact(s) to ${outputFile}`));
48
+ }
49
+
50
+ module.exports = exportCommand;
@@ -2,7 +2,7 @@ const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
  const chalk = require('chalk');
4
4
 
5
- function scaffold(projectRoot, projectName) {
5
+ function scaffold(projectRoot, projectName, minimal, artifactDir) {
6
6
  const templatesDir = path.join(__dirname, '..', '..', 'templates');
7
7
 
8
8
  // Create directories
@@ -10,15 +10,24 @@ function scaffold(projectRoot, projectName) {
10
10
  fs.ensureDirSync(path.join(projectRoot, '.claude', 'commands'));
11
11
 
12
12
  // Write config
13
- fs.writeJsonSync(path.join(projectRoot, '.productkit', 'config.json'), {
13
+ const config = {
14
14
  version: '1.0.0',
15
15
  created: new Date().toISOString(),
16
- }, { spaces: 2 });
16
+ };
17
+ if (minimal) {
18
+ config.minimal = true;
19
+ }
20
+ if (artifactDir) {
21
+ config.artifact_dir = artifactDir;
22
+ fs.ensureDirSync(path.join(projectRoot, artifactDir));
23
+ }
24
+ fs.writeJsonSync(path.join(projectRoot, '.productkit', 'config.json'), config, { spaces: 2 });
17
25
 
18
26
  // Copy slash command templates
19
27
  const commandsDir = path.join(templatesDir, 'commands');
20
28
  const commandFiles = fs.readdirSync(commandsDir);
21
29
  for (const file of commandFiles) {
30
+ if (minimal && file === 'productkit.constitution.md') continue;
22
31
  fs.copyFileSync(
23
32
  path.join(commandsDir, file),
24
33
  path.join(projectRoot, '.claude', 'commands', file)
@@ -61,13 +70,13 @@ async function init(projectName, options) {
61
70
  }
62
71
 
63
72
  try {
64
- scaffold(projectRoot, path.basename(projectRoot));
73
+ scaffold(projectRoot, path.basename(projectRoot), options.minimal, options.artifactDir);
65
74
 
66
75
  console.log(chalk.green.bold('Product Kit added to existing project!'));
67
76
  console.log();
68
77
  console.log(chalk.cyan('Next steps:'));
69
78
  console.log(' 1. claude');
70
- console.log(' 2. /productkit.constitution');
79
+ console.log(` 2. /productkit.${options.minimal ? 'users' : 'constitution'}`);
71
80
  console.log();
72
81
  } catch (error) {
73
82
  console.error(chalk.red('Error initializing:'), error.message);
@@ -89,7 +98,7 @@ async function init(projectName, options) {
89
98
  }
90
99
 
91
100
  try {
92
- scaffold(projectRoot, projectName);
101
+ scaffold(projectRoot, projectName, options.minimal, options.artifactDir);
93
102
 
94
103
  // Init git repo
95
104
  const { execSync } = require('child_process');
@@ -104,7 +113,7 @@ async function init(projectName, options) {
104
113
  console.log(chalk.cyan('Next steps:'));
105
114
  console.log(` 1. cd ${projectName}`);
106
115
  console.log(' 2. claude');
107
- console.log(' 3. /productkit.constitution');
116
+ console.log(` 3. /productkit.${options.minimal ? 'users' : 'constitution'}`);
108
117
  console.log();
109
118
  } catch (error) {
110
119
  console.error(chalk.red('Error initializing project:'), error.message);
@@ -2,6 +2,7 @@ const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
  const chalk = require('chalk');
4
4
  const readline = require('readline');
5
+ const { getArtifactDir } = require('../utils/fileUtils');
5
6
 
6
7
  const ARTIFACTS = [
7
8
  'constitution.md',
@@ -36,9 +37,11 @@ async function reset(options) {
36
37
  process.exit(1);
37
38
  }
38
39
 
40
+ const artifactDir = getArtifactDir(root);
41
+
39
42
  // Find existing artifacts
40
43
  const existing = ARTIFACTS.filter(file =>
41
- fs.existsSync(path.join(root, file))
44
+ fs.existsSync(path.join(artifactDir, file))
42
45
  );
43
46
 
44
47
  if (existing.length === 0) {
@@ -67,7 +70,7 @@ async function reset(options) {
67
70
  }
68
71
 
69
72
  for (const file of existing) {
70
- fs.removeSync(path.join(root, file));
73
+ fs.removeSync(path.join(artifactDir, file));
71
74
  console.log(chalk.yellow(` removed ${file}`));
72
75
  }
73
76
 
@@ -1,6 +1,7 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
  const chalk = require('chalk');
4
+ const { getArtifactDir } = require('../utils/fileUtils');
4
5
 
5
6
  const ARTIFACTS = [
6
7
  { file: 'constitution.md', command: '/productkit.constitution', label: 'Constitution' },
@@ -22,11 +23,12 @@ async function status() {
22
23
  process.exit(1);
23
24
  }
24
25
 
26
+ const artifactDir = getArtifactDir(root);
25
27
  const done = [];
26
28
  const remaining = [];
27
29
 
28
30
  for (const artifact of ARTIFACTS) {
29
- const exists = fs.existsSync(path.join(root, artifact.file));
31
+ const exists = fs.existsSync(path.join(artifactDir, artifact.file));
30
32
  if (exists) {
31
33
  done.push(artifact);
32
34
  } else {
@@ -12,7 +12,19 @@ function getProjectRoot() {
12
12
  return null;
13
13
  }
14
14
 
15
+ function getArtifactDir(root) {
16
+ const configPath = path.join(root, '.productkit', 'config.json');
17
+ try {
18
+ const config = fs.readJsonSync(configPath);
19
+ if (config.artifact_dir) {
20
+ return path.join(root, config.artifact_dir);
21
+ }
22
+ } catch {}
23
+ return root;
24
+ }
25
+
15
26
  module.exports = {
16
27
  isProductKitProject,
17
28
  getProjectRoot,
29
+ getArtifactDir,
18
30
  };
@@ -15,10 +15,11 @@ Use these commands in order to build your product foundation:
15
15
  7. `/productkit.spec` — Generate a product spec
16
16
  8. `/productkit.clarify` — Resolve ambiguities across artifacts
17
17
  9. `/productkit.analyze` — Run a completeness/consistency check
18
+ 10. `/productkit.bootstrap` — Auto-draft all artifacts from an existing codebase
18
19
 
19
20
  ## Artifacts
20
21
 
21
- Product artifacts are written to the project root as markdown files:
22
+ Product artifacts are written as markdown files. Check `.productkit/config.json` for an `artifact_dir` field — if set, artifacts live in that directory instead of the project root. Default artifact locations:
22
23
  - `constitution.md` — Product principles and values
23
24
  - `users.md` — Target user personas
24
25
  - `problem.md` — Problem statement
@@ -30,3 +31,5 @@ Product artifacts are written to the project root as markdown files:
30
31
  ## Workflow
31
32
 
32
33
  Start with `/productkit.constitution` or `/productkit.users`, then work through the commands in order. Each command reads previous artifacts to maintain consistency.
34
+
35
+ For existing projects, use `/productkit.bootstrap` to auto-draft all artifacts from your codebase in one session.
@@ -1,6 +1,6 @@
1
1
  # {{PROJECT_NAME}}
2
2
 
3
- A product research project powered by [Product Kit](https://github.com/douno/product-kit).
3
+ A product research project powered by [Product Kit](https://github.com/iamquechua/product-kit). See the [full guide](https://iamquechua.github.io/product-kit/) for a walkthrough.
4
4
 
5
5
  ## Getting Started
6
6
 
@@ -19,9 +19,12 @@ Then use the slash commands to build your product foundation:
19
19
  7. `/productkit.spec` — Generate a product spec
20
20
  8. `/productkit.clarify` — Resolve ambiguities
21
21
  9. `/productkit.analyze` — Check consistency and completeness
22
+ 10. `/productkit.bootstrap` — Auto-draft all artifacts from existing codebase
22
23
 
23
24
  ## Artifacts
24
25
 
26
+ Artifacts are written to the project root by default. If `artifact_dir` is set in `.productkit/config.json`, they are written there instead.
27
+
25
28
  | File | Description |
26
29
  |------|-------------|
27
30
  | `constitution.md` | Product principles and values |
@@ -10,7 +10,9 @@ Evaluate the overall quality, consistency, and completeness of the product think
10
10
 
11
11
  ## Before You Start
12
12
 
13
- Read all existing artifacts in the project root:
13
+ Check `.productkit/config.json` for an `artifact_dir` field. If set, read artifacts there instead of the project root. If not set, default to the project root.
14
+
15
+ Read all existing artifacts:
14
16
  - `constitution.md`
15
17
  - `users.md`
16
18
  - `problem.md`
@@ -41,7 +41,9 @@ Also read if they exist:
41
41
 
42
42
  ## Output
43
43
 
44
- Write to `assumptions.md` in the project root:
44
+ Check `.productkit/config.json` for an `artifact_dir` field. If set, write artifacts there instead of the project root. If not set, default to the project root.
45
+
46
+ Write to `assumptions.md`:
45
47
 
46
48
  ```markdown
47
49
  # Assumptions
@@ -0,0 +1,81 @@
1
+ ---
2
+ description: Auto-draft all product artifacts from an existing codebase
3
+ ---
4
+
5
+ You are a product analyst bootstrapping Product Kit artifacts for an existing project. Your job is to read the codebase and draft each artifact so the user gets a fast start instead of building from scratch.
6
+
7
+ ## Your Role
8
+
9
+ Analyze the existing project — code, docs, README, config files, comments — and draft product artifacts in workflow order. Present each draft for user approval before writing it.
10
+
11
+ ## Before You Start
12
+
13
+ 1. Read the project's README, CLAUDE.md, package.json (or equivalent), and scan the directory structure to understand what this project does.
14
+ 2. Check `.productkit/config.json` for an `artifact_dir` field. If set, read and write artifacts there instead of the project root. If not set, default to the project root.
15
+ 3. Check which artifacts already exist (constitution.md, users.md, problem.md, assumptions.md, solution.md, priorities.md, spec.md) in the artifact directory. **Skip any that already exist** — tell the user you're skipping them.
16
+ 4. Check `.productkit/config.json` — if `minimal: true`, skip `constitution.md`.
17
+
18
+ ## Process
19
+
20
+ Work through each missing artifact in this order:
21
+
22
+ ### 1. Constitution (`constitution.md`)
23
+ Draft based on: README vision/mission, CLAUDE.md principles, project conventions.
24
+ - Product vision — infer from what the project does
25
+ - Core principles — infer from code patterns, docs, and design choices
26
+ - Non-negotiables — infer from what the project explicitly avoids
27
+
28
+ ### 2. Users (`users.md`)
29
+ Draft based on: README audience, docs, issue tracker themes, CLI help text, UI copy.
30
+ - Identify 2-4 user types from project context
31
+ - Describe each with specifics inferred from the codebase
32
+
33
+ ### 3. Problem (`problem.md`)
34
+ Draft based on: README "why", issue patterns, gaps the project fills.
35
+ - Frame the core problem the project solves
36
+ - Ground it in the users you just defined
37
+
38
+ ### 4. Assumptions (`assumptions.md`)
39
+ Draft based on: implicit bets in the architecture, undocumented dependencies, target audience guesses.
40
+ - Surface 5-10 assumptions from code and docs
41
+ - Categorize by risk (high/medium/low)
42
+
43
+ ### 5. Solution (`solution.md`)
44
+ Draft based on: the actual implementation, architecture choices, alternatives mentioned in docs/comments.
45
+ - Describe the chosen approach and why
46
+ - Note alternatives that were likely considered
47
+
48
+ ### 6. Priorities (`priorities.md`)
49
+ Draft based on: feature completeness, TODO comments, open issues, roadmap docs.
50
+ - List features/capabilities by apparent priority
51
+ - Flag gaps between what exists and what's needed
52
+
53
+ ### 7. Spec (`spec.md`)
54
+ Draft based on: all previous artifacts plus technical implementation details.
55
+ - Synthesize everything into a product spec
56
+
57
+ ## For Each Artifact
58
+
59
+ 1. **Show your draft** — present the full markdown content
60
+ 2. **Explain your reasoning** — briefly note what codebase signals you used
61
+ 3. **Ask for approval** — "Should I write this to `[filename]`? Or would you like to adjust anything?"
62
+ 4. **On approval** — write the file to the artifact directory
63
+ 5. **On feedback** — revise and re-present
64
+
65
+ ## Conversation Style
66
+
67
+ - Be direct — present drafts quickly, don't over-ask before showing something
68
+ - Flag low-confidence sections with "[Needs input]" where the codebase doesn't give enough signal
69
+ - If the codebase has very little documentation, acknowledge gaps honestly and ask the user to fill in
70
+ - After each artifact, move to the next without prompting — keep momentum
71
+
72
+ ## Output
73
+
74
+ Each artifact follows the same format as its corresponding slash command would produce. Refer to the individual command templates for the expected structure.
75
+
76
+ ## When Done
77
+
78
+ After all artifacts are written (or skipped), summarize:
79
+ - Which artifacts were drafted and written
80
+ - Which were skipped (already existed)
81
+ - Suggest running `/productkit.clarify` to resolve any cross-artifact inconsistencies
@@ -10,7 +10,9 @@ Cross-reference all existing artifacts, find inconsistencies, and guide the user
10
10
 
11
11
  ## Before You Start
12
12
 
13
- Read all existing artifacts in the project root:
13
+ Check `.productkit/config.json` for an `artifact_dir` field. If set, read and write artifacts there instead of the project root. If not set, default to the project root.
14
+
15
+ Read all existing artifacts:
14
16
  - `constitution.md`
15
17
  - `users.md`
16
18
  - `problem.md`
@@ -25,7 +25,9 @@ Act as a seasoned PM mentor. Guide the user through defining their product's cor
25
25
 
26
26
  ## Output
27
27
 
28
- Write the final constitution to `constitution.md` in the project root with this format:
28
+ Check `.productkit/config.json` for an `artifact_dir` field. If set, write artifacts there instead of the project root. If not set, default to the project root.
29
+
30
+ Write the final constitution to `constitution.md` with this format:
29
31
 
30
32
  ```markdown
31
33
  # Product Constitution
@@ -42,7 +42,9 @@ If `solution.md` does not exist, tell the user to run `/productkit.solution` fir
42
42
 
43
43
  ## Output
44
44
 
45
- Write to `priorities.md` in the project root:
45
+ Check `.productkit/config.json` for an `artifact_dir` field. If set, write artifacts there instead of the project root. If not set, default to the project root.
46
+
47
+ Write to `priorities.md`:
46
48
 
47
49
  ```markdown
48
50
  # Feature Priorities
@@ -34,7 +34,9 @@ If `users.md` does not exist, tell the user to run `/productkit.users` first.
34
34
 
35
35
  ## Output
36
36
 
37
- Write the problem statement to `problem.md` in the project root:
37
+ Check `.productkit/config.json` for an `artifact_dir` field. If set, write artifacts there instead of the project root. If not set, default to the project root.
38
+
39
+ Write the problem statement to `problem.md`:
38
40
 
39
41
  ```markdown
40
42
  # Problem Statement
@@ -44,7 +44,9 @@ If `users.md` or `problem.md` do not exist, tell the user to run `/productkit.us
44
44
 
45
45
  ## Output
46
46
 
47
- Write to `solution.md` in the project root:
47
+ Check `.productkit/config.json` for an `artifact_dir` field. If set, write artifacts there instead of the project root. If not set, default to the project root.
48
+
49
+ Write to `solution.md`:
48
50
 
49
51
  ```markdown
50
52
  # Solution
@@ -10,7 +10,9 @@ Pull together everything the user has built — constitution, users, problem, as
10
10
 
11
11
  ## Before You Start
12
12
 
13
- Read all existing artifacts in the project root:
13
+ Check `.productkit/config.json` for an `artifact_dir` field. If set, read and write artifacts there instead of the project root. If not set, default to the project root.
14
+
15
+ Read all existing artifacts:
14
16
  - `constitution.md` — product principles
15
17
  - `users.md` — target users (required)
16
18
  - `problem.md` — problem statement (required)
@@ -37,7 +39,7 @@ At minimum, `users.md`, `problem.md`, and `solution.md` must exist. If any are m
37
39
 
38
40
  ## Output
39
41
 
40
- Write to `spec.md` in the project root:
42
+ Write to `spec.md`:
41
43
 
42
44
  ```markdown
43
45
  # Product Spec: [Product Name]
@@ -33,7 +33,9 @@ Read `constitution.md` if it exists — use the product vision to inform user di
33
33
 
34
34
  ## Output
35
35
 
36
- Write the final personas to `users.md` in the project root with this format:
36
+ Check `.productkit/config.json` for an `artifact_dir` field. If set, write artifacts there instead of the project root. If not set, default to the project root.
37
+
38
+ Write the final personas to `users.md` with this format:
37
39
 
38
40
  ```markdown
39
41
  # Target Users