spets 0.1.1 → 0.1.3

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
@@ -5,23 +5,27 @@ Spec Driven Development Execution Framework - 유저가 정의한 스텝대로 S
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
+ # 글로벌 설치 (선택)
8
9
  npm install -g spets
10
+
11
+ # 또는 npx로 바로 사용 (설치 불필요)
12
+ npx spets init
9
13
  ```
10
14
 
11
15
  ## Quick Start
12
16
 
13
17
  ```bash
14
18
  # 프로젝트에서 초기화
15
- spets init
19
+ npx spets init
16
20
 
17
21
  # 워크플로우 시작
18
- spets start "TODO 앱 만들어줘"
22
+ npx spets start "TODO 앱 만들어줘"
19
23
 
20
24
  # 상태 확인
21
- spets status
25
+ npx spets status
22
26
 
23
27
  # 중단된 워크플로우 재개
24
- spets resume
28
+ npx spets resume
25
29
  ```
26
30
 
27
31
  ## How it Works
@@ -56,10 +60,10 @@ PR/Issue 코멘트로 워크플로우 제어:
56
60
 
57
61
  ```bash
58
62
  # GitHub Actions 워크플로우 포함해서 초기화
59
- spets init --github
63
+ npx spets init --github
60
64
 
61
65
  # GitHub 플랫폼으로 시작
62
- spets start "task" --platform github --owner myorg --repo myrepo --issue 42
66
+ npx spets start "task" --platform github --owner myorg --repo myrepo --issue 42
63
67
  ```
64
68
 
65
69
  코멘트 명령어:
@@ -71,12 +75,14 @@ spets start "task" --platform github --owner myorg --repo myrepo --issue 42
71
75
 
72
76
  ```bash
73
77
  # Claude Code 스킬 설치
74
- spets plugin install claude
78
+ npx spets plugin install claude
75
79
 
76
80
  # Claude Code에서 사용
77
81
  /spets start "task description"
78
82
  ```
79
83
 
84
+ 스킬이 설치되면 Claude Code 내에서 `npx spets` 명령어를 자동으로 실행합니다. 글로벌 설치 없이도 동작합니다.
85
+
80
86
  ## Configuration
81
87
 
82
88
  `.sept/config.yml`:
@@ -52,6 +52,10 @@ function loadStepDefinition(stepName, cwd = process.cwd()) {
52
52
  template
53
53
  };
54
54
  }
55
+ function getGitHubConfig(cwd = process.cwd()) {
56
+ const config = loadConfig(cwd);
57
+ return config.github;
58
+ }
55
59
 
56
60
  // src/core/state.ts
57
61
  function generateTaskId() {
@@ -194,6 +198,7 @@ export {
194
198
  spetsExists,
195
199
  loadConfig,
196
200
  loadStepDefinition,
201
+ getGitHubConfig,
197
202
  generateTaskId,
198
203
  getTaskDir,
199
204
  getOutputPath,
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  generateTaskId,
4
+ getGitHubConfig,
4
5
  getOutputPath,
5
6
  getSpetsDir,
6
7
  getWorkflowState,
@@ -13,7 +14,7 @@ import {
13
14
  saveTaskMetadata,
14
15
  spetsExists,
15
16
  updateDocumentStatus
16
- } from "./chunk-RW22VIUI.js";
17
+ } from "./chunk-XYU22TND.js";
17
18
 
18
19
  // src/index.ts
19
20
  import { Command } from "commander";
@@ -37,12 +38,14 @@ async function initCommand(options) {
37
38
  const templatesDir = join(__dirname, "..", "templates");
38
39
  writeFileSync(join(spetsDir, "config.yml"), getDefaultConfig());
39
40
  createDefaultSteps(spetsDir);
41
+ createClaudeCommand(cwd);
40
42
  console.log("Initialized spets in .spets/");
41
43
  console.log("");
42
44
  console.log("Created:");
43
- console.log(" .spets/config.yml - Workflow configuration");
44
- console.log(" .spets/steps/01-plan/ - Planning step");
45
- console.log(" .spets/steps/02-implement/ - Implementation step");
45
+ console.log(" .spets/config.yml - Workflow configuration");
46
+ console.log(" .spets/steps/01-plan/ - Planning step");
47
+ console.log(" .spets/steps/02-implement/ - Implementation step");
48
+ console.log(" .claude/commands/spets.md - Claude Code command");
46
49
  if (options.github) {
47
50
  createGitHubWorkflow(cwd);
48
51
  console.log(" .github/workflows/spets.yml - GitHub Actions workflow");
@@ -236,6 +239,65 @@ None / List any deviations with justification.
236
239
  - Follow-up task 2
237
240
  `;
