@longtable/cli 0.1.2 → 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.
Files changed (3) hide show
  1. package/README.md +53 -59
  2. package/dist/cli.js +181 -5
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,107 +1,101 @@
1
1
  # @longtable/cli
2
2
 
3
- Researcher-facing Long Table CLI built on top of the legacy `@diverga/*` package surface.
3
+ Long Table researcher-facing CLI입니다.
4
4
 
5
- 현재 공개 설치 경로는 `@longtable/cli`입니다.
5
+ 패키지는 연구자가 아래처럼 시작할 수 있게 만드는 것이 목표입니다.
6
6
 
7
- ## Install
8
-
9
- 공개 설치:
7
+ - `longtable init`
8
+ - `longtable start`
9
+ - `longtable ask --prompt "..."`
10
10
 
11
- ```bash
12
- npm install -g @longtable/cli
13
- ```
11
+ 긴 내부 명령이나 legacy package 이름을 알 필요 없이,
12
+ 연구자가 `오늘 무엇이 필요한가`에서 바로 출발할 수 있게 하는 표면입니다.
14
13
 
15
- 로컬 preview:
14
+ ## Install
16
15
 
17
16
  ```bash
18
- npm install
19
- npm run build
20
- node packages/longtable/dist/cli.js --help
17
+ npm install -g @longtable/cli
21
18
  ```
22
19
 
23
20
  ## Recommended flow
24
21
 
25
- Run setup once and install Codex prompt aliases:
22
+ ### 1. Setup once
26
23
 
27
24
  ```bash
28
- longtable init --flow interview --install-prompts
25
+ longtable init --flow interview
29
26
  ```
30
27
 
31
- `longtable init` now uses an arrow-key terminal menu instead of plain number-entry prompts and supports:
28
+ 인터뷰 setup은 연구자의
32
29
 
33
- - `--flow quickstart`
34
- - `--flow interview`
30
+ - 현재 주제
31
+ - 현재 막힘
32
+ - 선호하는 첫 진입 모드
33
+ - 가장 많이 도전받고 싶은 영역
34
+ - 역할 간 의견 충돌 가시성
35
35
 
36
- Then you can work in two ways.
36
+ 까지 저장합니다.
37
37
 
38
- From the terminal:
38
+ ### 2. Start from today’s work
39
39
 
40
40
  ```bash
41
- longtable ask --prompt "연구를 시작하고 싶어. 지금 어디서부터 좁혀야 할지 모르겠어."
42
- longtable review --prompt "Review this claim critically."
43
- longtable review --prompt "BJET 편집자 관점에서 봐줘." --role editor
44
- longtable review --prompt "방법론적으로 어디가 취약한지 말해줘." --panel --show-conflicts
41
+ longtable start
45
42
  ```
46
43
 
47
- Inside Codex after prompt aliases are installed:
48
-
49
- - `/prompts:longtable`
50
- - `/prompts:longtable-init`
51
- - `/prompts:longtable-explore`
52
- - `/prompts:longtable-review`
53
- - `/prompts:longtable-critique`
54
- - `/prompts:longtable-draft`
55
- - `/prompts:longtable-commit`
56
- - `/prompts:longtable-status`
44
+ `longtable start`는 가장 단순한 진입점입니다.
45
+ 오늘 필요한 작업을 먼저 고르고, 그 다음 자연어로 상황을 말하면 됩니다.
57
46
 
58
- ## Core commands
47
+ ### 3. Or jump straight in
59
48
 
60
49
  ```bash
61
- longtable ask --prompt "Help me open this research problem carefully."
62
- longtable init
63
- longtable show --json
64
- longtable install --json
65
- longtable explore --prompt "Help me stay exploratory."
66
- longtable review --prompt "Review this claim critically."
67
- longtable commit --prompt "Help me make this decision carefully."
50
+ longtable ask --prompt "연구를 시작하고 싶은데 어디서부터 좁혀야 할지 모르겠어."
68
51
  ```
69
52
 
70
- ## Codex overlay
71
-
72
- Install Codex prompt aliases:
53
+ ## Useful commands
73
54
 
