linersh 0.5.6 → 1.0.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.
Files changed (98) hide show
  1. package/README.md +65 -165
  2. package/bin/liner.js +82 -44
  3. package/cli-update-docs/ABOUT.md +16 -16
  4. package/cli-update-docs/AI-HANDOFF.md +62 -190
  5. package/cli-update-docs/CURATION.md +48 -19
  6. package/cli-update-docs/JTBD-MASTER-PROMPT-ABOUT.md +9 -12
  7. package/cli-update-docs/JTBD-MASTER-PROMPT.md +1 -1
  8. package/cli-update-docs/LINER-MASTER.md +77 -63
  9. package/cli-update-docs/LINER-MD-PRD.md +531 -0
  10. package/cli-update-docs/MIXTAPE-FORMAT.md +76 -44
  11. package/cli-update-docs/PLATFORM.md +47 -46
  12. package/cli-update-docs/README.md +6 -6
  13. package/cli-update-docs/SKILL.md +72 -37
  14. package/cli-update-docs/TUI-BACKLOG.md +205 -26
  15. package/cli-update-docs/quality-check-tests.md +256 -8
  16. package/cli-update-docs/source-finding-tactics.md +140 -3
  17. package/cli-update-docs/source-quality-hierarchy.md +83 -0
  18. package/cli-update-docs/synthesis-guidance.md +19 -5
  19. package/dist/agents/artifact-validation.js +440 -0
  20. package/dist/agents/artifact-validation.js.map +1 -0
  21. package/dist/agents/candidate-longlist.js +100 -0
  22. package/dist/agents/candidate-longlist.js.map +1 -0
  23. package/dist/agents/detect.js +3 -2
  24. package/dist/agents/detect.js.map +1 -1
  25. package/dist/agents/evaluation-assembly.js +270 -0
  26. package/dist/agents/evaluation-assembly.js.map +1 -0
  27. package/dist/agents/headless-runner.js +227 -0
  28. package/dist/agents/headless-runner.js.map +1 -0
  29. package/dist/agents/jtbd-clarify.js +42 -41
  30. package/dist/agents/jtbd-clarify.js.map +1 -1
  31. package/dist/agents/models.js +6 -7
  32. package/dist/agents/models.js.map +1 -1
  33. package/dist/agents/prompts.js +220 -20
  34. package/dist/agents/prompts.js.map +1 -1
  35. package/dist/agents/runner.js +462 -21
  36. package/dist/agents/runner.js.map +1 -1
  37. package/dist/phases.js +13 -13
  38. package/dist/phases.js.map +1 -1
  39. package/dist/source-inbox.js +297 -0
  40. package/dist/source-inbox.js.map +1 -0
  41. package/dist/version.js +3 -9
  42. package/dist/version.js.map +1 -1
  43. package/dist/yaml-io.js +42 -11
  44. package/dist/yaml-io.js.map +1 -1
  45. package/package.json +26 -23
  46. package/cli-update-docs/JOB-STORY-MIGRATION.md +0 -99
  47. package/dist/App.js +0 -220
  48. package/dist/App.js.map +0 -1
  49. package/dist/colors.js +0 -132
  50. package/dist/colors.js.map +0 -1
  51. package/dist/components/Header.js +0 -15
  52. package/dist/components/Header.js.map +0 -1
  53. package/dist/components/KeyHints.js +0 -17
  54. package/dist/components/KeyHints.js.map +0 -1
  55. package/dist/components/LabeledBox.js +0 -53
  56. package/dist/components/LabeledBox.js.map +0 -1
  57. package/dist/components/NextSteps.js +0 -18
  58. package/dist/components/NextSteps.js.map +0 -1
  59. package/dist/index.js +0 -17
  60. package/dist/index.js.map +0 -1
  61. package/dist/screens/AgentSetup.js +0 -224
  62. package/dist/screens/AgentSetup.js.map +0 -1
  63. package/dist/screens/BootSplash.js +0 -163
  64. package/dist/screens/BootSplash.js.map +0 -1
  65. package/dist/screens/CompileView.js +0 -567
  66. package/dist/screens/CompileView.js.map +0 -1
  67. package/dist/screens/FramingConfirmReview.js +0 -197
  68. package/dist/screens/FramingConfirmReview.js.map +0 -1
  69. package/dist/screens/Gate1Review.js +0 -147
  70. package/dist/screens/Gate1Review.js.map +0 -1
  71. package/dist/screens/Gate2Review.js +0 -162
  72. package/dist/screens/Gate2Review.js.map +0 -1
  73. package/dist/screens/ImportPrompt.js +0 -173
  74. package/dist/screens/ImportPrompt.js.map +0 -1
  75. package/dist/screens/JsSetup.js +0 -77
  76. package/dist/screens/JsSetup.js.map +0 -1
  77. package/dist/screens/LocalFilePicker.js +0 -139
  78. package/dist/screens/LocalFilePicker.js.map +0 -1
  79. package/dist/screens/NewMixtapeWizard.js +0 -662
  80. package/dist/screens/NewMixtapeWizard.js.map +0 -1
  81. package/dist/screens/PhaseRunner.js +0 -1203
  82. package/dist/screens/PhaseRunner.js.map +0 -1
  83. package/dist/screens/ProcessManifest.js +0 -160
  84. package/dist/screens/ProcessManifest.js.map +0 -1
  85. package/dist/screens/ProjectHub.js +0 -557
  86. package/dist/screens/ProjectHub.js.map +0 -1
  87. package/dist/screens/SourceModal.js +0 -269
  88. package/dist/screens/SourceModal.js.map +0 -1
  89. package/dist/screens/TapeBrowser.js +0 -312
  90. package/dist/screens/TapeBrowser.js.map +0 -1
  91. package/dist/screens/TapeDraftReview.js +0 -444
  92. package/dist/screens/TapeDraftReview.js.map +0 -1
  93. package/dist/screens/TapeEditor.js +0 -310
  94. package/dist/screens/TapeEditor.js.map +0 -1
  95. package/dist/screens/cassette-art.js +0 -72
  96. package/dist/screens/cassette-art.js.map +0 -1
  97. package/dist/store.js +0 -10
  98. package/dist/store.js.map +0 -1
