harness-bujang 0.1.0 → 0.2.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/README.md CHANGED
@@ -7,13 +7,16 @@ Install the [Harness-Bujang](https://github.com/bjcho4141/harness-bujang) multi-
7
7
  ## Quick start
8
8
 
9
9
  ```bash
10
- # English agents (default), drop into the current directory
10
+ # Interactive setup prompts for language, backend, etc.
11
11
  npx harness-bujang init
12
12
 
13
+ # Non-interactive (CI / scripts) — accept all defaults
14
+ npx harness-bujang init --yes
15
+
13
16
  # Korean agents (full 부장 persona)
14
17
  npx harness-bujang init --lang=ko
15
18
 
16
- # Into a different folder, skip the chat-room UI
19
+ # Different folder, skip the chat-room UI
17
20
  npx harness-bujang init --target=./my-app --no-template
18
21
  ```
19
22
 
@@ -40,9 +43,11 @@ Options:
40
43
  --no-template Skip chat-room UI install
41
44
  --no-claude-md Skip CLAUDE.md edit
42
45
  --no-learning-log Skip learning log seed
43
- --yes, -y Overwrite existing files without asking
46
+ --yes, -y Skip prompts and overwrite (non-interactive — for CI / scripts)
44
47
  ```
45
48
 
49
+ When `--yes` is omitted and stdin is a TTY, the CLI prompts for language, chat backend, and (for Next.js projects) whether to install the chat-room UI.
50
+
46
51
  ### `status`
47
52
 
48
53
  ```
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@
4
4
  import * as fs2 from "fs/promises";
5
5
  import * as path2 from "path";
6
6
  import { fileURLToPath } from "url";
7
+ import { select, confirm } from "@inquirer/prompts";
7
8
 
8
9
  // src/scan.ts
9
10
  import * as fs from "fs/promises";
@@ -180,13 +181,11 @@ If installed via npm, try reinstalling. If running from source, run "npm run bui
180
181
  );
181
182
  }