238
241
  }
242
+ function createClaudeCommand(cwd) {
243
+ const commandDir = join(cwd, ".claude", "commands");
244
+ mkdirSync(commandDir, { recursive: true });
245
+ writeFileSync(join(commandDir, "spets.md"), getClaudeCommand());
246
+ }
247
+ function getClaudeCommand() {
248
+ return `# Spets - Spec Driven Development
249
+
250
+ Run spets workflows from Claude Code.
251
+
252
+ ## Usage
253
+
254
+ \`\`\`
255
+ /spets start "task description" - Start a new workflow
256
+ /spets status - Show workflow status
257
+ /spets resume - Resume paused workflow
258
+ \`\`\`
259
+
260
+ ## Instructions
261
+
262
+ When the user invokes this command:
263
+
264
+ 1. Parse the subcommand (start, status, resume)
265
+ 2. Execute the appropriate spets CLI command using Bash
266
+ 3. For 'start', read the generated documents and help iterate
267
+
268
+ ### Start Flow
269
+
270
+ 1. Run: \`npx spets start "<query>"\`
271
+ 2. Read the generated plan document from .spets/outputs/<taskId>/
272
+ 3. Present the plan to the user
273
+ 4. If user approves, continue. If they want changes, provide feedback.
274
+
275
+ ### Status Flow
276
+
277
+ 1. Run: \`npx spets status\`
278
+ 2. Present the current workflow state
279
+
280
+ ### Resume Flow
281
+
282
+ 1. Run: \`npx spets resume\`
283
+ 2. Continue the workflow from where it paused
284
+
285
+ ## Example Session
286
+
287
+ User: /spets start "Create a REST API for user management"
288
+
289
+ Claude:
290
+ 1. Runs \`npx spets start "Create a REST API for user management"\`
291
+ 2. Reads the generated plan
292
+ 3. Asks user: "Here's the plan. [shows plan] Would you like to approve or revise?"
293
+ 4. On approve: \`npx spets resume --approve\`
294
+ 5. On revise: \`npx spets resume --revise "user feedback"\`
295
+
296
+ $ARGUMENTS
297
+ command: The spets command to run (start, status, resume)
298
+ args: Additional arguments for the command
299
+ `;
300
+ }
239
301
  function createGitHubWorkflow(cwd) {
240
302
  const workflowDir = join(cwd, ".github", "workflows");
241
303
  mkdirSync(workflowDir, { recursive: true });
@@ -591,7 +653,7 @@ var Executor = class {
591
653
  };
592
654
 
593
655
  // src/platform/cli.ts
594
- import { spawn as spawn2 } from "child_process";
656
+ import { spawn as spawn2, execSync } from "child_process";
595
657
  import { input, select, confirm } from "@inquirer/prompts";
596
658
 
597
659
  // src/platform/interface.ts
@@ -740,6 +802,24 @@ var CliPlatform = class extends BasePlatform {
740
802
  });
741
803
  });
742
804
  }