74
55
  ```bash
75
- longtable codex install-prompts
56
+ longtable start
57
+ longtable roles
58
+ longtable ask --prompt "이 연구 아이디어를 어디서부터 열어야 할지 모르겠어."
59
+ longtable review --prompt "BJET 편집자 관점에서 봐줘." --role editor
60
+ longtable review --prompt "방법론적으로 어디가 취약한지 말해줘." --role methods_critic
61
+ longtable review --prompt "의견 충돌까지 보여줘." --panel --show-conflicts
62
+ longtable show --json
76
63
  ```
77
64
 
78
- If you finish onboarding inside Codex with `/prompts:longtable-init`, you can persist the collected answers with:
65
+ ## What `roles` means
79
66
 
80
67
  ```bash
81
- longtable codex persist-init --flow interview --provider codex --field education --career-stage doctoral --experience intermediate --project-type "journal article" --checkpoint balanced --topic "AI adoption in workplace settings" --blocker "기업 맥락으로 범위를 다시 잡아야 하는데 어디서부터 포함/제외 기준을 세울지 모르겠어." --entry-mode explore --weakest-domain methodology --panel-preference show_on_conflict --install-prompts
68
+ longtable roles
82
69
  ```
83
70
 
84
- Or from a JSON block:
71
+ Long Table이 어떤 관점을 호출할 수 있는지 짧게 보여줍니다.
85
72
 
86
- ```bash
87
- pbpaste | longtable codex persist-init --stdin --install-prompts
88
- ```
73
+ 예:
74
+
75
+ - `editor`
76
+ - `reviewer`
77
+ - `methods_critic`
78
+ - `voice_keeper`
89
79
 
90
- Check whether setup and aliases are present:
80
+ 기본값은 하나의 Long Table synthesis이지만, 필요하면 panel과 conflict도 드러낼 수 있습니다.
81
+
82
+ ## Codex integration
83
+
84
+ Long Table은 Codex prompt file 설치도 지원합니다.
91
85
 
92
86
  ```bash
87
+ longtable codex install-prompts
93
88
  longtable codex status
94
89
  ```
95
90
 
96
- Remove the aliases:
91
+ 하지만 경로는 현재 `실험적`입니다.
97
92
 
98
- ```bash
99
- longtable codex remove-prompts
100
- ```
93
+ - Codex 버전/빌드에 따라 prompt file이 slash command로 바로 노출되지 않을 수 있습니다.
94
+ - 그래서 기본 사용자 경로는 `/prompts:...`가 아니라 `longtable start`와 `longtable ask`입니다.
101
95
 
102
96
  ## Why this package exists
103
97
 
104
- Long Table is the product name.
105
- `Diverga` remains an internal compatibility layer for some lower-level packages and runtime paths.
98
+ Long Table 제품명입니다.
99
+ `Diverga`는 아직 일부 하위 패키지와 runtime path에서만 남아 있는 호환성 레이어입니다.
106
100
 
