spets 0.1.1 → 0.1.2

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";
@@ -591,7 +592,7 @@ var Executor = class {
591
592
  };
592
593
 
593
594
  // src/platform/cli.ts
594
- import { spawn as spawn2 } from "child_process";
595
+ import { spawn as spawn2, execSync } from "child_process";
595
596
  import { input, select, confirm } from "@inquirer/prompts";
596
597
 
597
598
  // src/platform/interface.ts
@@ -740,6 +741,24 @@ var CliPlatform = class extends BasePlatform {
740
741
  });
741
742
  });
742
743
  }
744
+ isClaudeInstalled() {
745
+ try {
746
+ const command = process.platform === "win32" ? "where" : "which";
747
+ execSync(`${command} claude`, { stdio: "ignore" });
748
+ return true;
749
+ } catch {
750
+ return false;
751
+ }
752
+ }
753
+ getClaudeExecutable() {
754
+ if (this.claudeCommand !== "claude") {
755
+ return { command: this.claudeCommand, args: [] };
756
+ }
757
+ if (this.isClaudeInstalled()) {
758
+ return { command: "claude", args: [] };
759
+ }
760
+ return { command: "npx", args: ["--yes", "@anthropic-ai/claude-code"] };
761
+ }
743
762
  parseResponse(response) {
744
763
  const questions = [];
745
764
  const questionMatch = response.match(/```questions\n([\s\S]*?)```/);
@@ -1015,19 +1034,24 @@ async function startCommand(query, options) {
1015
1034
  saveTaskMetadata(taskId, query, cwd);
1016
1035
  let platform;
1017
1036
  if (options.platform === "github") {
1018
- if (!options.owner || !options.repo) {
1019
- console.error("GitHub platform requires --owner and --repo");
1037
+ const githubConfig = getGitHubConfig(cwd);
1038
+ const owner = options.owner || githubConfig?.owner;
1039
+ const repo = options.repo || githubConfig?.repo;
1040
+ const pr = options.pr || (githubConfig?.defaultPr ? String(githubConfig.defaultPr) : void 0);
1041
+ const issue = options.issue || (githubConfig?.defaultIssue ? String(githubConfig.defaultIssue) : void 0);
1042
+ if (!owner || !repo) {
1043
+ console.error("GitHub platform requires --owner and --repo (or set in .spets/config.yml)");
1020
1044
  process.exit(1);
1021
1045
  }
1022
- if (!options.pr && !options.issue) {
1023
- console.error("GitHub platform requires --pr or --issue");
1046
+ if (!pr && !issue) {
1047
+ console.error("GitHub platform requires --pr or --issue (or set defaultPr/defaultIssue in .spets/config.yml)");
1024
1048
  process.exit(1);
1025
1049
  }
1026
1050
  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
1051
+ owner,
1052
+ repo,
1053
+ prNumber: pr ? parseInt(pr, 10) : void 0,
1054
+ issueNumber: issue ? parseInt(issue, 10) : void 0
1031
1055
  });
1032
1056
  } else {
1033
1057
  platform = new CliPlatform();
@@ -1188,6 +1212,8 @@ function installClaudePlugin() {
1188
1212
  console.log(' /spets start "your task description"');
1189
1213
  console.log(" /spets status");
1190
1214
  console.log(" /spets resume");
1215
+ console.log("");
1216
+ console.log("Note: The plugin uses npx to run spets, so global installation is not required.");
1191
1217
  }
1192
1218
  async function uninstallPlugin(name) {
1193
1219
  if (name === "claude") {
@@ -1238,21 +1264,23 @@ When the user invokes this command:
1238
1264
  2. Execute the appropriate spets CLI command using Bash
1239
1265
  3. For 'start', read the generated documents and help iterate
1240
1266
 
1267
+ **Important**: Use \`npx spets\` to run commands. This ensures the command works even if spets is not globally installed.
1268
+
1241
1269
  ### Start Flow
1242
1270
 
1243
- 1. Run: \`spets start "<query>"\`
1271
+ 1. Run: \`npx spets start "<query>"\`
1244
1272
  2. Read the generated plan document from .spets/outputs/<taskId>/
1245
1273
  3. Present the plan to the user
1246
1274
  4. If user approves, continue. If they want changes, provide feedback.
1247
1275
 
1248
1276
  ### Status Flow
1249
1277
 
1250
- 1. Run: \`spets status\`
1278
+ 1. Run: \`npx spets status\`
1251
1279
  2. Present the current workflow state
1252
1280
 
1253
1281
  ### Resume Flow
1254
1282
 
1255
- 1. Run: \`spets resume\`
1283
+ 1. Run: \`npx spets resume\`
1256
1284
  2. Continue the workflow from where it paused
1257
1285
 
1258
1286
  ## Example Session
@@ -1260,11 +1288,11 @@ When the user invokes this command:
1260
1288
  User: /spets start "Create a REST API for user management"
1261
1289
 
1262
1290
  Claude:
1263
- 1. Runs \`spets start "Create a REST API for user management"\`
1291
+ 1. Runs \`npx spets start "Create a REST API for user management"\`
1264
1292
  2. Reads the generated plan
1265
1293
  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"\`
1294
+ 4. On approve: \`npx spets resume --approve\`
1295
+ 5. On revise: \`npx spets resume --revise "user feedback"\`
1268
1296
 
1269
1297
  $ARGUMENTS
1270
1298
  command: The spets command to run (start, status, resume)
@@ -1279,9 +1307,18 @@ async function githubCommand(options) {
1279
1307
  console.error("Spets not initialized.");
1280
1308
  process.exit(1);
1281
1309
  }
1282
- const { owner, repo, pr, issue, comment, task } = options;
1310
+ const configGitHub = getGitHubConfig(cwd);
1311
+ const owner = options.owner || configGitHub?.owner;
1312
+ const repo = options.repo || configGitHub?.repo;
1313
+ const pr = options.pr || (configGitHub?.defaultPr ? String(configGitHub.defaultPr) : void 0);
1314
+ const issue = options.issue || (configGitHub?.defaultIssue ? String(configGitHub.defaultIssue) : void 0);
1315
+ const { comment, task } = options;
1316
+ if (!owner || !repo) {
1317
+ console.error("GitHub requires --owner and --repo (or set in .spets/config.yml)");
1318
+ process.exit(1);
1319
+ }
1283
1320
  if (!pr && !issue) {
1284
- console.error("Either --pr or --issue is required");
1321
+ console.error("Either --pr or --issue is required (or set defaultPr/defaultIssue in .spets/config.yml)");
1285
1322
  process.exit(1);
1286
1323
  }
1287
1324
  const parsed = parseGitHubCommand(comment);
@@ -1299,7 +1336,7 @@ async function githubCommand(options) {
1299
1336
  }
1300
1337
  if (!taskId) {
1301
1338
  const config2 = loadConfig(cwd);
1302
- const { listTasks: listTasks2 } = await import("./state-34RYXOKQ.js");
1339
+ const { listTasks: listTasks2 } = await import("./state-H2GQS43T.js");
1303
1340
  const tasks = listTasks2(cwd);
1304
1341
  for (const tid of tasks) {
1305
1342
  const state2 = getWorkflowState(tid, config2, cwd);
@@ -1431,6 +1468,6 @@ program.command("init").description("Initialize spets in current directory").opt
1431
1468
  program.command("status").description("Show current workflow status").option("-t, --task <taskId>", "Show status for specific task").action(statusCommand);
1432
1469
  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
1470
  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);
1471
+ 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
1472
  program.command("plugin").description("Manage plugins").argument("<action>", "Action: install, uninstall, list").argument("[name]", "Plugin name").action(pluginCommand);
1436
1473
  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.2",
4
4
  "description": "Spec Driven Development Execution Framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",