805
+ isClaudeInstalled() {
806
+ try {
807
+ const command = process.platform === "win32" ? "where" : "which";
808
+ execSync(`${command} claude`, { stdio: "ignore" });
809
+ return true;
810
+ } catch {
811
+ return false;
812
+ }
813
+ }
814
+ getClaudeExecutable() {
815
+ if (this.claudeCommand !== "claude") {
816
+ return { command: this.claudeCommand, args: [] };
817
+ }
818
+ if (this.isClaudeInstalled()) {
819
+ return { command: "claude", args: [] };
820
+ }
821
+ return { command: "npx", args: ["--yes", "@anthropic-ai/claude-code"] };
822
+ }
743
823
  parseResponse(response) {
744
824
  const questions = [];
745
825
  const questionMatch = response.match(/```questions\n([\s\S]*?)```/);
@@ -1015,19 +1095,24 @@ async function startCommand(query, options) {
1015
1095
  saveTaskMetadata(taskId, query, cwd);
1016
1096
  let platform;
1017
1097
  if (options.platform === "github") {
1018
- if (!options.owner || !options.repo) {
1019
- console.error("GitHub platform requires --owner and --repo");
1098
+ const githubConfig = getGitHubConfig(cwd);
1099
+ const owner = options.owner || githubConfig?.owner;
1100
+ const repo = options.repo || githubConfig?.repo;
1101
+ const pr = options.pr || (githubConfig?.defaultPr ? String(githubConfig.defaultPr) : void 0);
1102
+ const issue = options.issue || (githubConfig?.defaultIssue ? String(githubConfig.defaultIssue) : void 0);
1103
+ if (!owner || !repo) {
1104
+ console.error("GitHub platform requires --owner and --repo (or set in .spets/config.yml)");
1020
1105
  process.exit(1);
1021
1106
  }
1022
- if (!options.pr && !options.issue) {
1023
- console.error("GitHub platform requires --pr or --issue");
1107
+ if (!pr && !issue) {
1108
+ console.error("GitHub platform requires --pr or --issue (or set defaultPr/defaultIssue in .spets/config.yml)");
1024
1109
  process.exit(1);
1025
1110
  }
1026
1111
  platform = new GitHubPlatform({
1027
- owner: options.owner,
1028
- repo: options.repo,
1029
- prNumber: options.pr ? parseInt(options.pr, 10) : void 0,
1030
- issueNumber: options.issue ? parseInt(options.issue, 10) : void 0
1112
+ owner,
1113
+ repo,
1114
+ prNumber: pr ? parseInt(pr, 10) : void 0,
1115
+ issueNumber: issue ? parseInt(issue, 10) : void 0
1031
1116
  });
1032
1117
  } else {
1033
1118
  platform = new CliPlatform();
@@ -1188,6 +1273,8 @@ function installClaudePlugin() {
1188
1273
  console.log(' /spets start "your task description"');
1189
1274
  console.log(" /spets status");
1190
1275
  console.log(" /spets resume");
1276
+ console.log("");
1277
+ console.log("Note: The plugin uses npx to run spets, so global installation is not required.");
1191
1278
  }
1192
1279
  async function uninstallPlugin(name) {
1193
1280
  if (name === "claude") {
@@ -1238,21 +1325,23 @@ When the user invokes this command:
1238
1325
  2. Execute the appropriate spets CLI command using Bash
1239
1326
  3. For 'start', read the generated documents and help iterate
1240
1327
 
1328
+ **Important**: Use \`npx spets\` to run commands. This ensures the command works even if spets is not globally installed.
1329
+
1241
1330
  ### Start Flow
1242
1331
 
1243
- 1. Run: \`spets start "<query>"\`
1332
+ 1. Run: \`npx spets start "<query>"\`
1244
1333
  2. Read the generated plan document from .spets/outputs/<taskId>/
1245
1334
  3. Present the plan to the user
1246
1335
  4. If user approves, continue. If they want changes, provide feedback.
1247
1336
 
1248
1337
  ### Status Flow
1249
1338
 
1250
- 1. Run: \`spets status\`
1339
+ 1. Run: \`npx spets status\`
1251
1340
  2. Present the current workflow state
1252
1341
 
1253
1342
  ### Resume Flow
1254
1343
 
1255
- 1. Run: \`spets resume\`
1344
+ 1. Run: \`npx spets resume\`
1256
1345
  2. Continue the workflow from where it paused
1257
1346
 
1258
1347
  ## Example Session
@@ -1260,11 +1349,11 @@ When the user invokes this command:
1260
1349
  User: /spets start "Create a REST API for user management"
1261
1350
 
1262
1351
  Claude:
1263
- 1. Runs \`spets start "Create a REST API for user management"\`
1352
+ 1. Runs \`npx spets start "Create a REST API for user management"\`
1264
1353
  2. Reads the generated plan
1265
1354
  3. Asks user: "Here's the plan. [shows plan] Would you like to approve or revise?"
1266
- 4. On approve: \`spets resume --approve\`
1267
- 5. On revise: \`spets resume --revise "user feedback"\`
1355
+ 4. On approve: \`npx spets resume --approve\`
1356
+ 5. On revise: \`npx spets resume --revise "user feedback"\`
1268
1357
 
1269
1358
  $ARGUMENTS
1270
1359
  command: The spets command to run (start, status, resume)
@@ -1279,9 +1368,18 @@ async function githubCommand(options) {
1279
1368
  console.error("Spets not initialized.");
1280
1369
  process.exit(1);
1281
1370
  }
1282
- const { owner, repo, pr, issue, comment, task } = options;
1371
+ const configGitHub = getGitHubConfig(cwd);
1372
+ const owner = options.owner || configGitHub?.owner;
1373
+ const repo = options.repo || configGitHub?.repo;
1374
+ const pr = options.pr || (configGitHub?.defaultPr ? String(configGitHub.defaultPr) : void 0);
1375
+ const issue = options.issue || (configGitHub?.defaultIssue ? String(configGitHub.defaultIssue) : void 0);
1376
+ const { comment, task } = options;
1377
+ if (!owner || !repo) {
1378
+ console.error("GitHub requires --owner and --repo (or set in .spets/config.yml)");
1379
+ process.exit(1);
1380
+ }
1283
1381
  if (!pr && !issue) {
1284
- console.error("Either --pr or --issue is required");
1382
+ console.error("Either --pr or --issue is required (or set defaultPr/defaultIssue in .spets/config.yml)");
1285
1383
  process.exit(1);
1286
1384
  }
1287
1385
  const parsed = parseGitHubCommand(comment);
@@ -1299,7 +1397,7 @@ async function githubCommand(options) {
1299
1397
  }
1300
1398
  if (!taskId) {
1301
1399
  const config2 = loadConfig(cwd);
1302
- const { listTasks: listTasks2 } = await import("./state-34RYXOKQ.js");
1400
+ const { listTasks: listTasks2 } = await import("./state-H2GQS43T.js");
1303
1401
  const tasks = listTasks2(cwd);
1304
1402
  for (const tid of tasks) {
1305
1403
  const state2 = getWorkflowState(tid, config2, cwd);
@@ -1431,6 +1529,6 @@ program.command("init").description("Initialize spets in current directory").opt
1431
1529
  program.command("status").description("Show current workflow status").option("-t, --task <taskId>", "Show status for specific task").action(statusCommand);
1432
1530
  program.command("start").description("Start a new workflow").argument("<query>", "User query describing the task").option("-p, --platform <platform>", "Platform to use (cli, github)", "cli").option("--owner <owner>", "GitHub owner (for github platform)").option("--repo <repo>", "GitHub repo (for github platform)").option("--pr <number>", "GitHub PR number (for github platform)").option("--issue <number>", "GitHub issue number (for github platform)").action(startCommand);
1433
1531
  program.command("resume").description("Resume paused workflow").option("-t, --task <taskId>", "Resume specific task").option("--approve", "Approve current document and proceed").option("--revise <feedback>", "Request revision with feedback").action(resumeCommand);
1434
- program.command("github").description("Handle GitHub Action callback (internal)").requiredOption("--owner <owner>", "GitHub owner").requiredOption("--repo <repo>", "GitHub repo").option("--pr <number>", "PR number").option("--issue <number>", "Issue number").option("-t, --task <taskId>", "Task ID").requiredOption("--comment <comment>", "Comment body").action(githubCommand);
1532
+ program.command("github").description("Handle GitHub Action callback (internal)").option("--owner <owner>", "GitHub owner (or set in .spets/config.yml)").option("--repo <repo>", "GitHub repo (or set in .spets/config.yml)").option("--pr <number>", "PR number (or set defaultPr in .spets/config.yml)").option("--issue <number>", "Issue number (or set defaultIssue in .spets/config.yml)").option("-t, --task <taskId>", "Task ID").requiredOption("--comment <comment>", "Comment body").action(githubCommand);
1435
1533
  program.command("plugin").description("Manage plugins").argument("<action>", "Action: install, uninstall, list").argument("[name]", "Plugin name").action(pluginCommand);
1436
1534
  program.parse();
@@ -12,7 +12,7 @@ import {
12
12
  saveDocument,
13
13
  saveTaskMetadata,
14
14
  updateDocumentStatus
15
- } from "./chunk-RW22VIUI.js";
15
+ } from "./chunk-XYU22TND.js";
16
16
  export {
17
17
  createDocument,
18
18
  ensureTaskDir,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spets",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Spec Driven Development Execution Framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",