107
- This package exists so researchers can install and run `longtable` directly while that compatibility layer remains underneath.
101
+ 패키지는 연구자가 `longtable`만 알면 되게 하기 위해 존재합니다.
package/dist/cli.js CHANGED
@@ -7,6 +7,7 @@ import { buildProviderChoices, buildQuickSetupFlow, createPersistedSetupOutput,
7
7
  import { buildCodexThinWrappedPrompt, runCodexThinWrapper } from "@diverga/provider-codex";
8
8
  import { installCodexPromptAliases, listInstalledCodexPromptAliases, removeCodexPromptAliases, resolveCodexPromptsDir } from "./prompt-aliases.js";
9
9
  import { buildPersonaGuidance } from "./persona-router.js";
10
+ import { PERSONA_DEFINITIONS } from "./personas.js";
10
11
  const VALID_MODES = new Set([
11
12
  "explore",
12
13
  "review",
@@ -28,6 +29,8 @@ function usage() {
28
29
  return [
29
30
  "Usage:",
30
31
  " longtable init [--flow quickstart|interview] [--provider codex|claude] [--field <field>] [--career-stage <stage>] [--experience novice|intermediate|advanced] [--project-type <type>] [--checkpoint low|balanced|high] [--authorship-signal <text>] [--topic <text>] [--blocker <text>] [--entry-mode explore|review|critique|draft|commit] [--weakest-domain theory|methodology|measurement|analysis|writing] [--panel-preference synthesis_only|show_on_conflict|always_visible] [--json] [--no-install] [--install-prompts]",
32
+ " longtable start [--prompt <text>] [--setup <path>] [--cwd <path>] [--print] [--json]",
33
+ " longtable roles [--json]",
31
34
  " longtable show [--json] [--path <file>]",
32
35
  " longtable install [--json] [--path <file>] [--runtime-path <file>]",
33
36
  " longtable ask [--prompt <text>] [--print] [--json] [--setup <path>] [--cwd <path>]",
@@ -39,6 +42,8 @@ function usage() {
39
42
  "",
40
43
  "Examples:",
41
44
  " longtable init --flow interview --install-prompts",
45
+ " longtable start",
46
+ " longtable roles",
42
47
  " longtable ask --prompt \"연구를 시작하고 싶어. 지금 어디서부터 좁혀야 할지 모르겠어.\"",
43
48
  " longtable review --prompt \"Review this claim critically.\" --panel --show-conflicts",
44
49
  " longtable review --role editor --prompt \"BJET 편집자 관점에서 봐줘.\"",
@@ -51,7 +56,7 @@ function parseArgs(argv) {
51
56
  const values = {};
52
57
  let subcommand = maybeSubcommand;
53
58
  const modeCommand = command && VALID_MODES.has(command);
54
- const directCommand = command && ["init", "show", "install", "codex", "ask"].includes(command);
59
+ const directCommand = command && ["init", "start", "roles", "show", "install", "codex", "ask"].includes(command);
55
60
  let startIndex = 1;
56
61
  if (modeCommand) {
57
62
  subcommand = undefined;
@@ -137,6 +142,9 @@ function questionSection(questionId) {
137
142
  }
138
143
  return "Authorship and voice";
139
144
  }
145
+ function formatModeLabel(mode) {
146
+ return `${mode[0].toUpperCase()}${mode.slice(1)}`;
147
+ }
140
148
  function moveCursorUp(lines) {
141
149
  return lines > 0 ? `\u001B[${lines}A` : "";
142
150
  }
@@ -252,6 +260,52 @@ async function promptChoiceWithArrows(rl, prompt, choices) {
252
260
  async function promptChoice(rl, prompt, choices) {
253
261
  return promptChoiceWithArrows(rl, prompt, choices);
254
262
  }
263
+ async function promptStartAction(rl, blocker) {
264
+ return (await promptChoice(rl, blocker?.trim()
265
+ ? `What do you want to do with this first?\nCurrent blocker: ${blocker.trim()}`
266
+ : "What do you want Long Table to help you do first?", [
267
+ {
268
+ id: "explore",
269
+ label: "Open the problem",
270
+ description: "Start with questions, tensions, and a clearer research direction."
271
+ },
272
+ {
273
+ id: "review",
274
+ label: "Review something",
275
+ description: "Critically inspect a claim, outline, or draft."
276
+ },
277
+ {
278
+ id: "critique",
279
+ label: "Challenge me hard",
280
+ description: "Push back, stress-test assumptions, and surface hidden risks."
281
+ },
282
+ {
283
+ id: "editor",
284
+ label: "Journal editor view",
285
+ description: "See how an editor might judge framing, fit, and contribution."
286
+ },
287
+ {
288
+ id: "methods",
289
+ label: "Methods check",
290
+ description: "Focus on design fit, defensibility, and methodological weakness."
291
+ },
292
+ {
293
+ id: "panel",
294
+ label: "Show disagreement",
295
+ description: "Let multiple roles disagree instead of forcing one answer."
296
+ },
297
+ {
298
+ id: "status",
299
+ label: "Check my setup",
300
+ description: "See what Long Table knows and what is installed."
301
+ },
302
+ {
303
+ id: "roles",
304
+ label: "What roles exist?",
305
+ description: "See what perspectives Long Table can bring into the conversation."
306
+ }
307
+ ]));
308
+ }
255
309
  function hasCompleteFlagInput(args) {
256
310
  const required = ["provider", "field", "career-stage", "experience", "project-type", "checkpoint"];
257
311
  return required.every((key) => typeof args[key] === "string" && String(args[key]).trim().length > 0);
@@ -429,15 +483,18 @@ async function runInit(args) {
429
483
  }
430
484
  if (installedPrompts.length > 0) {
431
485
  console.log("");
432
- console.log("Installed Codex prompt aliases:");
486
+ console.log("Installed Codex prompt files:");
433
487
  for (const prompt of installedPrompts) {
434
488
  console.log(`- /prompts:${prompt.name}`);
435
489
  }
490
+ console.log(" Note: whether Codex exposes these as slash commands depends on your Codex build.");
436
491
  }
437
492
  if (provider === "codex") {
438
493
  console.log("");
439
494
  console.log("Next step:");
440
- console.log("- Open Codex and start with `/prompts:longtable`.");
495
+ console.log("- Start here: `longtable start`.");
496
+ console.log("- If you want a direct natural-language entry: `longtable ask --prompt \"...\"`.");
497
+ console.log("- Codex prompt files are available as an experimental integration, not the primary path.");
441
498
  if (answers.currentBlocker) {
442
499
  console.log(`- Suggested first message: ${answers.currentBlocker}`);
443
500
  }
@@ -492,15 +549,18 @@ async function runCodexPersistInit(args) {
492
549
  console.log(renderInstallSummary(result));
493
550
  if (installedPrompts.length > 0) {
494
551
  console.log("");
495
- console.log("Installed Codex prompt aliases:");
552
+ console.log("Installed Codex prompt files:");
496
553
  for (const prompt of installedPrompts) {
497
554
  console.log(`- /prompts:${prompt.name}`);
498
555
  }
556
+ console.log(" Note: whether Codex exposes these as slash commands depends on your Codex build.");
499
557
  }
500
558
  if (provider === "codex") {
501
559
  console.log("");
502
560
  console.log("Next step:");
503
- console.log("- Start Codex and use `/prompts:longtable` for the most natural entry.");
561
+ console.log("- Start here: `longtable start`.");
562
+ console.log("- If you want a direct natural-language entry: `longtable ask --prompt \"...\"`.");
563
+ console.log("- Codex prompt files are available as an experimental integration, not the primary path.");
504
564
  if (answers.currentBlocker) {
505
565
  console.log(`- Suggested first message: ${answers.currentBlocker}`);
506
566
  }
@@ -642,11 +702,118 @@ async function runAsk(args) {
642
702
  }
643
703
  await runModeCommand(mode, delegatedArgs);
644
704
  }
705
+ async function runRoles(args) {
706
+ const payload = PERSONA_DEFINITIONS.map((persona) => ({
707
+ key: persona.key,
708
+ label: persona.label,
709
+ description: persona.shortDescription,
710
+ triggerMode: persona.triggerMode,
711
+ exampleTriggers: persona.synonyms.slice(0, 4)
712
+ }));
713
+ if (args.json === true) {
714
+ console.log(JSON.stringify(payload, null, 2));
715
+ return;
716
+ }
717
+ console.log("Long Table roles");
718
+ console.log("These are perspectives Long Table can consult when relevant.");
719
+ console.log("");
720
+ for (const persona of payload) {
721
+ console.log(`- ${persona.label} (${persona.key})`);
722
+ console.log(` ${persona.description}`);
723
+ console.log(` Trigger: ${persona.triggerMode === "auto-callable" ? "auto-callable when your language strongly implies it" : "explicit request only"}`);
724
+ console.log(` Examples: ${persona.exampleTriggers.join(", ")}`);
725
+ }
726
+ }
727
+ async function runStart(args) {
728
+ const setupPath = typeof args.setup === "string" ? args.setup : undefined;
729
+ const existingSetup = await loadOptionalSetup(setupPath);
730
+ if (!existingSetup) {
731
+ console.log("Long Table is not set up yet. Starting the interview flow first.");
732
+ console.log("");
733
+ await runInit({
734
+ ...args,
735
+ flow: typeof args.flow === "string" ? args.flow : "interview",
736
+ "install-prompts": true
737
+ });
738
+ return;
739
+ }
740
+ const directPrompt = typeof args.prompt === "string" ? args.prompt.trim() : "";
741
+ if (directPrompt) {
742
+ await runAsk({
743
+ ...args,
744
+ prompt: directPrompt,
745
+ ...(setupPath ? { setup: setupPath } : {})
746
+ });
747
+ return;
748
+ }
749
+ const rl = createInterface({ input, output });
750
+ try {
751
+ const action = await promptStartAction(rl, existingSetup.profileSeed.currentBlocker ?? existingSetup.profileSeed.currentResearchTopic);
752
+ if (action === "status") {
753
+ rl.close();
754
+ await runCodexSubcommand("status", args);
755
+ return;
756
+ }
757
+ if (action === "roles") {
758
+ rl.close();
759
+ await runRoles(args);
760
+ return;
761
+ }
762
+ const defaultPrompt = existingSetup.profileSeed.currentBlocker ??
763
+ existingSetup.profileSeed.currentResearchTopic ??
764
+ "";
765
+ const prompt = (await rl.question(defaultPrompt
766
+ ? `What are you working on today?\nPress Enter to use: ${defaultPrompt}\n> `
767
+ : "What are you working on today?\n> ")).trim() || defaultPrompt;
768
+ rl.close();
769
+ if (!prompt) {
770
+ throw new Error("A prompt is required.");
771
+ }
772
+ if (action === "editor") {
773
+ await runModeCommand("review", {
774
+ ...args,
775
+ prompt,
776
+ role: "editor",
777
+ ...(setupPath ? { setup: setupPath } : {})
778
+ });
779
+ return;
780
+ }
781
+ if (action === "methods") {
782
+ await runModeCommand("review", {
783
+ ...args,
784
+ prompt,
785
+ role: "methods_critic",
786
+ ...(setupPath ? { setup: setupPath } : {})
787
+ });
788
+ return;
789
+ }
790
+ if (action === "panel") {
791
+ await runModeCommand("review", {
792
+ ...args,
793
+ prompt,
794
+ panel: true,
795
+ "show-conflicts": true,
796
+ ...(setupPath ? { setup: setupPath } : {})
797
+ });
798
+ return;
799
+ }
800
+ const mode = action;
801
+ await runModeCommand(mode, {
802
+ ...args,
803
+ prompt,
804
+ ...(setupPath ? { setup: setupPath } : {})
805
+ });
806
+ }
807
+ finally {
808
+ rl.close();
809
+ }
810
+ }
645
811
  async function runCodexSubcommand(subcommand, args) {
646
812
  const customDir = typeof args.dir === "string" ? args.dir : undefined;
647
813
  if (subcommand === "install-prompts") {
648
814
  const installed = await installCodexPromptAliases(customDir);
649
815
  console.log(`Installed ${installed.length} Long Table prompt aliases in ${resolveCodexPromptsDir(customDir)}`);
816
+ console.log("Note: prompt-file discovery depends on the Codex build. Treat this as an experimental integration.");
650
817
  for (const prompt of installed) {
651
818
  console.log(`- /prompts:${prompt.name}`);
652
819
  }
@@ -681,6 +848,7 @@ async function runCodexSubcommand(subcommand, args) {
681
848
  console.log(`- setup: ${status.setupExists ? "present" : "missing"} (${setupPath})`);
682
849
  console.log(`- codex runtime artifact: ${status.runtimeExists ? "present" : "missing"} (${runtimePath})`);
683
850
  console.log(`- prompt aliases dir: ${status.promptsDir}`);
851
+ console.log("- prompt-file integration: experimental (your Codex build may not expose these as slash commands)");
684
852
  if (aliases.length === 0) {
685
853
  console.log("- prompt aliases: none");
686
854
  }
@@ -705,6 +873,14 @@ async function main() {
705
873
  await runInit(values);
706
874
  return;
707
875
  }
876
+ if (command === "start") {
877
+ await runStart(values);
878
+ return;
879
+ }
880
+ if (command === "roles") {
881
+ await runRoles(values);
882
+ return;
883
+ }
708
884
  if (command === "show") {
709
885
  await runShow(values);
710
886
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longtable/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "description": "Researcher-facing Long Table CLI on top of the legacy Diverga package surface",
6
6
  "type": "module",
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@diverga/provider-codex": "0.1.1",
29
- "@diverga/setup": "0.1.2"
29
+ "@diverga/setup": "0.1.3"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.10.1",