package/README.md CHANGED
@@ -1,197 +1,97 @@
1
- # Liner TUI
1
+ # Liner NPM Shim And Runner Package
2
2
 
3
- Interactive authoring UI for [Liner](../..) — create, edit, compile, and share mixtape **project folders** from the keyboard.
3
+ This package is still named `linersh` because it owns the published `liner`
4
+ binary. It is no longer the React/Ink TUI implementation.
4
5
 
5
- A *tape file* (`tape.yaml`) is the recipe. A *mixtape* is the project folder Liner builds from it. The TUI is for authoring: it scaffolds folders, edits tapes, surfaces the synthesis status, then runs `liner compile` to produce the consumable `MIXTAPE.md` + `sources/` artifacts.
6
+ Active responsibilities:
7
+
8
+ - `bin/liner.js`: npm binary shim
9
+ - Go TUI launcher for `packages/go-tui/` in development
10
+ - TypeScript headless methodology runner under `src/agents/`
11
+ - packaged curation skill bundle copied from `../../docs/curation-skill/` into
12
+ `cli-update-docs/`
13
+ - optional per-platform packages that contain the native CLI and Go TUI
14
+ binaries for installed users
15
+
16
+ The old React/Ink TUI has been decommissioned and is no longer part of the
17
+ active package shape. `LINER_TUI=ink` intentionally fails with a decommissioning
18
+ message.
6
19
 
7
20
  ## Install
8
21
 
9
22
  ```sh
10
- # One-shot:
11
23
  npx linersh
12
-
13
- # Persistent:
14
- npm install -g linersh # adds `liner` to PATH
24
+ npm install -g linersh
15
25
  liner
16
26
  ```
17
27
 
18
- The npm package includes the TUI and resolves the Python core from a per-platform optional package (`linersh-<platform>-<arch>`). With no arguments, `liner` opens the TUI. CLI subcommands such as `liner setup-js`, `liner compile`, `liner share`, and `liner status` pass through to the bundled core.
19
-
20
- For JavaScript-rendered pages, run the setup command from the same npm install:
21
-
22
- ```sh
23
- liner setup-js
24
- ```
25
-
26
- That command is idempotent and downloads the Playwright browser used for `render: js` and automatic JS-wall fallback (about 150MB). The TUI also offers this during first-run onboarding, and again from compile results if a source needs JS rendering. For debugging or local development, `LINER_BIN=/path/to/liner liner` overrides the bundled binary.
27
-
28
- To reset a machine for clean testing, run:
29
-
30
- ```sh
31
- liner uninstall --yes
32
- ```
28
+ With no arguments, `liner` launches the Go TUI. CLI subcommands such as
29
+ `liner compile`, `liner share`, `liner import`, `liner status`, and
30
+ `liner setup-js` pass through to the Python core.
33
31
 