182
183
  async function runInit(args) {
183
- const opts = parseArgs(args);
184
+ let opts = parseArgs(args);
184
185
  const assets = await resolveAssetPaths();
185
186
  console.log();
186
187
  console.log(c.bold("\u{1F4E6} Harness-Bujang init"));
187
188
  console.log(c.dim(` Target: ${opts.target}`));
188
- console.log(c.dim(` Language: ${opts.lang}`));
189
- console.log(c.dim(` Chat backend: ${opts.chatBackend}${opts.chatBackend === "sqlite" ? c.dim(" (default \u2014 local file)") : c.dim(" (cloud Postgres)")}`));
190
189
  console.log(c.dim(` Assets: ${assets.mode}`));
191
190
  console.log();
192
191
  if (!await exists2(opts.target)) {
@@ -201,6 +200,41 @@ async function runInit(args) {
201
200
  console.log(` Payment: ${scan.payment}`);
202
201
  console.log(` GitHub: ${scan.ghUser}`);
203
202
  console.log();
203
+ const interactive = !opts.yes && Boolean(process.stdin.isTTY);
204
+ if (interactive) {
205
+ try {
206
+ opts = await promptInteractive(opts, scan);
207
+ } catch (err) {
208
+ if (err && typeof err === "object" && "name" in err && err.name === "ExitPromptError") {
209
+ console.log(c.dim(" (aborted)"));
210
+ return;
211
+ }
212
+ throw err;
213
+ }
214
+ }
215
+ console.log(c.bold("\u{1F4CB} Configuration"));
216
+ console.log(c.dim(` Language: ${opts.lang}`));
217
+ console.log(c.dim(` Chat backend: ${opts.chatBackend}${opts.chatBackend === "sqlite" ? " (local file)" : " (cloud Postgres)"}`));
218
+ if (scan.framework.startsWith("Next.js")) {
219
+ console.log(c.dim(` Chat-room UI: ${opts.installTemplate ? "install" : "skip"}`));
220
+ }
221
+ console.log();
222
+ if (interactive) {
223
+ try {
224
+ const proceed = await confirm({ message: "Proceed with these settings?", default: true });
225
+ if (!proceed) {
226
+ console.log(c.dim(" (aborted)"));
227
+ return;
228
+ }
229
+ console.log();
230
+ } catch (err) {
231
+ if (err && typeof err === "object" && "name" in err && err.name === "ExitPromptError") {
232
+ console.log(c.dim(" (aborted)"));
233
+ return;
234
+ }
235
+ throw err;
236
+ }
237
+ }
204
238
  const context = {
205
239
  PROJECT_PATH: opts.target,
206
240
  PROJECT_NAME: path2.basename(opts.target),
@@ -355,6 +389,32 @@ async function runInit(args) {
355
389
  console.log(` ${c.cyan("3.")} Watch ${c.bold(context.ADMIN_HARNESS_ROUTE)} for live updates (after env setup)`);
356
390
  console.log();
357
391
  }
392
+ async function promptInteractive(opts, scan) {
393
+ const lang = await select({
394
+ message: "Agent language",
395
+ choices: [
396
+ { name: "English", value: "en" },
397
+ { name: "Korean \u2014 full \uBD80\uC7A5 persona (\uD55C\uAD6D\uC5B4)", value: "ko" }
398
+ ],
399
+ default: opts.lang
400
+ });
401
+ const chatBackend = await select({
402
+ message: "Chat backend",
403
+ choices: [
404
+ { name: "SQLite \u2014 local file, zero setup (recommended)", value: "sqlite" },
405
+ { name: "Supabase \u2014 cloud Postgres for team sharing", value: "supabase" }
406
+ ],
407
+ default: opts.chatBackend
408
+ });
409
+ let installTemplate = opts.installTemplate;
410
+ if (scan.framework.startsWith("Next.js") && opts.installTemplate) {
411
+ installTemplate = await confirm({
412
+ message: "Install chat-room UI (Next.js admin route at /admin/harness)?",
413
+ default: true
414
+ });
415
+ }
416
+ return { ...opts, lang, chatBackend, installTemplate };
417
+ }
358
418
  function parseArgs(args) {
359
419
  const lang = getFlag(args, "--lang") ?? "en";
360
420
  if (!["ko", "en"].includes(lang)) {
@@ -663,7 +723,7 @@ Run "npx harness-bujang init" first.`
663
723
  }
664
724
  console.log();
665
725
  console.log(c3.dim("Pass --yes to skip this confirmation."));
666
- if (!await confirm("Continue?")) {
726
+ if (!await confirm2("Continue?")) {
667
727
  console.log(c3.dim("Aborted."));
668
728
  return;
669
729
  }
@@ -775,7 +835,7 @@ async function upsertEnvVar(envFile, key, value) {
775
835
  }
776
836
  await fs4.writeFile(envFile, content);
777
837
  }
778
- async function confirm(message) {
838
+ async function confirm2(message) {
779
839
  process.stdout.write(`${message} [y/N] `);
780
840
  return new Promise((resolve4) => {
781
841
  process.stdin.setEncoding("utf8");
@@ -843,7 +903,9 @@ ${c4.bold("Options for init:")}
843
903
  --no-template Skip chat-room UI install
844
904
  --no-claude-md Skip CLAUDE.md edit
845
905
  --no-learning-log Skip learning log seed
846
- --yes, -y Overwrite without asking
906
+ --yes, -y Skip prompts and overwrite (non-interactive \u2014 for CI / scripts)
907
+
908
+ ${c4.dim("Run without --yes for an interactive setup (prompts for language, backend, etc.).")}
847
909
 
848
910
  ${c4.bold("Options for migrate:")}
849
911
  --to=<sqlite|supabase> Required \u2014 target backend
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harness-bujang",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Install the Harness-Bujang multi-agent harness into any project — Director, 7 specialist teams, real-time chat-room UI. Korean and English personas. Works with Claude Code, Cursor, Cline, Aider, or any tool that reads .claude/agents/.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -53,5 +53,8 @@
53
53
  },
54
54
  "engines": {
55
55
  "node": ">=20"
56
+ },
57
+ "dependencies": {
58
+ "@inquirer/prompts": "^8.4.2"
56
59
  }
57
60
  }