productkit 1.5.1 → 1.6.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 CHANGED
@@ -98,6 +98,7 @@ These markdown files are your product foundation — share them with your team,
98
98
  | `productkit status` | Show progress — which artifacts exist and what's next |
99
99
  | `productkit update` | Refresh slash commands to the latest version |
100
100
  | `productkit reset` | Remove all artifacts and start over |
101
+ | `productkit list` | Show available slash commands with descriptions |
101
102
  | `productkit check` | Verify Claude Code is installed |
102
103
 
103
104
  ## How It Works
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "productkit",
3
- "version": "1.5.1",
3
+ "version": "1.6.1",
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
@@ -7,13 +7,14 @@ const checkCommand = require('./commands/check');
7
7
  const statusCommand = require('./commands/status');
8
8
  const updateCommand = require('./commands/update');
9
9
  const resetCommand = require('./commands/reset');
10
+ const listCommand = require('./commands/list');
10
11
 
11
12
  const program = new Command();
12
13
 
13
14
  program
14
15
  .name('productkit')
15
16
  .description(chalk.cyan.bold('Product thinking toolkit for Claude Code'))
16
- .version('1.5.0');
17
+ .version('1.6.0');
17
18
 
18
19
  program
19
20
  .command('init [projectName]')
@@ -39,8 +40,14 @@ program
39
40
  program
40
41
  .command('reset')
41
42
  .description('Remove all artifacts and start over')
43
+ .option('--force', 'Skip confirmation prompt')
42
44
  .action(resetCommand);
43
45
 
46
+ program
47
+ .command('list')
48
+ .description('Show available slash commands with descriptions')
49
+ .action(listCommand);
50
+
44
51
  program.parse(process.argv);
45
52
 
46
53
  if (process.argv.length === 2) {
@@ -0,0 +1,47 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+
5
+ async function list() {
6
+ const root = process.cwd();
7
+ const commandsDir = path.join(root, '.claude', 'commands');
8
+
9
+ if (!fs.existsSync(commandsDir)) {
10
+ console.error(chalk.red('No slash commands found.'));
11
+ console.log('Run: productkit init <name>');
12
+ process.exit(1);
13
+ }
14
+
15
+ const files = fs.readdirSync(commandsDir)
16
+ .filter(f => f.startsWith('productkit.') && f.endsWith('.md'))
17
+ .sort();
18
+
19
+ if (files.length === 0) {
20
+ console.log(chalk.yellow('No Product Kit slash commands found.'));
21
+ process.exit(0);
22
+ }
23
+
24
+ console.log();
25
+ console.log(chalk.bold('Available slash commands:'));
26
+ console.log();
27
+
28
+ for (const file of files) {
29
+ const name = '/' + file.replace('.md', '');
30
+ const content = fs.readFileSync(path.join(commandsDir, file), 'utf-8');
31
+
32
+ // Extract description from front-matter
33
+ let description = '';
34
+ const match = content.match(/^---\s*\n[\s\S]*?description:\s*(.+)\n[\s\S]*?---/);
35
+ if (match) {
36
+ description = match[1].trim();
37
+ }
38
+
39
+ console.log(` ${chalk.cyan(name)}`);
40
+ if (description) {
41
+ console.log(` ${description}`);
42
+ }
43
+ console.log();
44
+ }
45
+ }
46
+
47
+ module.exports = list;
@@ -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 readline = require('readline');
4
5
 
5
6
  const ARTIFACTS = [
6
7
  'constitution.md',
@@ -12,7 +13,20 @@ const ARTIFACTS = [
12
13
  'spec.md',
13
14
  ];
14
15
 
15
- async function reset() {
16
+ function confirm(question) {
17
+ const rl = readline.createInterface({
18
+ input: process.stdin,
19
+ output: process.stdout,
20
+ });
21
+ return new Promise((resolve) => {
22
+ rl.question(question, (answer) => {
23
+ rl.close();
24
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
25
+ });
26
+ });
27
+ }
28
+
29
+ async function reset(options) {
16
30
  const root = process.cwd();
17
31
  const configPath = path.join(root, '.productkit', 'config.json');
18
32
 
@@ -22,24 +36,44 @@ async function reset() {
22
36
  process.exit(1);
23
37
  }
24
38
 
25
- let removed = 0;
39
+ // Find existing artifacts
40
+ const existing = ARTIFACTS.filter(file =>
41
+ fs.existsSync(path.join(root, file))
42
+ );
26
43
 
27
- for (const file of ARTIFACTS) {
28
- const filePath = path.join(root, file);
29
- if (fs.existsSync(filePath)) {
30
- fs.removeSync(filePath);
31
- console.log(chalk.yellow(` removed ${file}`));
32
- removed++;
33
- }
44
+ if (existing.length === 0) {
45
+ console.log();
46
+ console.log(chalk.green.bold('Nothing to reset — no artifacts found.'));
47
+ console.log();
48
+ return;
34
49
  }
35
50
 
51
+ // Show what will be deleted
36
52
  console.log();
37
- if (removed > 0) {
38
- console.log(chalk.green.bold(`Reset complete. ${removed} artifact${removed === 1 ? '' : 's'} removed.`));
39
- } else {
40
- console.log(chalk.green.bold('Nothing to reset — no artifacts found.'));
53
+ console.log(chalk.yellow.bold(`Found ${existing.length} artifact${existing.length === 1 ? '' : 's'}:`));
54
+ for (const file of existing) {
55
+ console.log(chalk.yellow(` ${file}`));
41
56
  }
42
57
  console.log();
58
+
59
+ // Confirm unless --force
60
+ if (!options.force) {
61
+ const yes = await confirm(chalk.red('Delete these artifacts? (y/N) '));
62
+ if (!yes) {
63
+ console.log('Reset cancelled.');
64
+ return;
65
+ }
66
+ console.log();
67
+ }
68
+
69
+ for (const file of existing) {
70
+ fs.removeSync(path.join(root, file));
71
+ console.log(chalk.yellow(` removed ${file}`));
72
+ }
73
+
74
+ console.log();
75
+ console.log(chalk.green.bold(`Reset complete. ${existing.length} artifact${existing.length === 1 ? '' : 's'} removed.`));
76
+ console.log();
43
77
  }
44
78
 
45
79
  module.exports = reset;