34
- This removes `~/.liner`, Playwright's Chromium cache, and npm's `_npx` execution cache. It does not delete your mixtape project folders. If you installed Liner globally, also run `npm uninstall -g linersh`.
32
+ ## Run Locally
35
33
 
36
- ## Run
34
+ From the repo root:
37
35
 
38
36
  ```sh
39
- cd ~/projects/my-thing
40
- liner
37
+ npm --prefix packages/tui run dev
41
38
  ```
42
39
 
43
- The TUI looks for (and creates) a `./mixtapes/` folder in your current directory. Each subdirectory inside it is a mixtape project folder (must contain a `tape.yaml`).
44
-
45
- Override the workspace with `LINER_DIR`:
40
+ From this package:
46
41
 
47
42
  ```sh
48
- LINER_DIR=~/mixtapes liner
43
+ npm run dev
49
44
  ```
50
45
 
51
- ## Keys
52
-
53
- ### Browser
54
- | Key | Action |
55
- |---|---|
56
- | `↑` `↓` or `j` `k` | move selection |
57
- | `enter` or `o` | open the selected mixtape hub |
58
- | `e` | open the selected mixtape source editor |
59
- | `n` | new mixtape (prompts for slug) |
60
- | `c` | compile selected |
61
- | `s` | share selected (zip to `.mixtape`) |
62
- | `i` | import a `.mixtape` archive |
63
- | `d` | delete selected folder (with confirm) |
64
- | `r` | refresh |
65
- | `q` | quit |
66
-
67
- ### Project Hub
68
- | Key | Action |
69
- |---|---|
70
- | `↑` `↓` | select phase |
71
- | `enter` | run/open the selected phase's primary action |
72
- | `e` | edit the selected artifact by hand |
73
- | `p` | open the process manifest |
74
- | `s` | share the mixtape |
75
- | `o` | open the project folder |
76
- | `esc` | back |
77
- | `q` | quit |
78
-
79
- Completed mixtapes land in a ready state. If `MIXTAPE.md` is current, pressing `enter` on Compile opens the existing compile result instead of fetching sources again. Press `r` from the compile result screen to explicitly re-run/retry.
80
-
81
- ### Source Editor
82
- | Key | Action |
83
- |---|---|
84
- | `t` `d` `u` | edit title / description / curator |
85
- | `m` | toggle mode (`quick` ⇄ `methodology`) |
86
- | `g` | edit JTBD (job-to-be-done) |
87
- | `E` | open `synthesis.md` in `$EDITOR` |
88
- | `↑` `↓` | select source |
89
- | `a` `e` `x` | add / edit / remove source |
90
- | `K` `J` | reorder selected source up/down |
91
- | `s` | save `tape.yaml` |
92
- | `c` | save + compile (blocked if synthesis is empty or still a placeholder) |
93
- | `esc` | back (warns on unsaved changes) |
94
-
95
- A soft warning appears when any source is missing a curator note. Notes are load-bearing — see [CURATION.md](https://liner.sh) §6.
96
-
97
- #### Local sources
98
-
99
- `local_file` sources reference content you've placed under `<project>/personal/` — book chapter PDFs, Reader-Mode-saved articles, exported HIG pages. Use them for material that isn't on the public web or that lives behind a paywall you have legitimate access to.
100
-
101
- Workflow:
102
-
103
- 1. Save the file into `<project>/personal/`. The TUI creates the folder lazily — the file picker offers a "new file (paste path)" option that you can use after saving the file manually with your OS file manager.
104
- 2. Add a source in the editor; press `T` in the source modal to switch the type to `local_file`.
105
- 3. Pick the file via the picker; supply a `citation` (author, title, publication, date — the AI uses this to weight the source).
106
- 4. Compile. The CLI extracts the content (PDFs via `pdfplumber`, HTML via the same readability pipeline as web sources, `.md`/`.txt` as-is).
107
-
108
- `liner share` includes `personal/` by default. Pass `--no-personal` (or use the corresponding TUI flag) to exclude it — required for any tape intended as a library submission.
109
-
110
- The synthesis indicator shows one of:
111
- - `✗ missing` — `liner compile` will hard-fail
112
- - `⚠ placeholder` — file exists but still has the boilerplate from `liner init`
113
- - `⚠ empty` — file exists but is empty
114
- - `✓ N chars` — ready to compile
115
-
116
- ### Source modal
117
- | Key | Action |
118
- |---|---|
119
- | `↑` `↓` | move between fields |
120
- | `enter` | edit the focused field (or open the file picker on the path field for `local_file` sources) |
121
- | `tab` | next field while editing |
122
- | `T` | toggle source type (`web` ⇄ `local_file`) |
123
- | `R` | toggle `render: server` ⇄ `render: js` (web sources only) |
124
- | `p` | toggle required/optional |
125
- | `s` | save source |
126
- | `esc` | cancel |
127
-
128
- For `web` sources the URL is the load-bearing field; the type is auto-detected as `youtube` or `web`. For `local_file` sources the modal shows `path`, `citation`, `note`, `section`, `priority` — pick the path via the file picker (lists files under `personal/`, with a "paste path" affordance for new files).
129
-
130
- ### Compile
131
- | Key | Action |
132
- |---|---|
133
- | `↑` `↓` | scroll sources |
134
- | `pgup` `pgdn` | jump through sources |
135
- | `j` | install JS rendering support when the result says it is needed |
136
- | `esc` | cancel running compile |
137
- | `y` | copy compiled `MIXTAPE.md` to clipboard (`pbcopy` / `xclip`) |
138
- | `s` | share the compiled mixtape (zip to `.mixtape`) |
139
- | `o` | open the project folder |
140
- | `r` | retry failed sources / re-run compile |
141
- | `b` | back to hub |
142
- | `q` | quit |
143
-
144
- The compile writes `MIXTAPE.md` and `sources/NN-<slug>.md` files directly into the project folder. A partial compile is still treated as a usable finished state when `MIXTAPE.md` is written; the hub shows "compiled with warnings" and the compile result screen lists the remaining warnings. There's nothing to "save" afterwards — the artifacts are already on disk.
145
-
146
- ## Uninstalling
147
-
148
- The TUI ships in the same `linersh` package as the CLI. For npm/npx installs, use the package uninstaller:
46
+ Override the projects folder:
149
47
 
150
48
  ```sh
151
- liner uninstall
152
- liner uninstall --yes
49
+ LINER_DIR=/path/to/projects node bin/liner.js
153
50
  ```
154
51
 
155
- It removes `~/.liner`, Playwright's Chromium cache, and npm's `_npx` execution cache. Your mixtape project folders are left alone. If you installed Liner globally, also run `npm uninstall -g linersh`. See the root [README — Uninstalling](../../README.md#uninstalling) for the manual recipe.
156
-
157
- ## Develop
52
+ Override the Python/core binary:
158
53
 
159
54
  ```sh
160
- cd packages/tui
161
- npm install
162
- npm run dev # tsx (no watch — Ctrl+C and re-run after code changes)
163
- npm run dev:built # builds, then runs the compiled output (closer to ship)
164
- npm run typecheck
165
- npm test # vitest
166
- npm run build # emits dist/
55
+ LINER_BIN=/absolute/path/to/liner node bin/liner.js
167
56
  ```
168
57
 
169
- **Why no `tsx watch`?** `tsx watch` keeps the TTY in raw mode for its own restart UI (Enter to restart, "rs" to force, Esc to clear). Ink TUIs also want raw stdin, and the two collide — typed characters get eaten, the app gets surprise-restarted, screens flicker. For interactive UIs, restart manually after code changes.
170
-
171
- In dev, the bin-resolver tries `LINER_BIN`, the bundled optional package, the repo-local `.venv/bin/liner`, then `liner` on `$PATH`. To point at a specific binary:
58
+ ## Build And Test
172
59
 
173
60
  ```sh
174
- LINER_BIN=/path/to/liner npm run dev
61
+ npm run build
62
+ npm run build:go
63
+ npm run build:package
64
+ npm test
175
65
  ```
176
66
 
177
- ## Architecture
178
-
179
- ```
180
- BootSplash ─────► TapeBrowser ──────► ProjectHub ──────┐
181
- │ │
182
- │ ImportPrompt ─────┤
183
- │ │
184
- ├────► NewProjectWizard ─────┤
185
- │ │
186
- ├────► TapeEditor ⇄ SourceModal
187
- │ │
188
- ├────► PhaseRunner / gates / draft review
189
- │ │
190
- └────► CompileView (streams NDJSON from `liner compile --emit-events`)
191
- ```
192
-
193
- State is global via `AppContext`. YAML is parsed and re-written in Node via the `yaml` package's `Document` API so user-written block comments survive edits. All folder operations (`init`, `compile`, `share`, `import`, `list`) go through the Python CLI as subprocesses — the TUI never reimplements them.
194
-
195
- The CLI's `compile --emit-events` streams NDJSON progress events to stdout; the TUI parses each line and updates per-source state live. The final `result` event reports the produced folder, `MIXTAPE.md` path, and per-source file paths.
196
-
197
- The same NDJSON protocol will power the planned MCP server, which calls into the same Python core directly without going through the CLI.
67
+ Notes:
68
+
69
+ - `build` compiles the TypeScript headless runner and shared runner utilities.
70
+ - `build:go` compiles `../go-tui/cmd/liner-tui` into `bin/liner-tui` for local
71
+ development.
72
+ - `build:package` runs both.
73
+ - Release packaging is verified with `npm run acceptance:go -- release-smoke`,
74
+ which packs a local platform package plus the main `linersh` package and
75
+ installs both into a clean consumer project.
76
+
77
+ ## Useful Environment Variables
78
+
79
+ - `LINER_DIR=/path/to/projects`: change the projects folder.
80
+ - `LINER_BIN=/path/to/liner`: force the Python/core binary.
81
+ - `LINER_GO_TUI_BIN=/path/to/liner-tui`: force the Go TUI binary.
82
+ - `LINER_HEADLESS_RUNNER=/path/to/headless-runner.js`: force the methodology
83
+ runner script.
84
+ - `LINER_AGENT=codex|claude`: override the agent selected by Liner config.
85
+ - `LINER_TUI=go`: accepted for compatibility, but no longer required.
86
+
87
+ ## Developer Gotchas
88
+
89
+ - Rebuild `bin/liner-tui` after Go changes or the npm shim may launch an older
90
+ binary.
91
+ - Rebuild `dist/` after TypeScript runner changes or methodology will fail.
92
+ - The published main package intentionally excludes `bin/liner-tui`; installed
93
+ users get the native TUI from `linersh-<platform>-<arch>`.
94
+ - If Project Health says `status failed`, check the resolved core. Older bundled
95
+ cores may reject `--no-write`; the Go wrapper has a fallback, but direct
96
+ `node bin/liner.js status ... --no-write` can still fail until platform cores
97
+ are refreshed.
package/bin/liner.js CHANGED
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  // Entry shim for `npx linersh` / `liner`.
3
3
  //
4
- // No args: launch the Ink TUI from dist/.
4
+ // No args: launch the selected TUI.
5
+ // unset -> launch the Charm Go TUI
6
+ // LINER_TUI=go -> launch the Charm Go TUI explicitly
5
7
  // CLI args: forward to the bundled Python core (or LINER_BIN/dev fallback).
6
8
  //
7
9
  // This lets the npm package expose one binary name while still supporting
@@ -41,6 +43,7 @@ const CLI_COMMANDS = new Set([
41
43
  "clone",
42
44
  "setup-js",
43
45
  "list",
46
+ "skills",
44
47
  "cache",
45
48
  "manifest",
46
49
  "status",
@@ -66,44 +69,67 @@ if (wantsCli(argv)) {
66
69
  process.exit(code ?? 1);
67
70
  });
68
71
  } else {
69
- // Enter the terminal's alternate screen buffer before launching Ink.
70
- //
71
- // Every Ink screen that changes total render height between frames (each
72
- // wizard step, each PhaseRunner stream event, each gate transition) was
73
- // committing older frames to the user's scrollback — producing stacked
74
- // duplicated headers above the visible content. The alternate buffer has
75
- // no scrollback by definition, so the bug class is eliminated.
76
- //
77
- // Trade-off: on exit, the TUI vanishes and the terminal returns to its
78
- // pre-launch state. Post-exit context lives in `.liner-runs/` and
79
- // `MIXTAPE.md`, which are the intended sources of truth anyway.
80
- //
81
- // Only enter alt-screen on a real TTY; piped/redirected stdout shouldn't
82
- // receive raw escape sequences.
83
- const useAltScreen = process.stdout.isTTY === true;
84
-
85
- if (useAltScreen) {
86
- process.stdout.write("\x1b[?1049h");
87
- const restoreScreen = () => {
88
- process.stdout.write("\x1b[?1049l");
89
- };
90
- process.on("exit", restoreScreen);
91
- process.on("SIGINT", () => {
92
- restoreScreen();
93
- process.exit(130);
94
- });
95
- process.on("SIGTERM", () => {
96
- restoreScreen();
97
- process.exit(143);
98
- });
99
- process.on("uncaughtException", (err) => {
100
- restoreScreen();
101
- console.error(err);
102
- process.exit(1);
103
- });
72
+ const tui = (process.env.LINER_TUI || "go").toLowerCase();
73
+ if (tui !== "go") {
74
+ console.error(
75
+ [
76
+ `Unsupported LINER_TUI value: ${process.env.LINER_TUI}`,
77
+ "",
78
+ "The Ink TUI has been decommissioned and moved to the repo's ink/ archive.",
79
+ "Run `liner` with no LINER_TUI override, or set LINER_TUI=go.",
80
+ ].join("\n"),
81
+ );
82
+ process.exit(1);
104
83
  }
105
84
 
106
- await import(join(packageRoot, "dist", "index.js"));
85
+ const resolved = resolveGoTuiBinary();
86
+ const child = spawn(resolved.command, resolved.args, {
87
+ stdio: "inherit",
88
+ cwd: resolved.cwd || process.cwd(),
89
+ env: {
90
+ ...process.env,
91
+ LINER_BIN: process.env.LINER_BIN || tryResolveCliCommand() || "",
92
+ },
93
+ });
94
+ child.on("exit", (code, signal) => {
95
+ if (signal) {
96
+ process.kill(process.pid, signal);
97
+ return;
98
+ }
99
+ process.exit(code ?? 1);
100
+ });
101
+ }
102
+
103
+ function resolveGoTuiBinary() {
104
+ const envBin = process.env.LINER_GO_TUI_BIN;
105
+ if (envBin && existsSync(envBin)) return { command: envBin, args: [] };
106
+
107
+ const packaged = join(packageRoot, "bin", process.platform === "win32" ? "liner-tui.exe" : "liner-tui");
108
+ if (existsSync(packaged)) return { command: packaged, args: [] };
109
+
110
+ const bundled = findBundledGoTuiBinary();
111
+ if (bundled) return { command: bundled, args: [] };
112
+
113
+ const sourceDir = join(packageRoot, "..", "go-tui");
114
+ if (existsSync(join(sourceDir, "go.mod"))) {
115
+ const go = spawnSync("go", ["version"], { encoding: "utf8" });
116
+ if (go.status === 0) {
117
+ return { command: "go", args: ["run", "./cmd/liner-tui"], cwd: sourceDir };
118
+ }
119
+ }
120
+
121
+ console.error(
122
+ [
123
+ "Could not find the Go Liner TUI.",
124
+ "",
125
+ "Expected one of:",
126
+ " - LINER_GO_TUI_BIN=/path/to/liner-tui",
127
+ " - packages/tui/bin/liner-tui built by npm run build:go",
128
+ " - bundled platform package (linersh-<platform>-<arch>)",
129
+ " - repo source at packages/go-tui with go installed",
130
+ ].join("\n"),
131
+ );
132
+ process.exit(1);
107
133
  }
108
134
 
109
135
  function resolveCliBinary() {
@@ -112,12 +138,12 @@ function resolveCliBinary() {
112
138
  return { command: envBin, args: [] };
113
139
  }
114
140
 
115
- const bundled = findBundledBinary();
116
- if (bundled) return { command: bundled, args: [] };
117
-
118
141
  const repoVenv = findRepoVenvBinary();
119
142
  if (repoVenv) return { command: repoVenv, args: [] };
120
143
 
144
+ const bundled = findBundledBinary();
145
+ if (bundled) return { command: bundled, args: [] };
146
+
121
147
  const pathHit = findPathBinary();
122
148
  if (pathHit) return { command: pathHit, args: [] };
123
149
 
@@ -254,13 +280,25 @@ function playwrightCachePath(home) {
254
280
  }
255
281
 
256
282
  function findBundledBinary() {
283
+ const baseDir = findBundledPackageDir();
284
+ if (!baseDir) return null;
285
+ const candidate = join(baseDir, exeName());
286
+ return existsSync(candidate) ? candidate : null;
287
+ }
288
+
289
+ function findBundledGoTuiBinary() {
290
+ const baseDir = findBundledPackageDir();
291
+ if (!baseDir) return null;
292
+ const candidate = join(baseDir, process.platform === "win32" ? "liner-tui.exe" : "liner-tui");
293
+ return existsSync(candidate) ? candidate : null;
294
+ }
295
+
296
+ function findBundledPackageDir() {
257
297
  const require = createRequire(import.meta.url);
258
298
  const target = `linersh-${process.platform}-${process.arch}`;
259
299
  try {
260
300
  const pkgJson = require.resolve(`${target}/package.json`);
261
- const baseDir = pkgJson.replace(/[\\/]package\.json$/, "");
262
- const candidate = join(baseDir, exeName());
263
- return existsSync(candidate) ? candidate : null;
301
+ return pkgJson.replace(/[\\/]package\.json$/, "");
264
302
  } catch {
265
303
  return null;
266
304
  }
@@ -311,7 +349,7 @@ function readTuiVersion() {
311
349
  function tryResolveCliCommand() {
312
350
  const envBin = process.env.LINER_BIN;
313
351
  if (envBin && existsSync(envBin)) return envBin;
314
- return findBundledBinary() || findRepoVenvBinary() || findPathBinary() || null;
352
+ return findRepoVenvBinary() || findBundledBinary() || findPathBinary() || null;
315
353
  }
316
354
 
317
355
  function printVersion() {
@@ -15,25 +15,25 @@ Liner treats curation as the work and produces a portable artifact.
15
15
  Liner is several things sharing a methodology and a file format:
16
16
 
17
17
  - **A CLI** for compiling mixtape projects
18
- - **A TUI** for the multi-step authoring lifecycle
18
+ - **A Go TUI** for the multi-step authoring lifecycle
19
19
  - **A skill** that runs the methodology inside Claude
20
- - **An MCP server** that exposes the same functions to any agent (Claude Code, Codex, Cursor, others)
21
- - **A library** of curated mixtapes anyone can clone, fork, or run as-is
20
+ - **A planned MCP server** that will expose the same functions to any agent (Claude Code, Codex, Cursor, others)
21
+ - **A planned library** of curated mixtapes anyone can clone, fork, or run as-is
22
22
  - **A methodology** documented in [CURATION.md](./CURATION.md) and applied across all the above
23
23
 
24
- The pieces are independent. The CLI works without the TUI. The skill works without the CLI. The MCP server works in any agent host. Users pick the surface that fits their workflow.
24
+ The implemented pieces are independent. The CLI works without the TUI. The skill works without the CLI. The planned MCP server will add an agent-native surface later. Users pick the surface that fits their workflow.
25
25
 
26
26
  ## What a mixtape is
27
27
 
28
- A mixtape is a project folder containing:
28
+ A mixtape is the corpus inside a Liner project folder. In v2 projects it lives under `mixtape/`; legacy root-level mixtape folders remain readable. The corpus contains:
29
29
 
30
- - A **recipe** (`tape.yaml`) — the curated list of sources with notes and sections
31
- - A **synthesis** — the curator's distilled understanding of the domain
32
- - **Source content** — extracted text from every source in the recipe
33
- - **Working notes** — the methodology's traces: JTBD, knowledge map, evaluation, quality checks
34
- - A **master file** (`MIXTAPE.md`) — the consumable artifact, with the synthesis up front and sources referenced by file
30
+ - A **recipe** (`mixtape/tape.yaml`) — the curated list of sources with notes and sections
31
+ - A **synthesis** (`mixtape/synthesis.md`) — the curator's distilled understanding of the domain
32
+ - **Source content** (`mixtape/sources/`) — extracted text from every source in the recipe
33
+ - **Working notes** (`mixtape/working/`) — the methodology's traces: JTBD, capability brief, knowledge map, source roles, evaluation, quality checks
34
+ - A **master file** (`mixtape/MIXTAPE.md`) — the consumable artifact, with the synthesis up front and sources referenced by file
35
35
 
36
- The recipe is small, shareable, and recompilable. The mixtape folder is heavier, self-contained, and ready to paste into an AI conversation. The two artifacts have different sharing properties and different purposes.
36
+ The recipe is small, shareable, and recompilable. The full Liner project folder is heavier, self-contained, and ready to hand to an AI session. The two artifacts have different sharing properties and different purposes.
37
37
 
38
38
  ## Who Liner is for
39
39
 
@@ -47,22 +47,22 @@ A few decisions that distinguish Liner from adjacent tools:
47
47
 
48
48
  - **Curation is the work.** The methodology is the product, not an afterthought. Tools that auto-generate context bundles produce mediocre results because they skip the judgment step. Liner is structured around making that judgment easier.
49
49
  - **Portable artifacts.** Mixtape folders are plain text — YAML and Markdown. They can be edited by hand, generated by tools, shared in repositories, and forked into derivatives. Nothing is locked into a platform.
50
- - **No hosted backend.** Liner doesn't run a service. The CLI runs locally. The library is a static repository. The website is a static site. No accounts, no servers, no infrastructure that can disappear.
51
- - **Two modes, same architecture.** Quick mode runs the methodology automatically; methodology mode runs it with substantive curator involvement. Same files, same format, different intensity. The library accepts methodology-mode mixtapes; personal use is whatever the curator wants.
50
+ - **No hosted backend.** Liner doesn't run a service. The CLI runs locally. The planned library will be a static repository. The website is a static site. No accounts, no servers, no infrastructure that can disappear.
51
+ - **Two modes, same architecture.** Quick mode runs the methodology automatically; methodology mode runs it with substantive curator involvement. Same files, same format, different intensity. The planned library will accept methodology-mode mixtapes; personal use is whatever the curator wants.
52
52
  - **Multiple surfaces, one methodology.** The same curation process applies whether the user is in the terminal, in a Claude conversation, or driving an agent. The methodology document is the source of truth; everything else implements it.
53
53
 
54
54
  ## How the pieces fit together
55
55
 
56
56
  - The **methodology** ([CURATION.md](./CURATION.md)) defines how to curate well.
57
57
  - The **mixtape format** ([MIXTAPE-FORMAT.md](./MIXTAPE-FORMAT.md)) defines what a mixtape folder contains and how `tape.yaml` is structured.
58
- - The **platform** ([PLATFORM.md](./PLATFORM.md)) defines how the Liner project specifically operates — the library, the contribution process, the boundaries.
59
- - The **tools** (CLI, TUI, skill, MCP server) implement the methodology and consume the format.
58
+ - The **platform** ([PLATFORM.md](./PLATFORM.md)) defines how the Liner project specifically operates — implemented surfaces, planned surfaces, the future library, the contribution process, and the boundaries.
59
+ - The **tools** (CLI, Go TUI, skill, and planned MCP server) implement the methodology and consume the format.
60
60
 
61
61
  A curator who learns the methodology can apply it with or without Liner's tools. A curator using Liner's tools can produce mixtapes that exist outside the Liner ecosystem. The methodology, the format, and the tools compose without locking into each other.
62
62
 
63
63
  ## Project status
64
64
 
65
- Active development. The CLI and TUI are both functional and published on npm (current release v0.5.5, Mac, Linux, and Windows x64). Both support the full v1.1 tape format — `youtube`, `web`, and `local_file` sources, with optional Playwright-backed JavaScript rendering for sites that need it (`liner setup-js`, surfaced by the TUI during onboarding and compile warnings). The TUI now treats compilation as the completion milestone and opens existing compile results instead of rerunning by default. The library is empty pending its first methodology-mode entries. The `curating-mixtapes` skill ships inside the TUI package; the MCP server is planned. Maintained as a side project — see [PLATFORM.md](./PLATFORM.md) for the maintenance contract.
65
+ Active development. The CLI and Go TUI are both functional and published on npm (current release v1.0.0, Mac, Linux, and Windows x64). They support the current tape format — `youtube`, `web`, `local_file`, and `skill` sources, with optional Playwright-backed JavaScript rendering for sites that need it (`liner setup-js`, surfaced by the TUI during onboarding and compile warnings). The TUI treats compilation as the corpus-ready milestone, opens existing compile results instead of rerunning by default, validates Phase 1 framing before source discovery can proceed, and creates an Operating Layer with `LINER.md`, root `SKILL.md`, and `liner.yaml`. The public library and MCP server are planned. The `curating-mixtapes` skill ships inside the TUI package. Maintained as a side project — see [PLATFORM.md](./PLATFORM.md) for the maintenance contract.
66
66
 
67
67
  ## License
68
68