sourceloop 0.1.1

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 (173) hide show
  1. package/README.md +401 -0
  2. package/dist/commands/attach.d.ts +2 -0
  3. package/dist/commands/attach.js +103 -0
  4. package/dist/commands/attach.js.map +1 -0
  5. package/dist/commands/auth.d.ts +2 -0
  6. package/dist/commands/auth.js +33 -0
  7. package/dist/commands/auth.js.map +1 -0
  8. package/dist/commands/chrome.d.ts +2 -0
  9. package/dist/commands/chrome.js +30 -0
  10. package/dist/commands/chrome.js.map +1 -0
  11. package/dist/commands/compose.d.ts +2 -0
  12. package/dist/commands/compose.js +14 -0
  13. package/dist/commands/compose.js.map +1 -0
  14. package/dist/commands/doctor.d.ts +2 -0
  15. package/dist/commands/doctor.js +15 -0
  16. package/dist/commands/doctor.js.map +1 -0
  17. package/dist/commands/import-latest.d.ts +2 -0
  18. package/dist/commands/import-latest.js +42 -0
  19. package/dist/commands/import-latest.js.map +1 -0
  20. package/dist/commands/ingest.d.ts +2 -0
  21. package/dist/commands/ingest.js +14 -0
  22. package/dist/commands/ingest.js.map +1 -0
  23. package/dist/commands/init.d.ts +2 -0
  24. package/dist/commands/init.js +24 -0
  25. package/dist/commands/init.js.map +1 -0
  26. package/dist/commands/notebook-bind.d.ts +2 -0
  27. package/dist/commands/notebook-bind.js +39 -0
  28. package/dist/commands/notebook-bind.js.map +1 -0
  29. package/dist/commands/notebook-create.d.ts +2 -0
  30. package/dist/commands/notebook-create.js +39 -0
  31. package/dist/commands/notebook-create.js.map +1 -0
  32. package/dist/commands/notebook-import.d.ts +2 -0
  33. package/dist/commands/notebook-import.js +39 -0
  34. package/dist/commands/notebook-import.js.map +1 -0
  35. package/dist/commands/notebook-source.d.ts +2 -0
  36. package/dist/commands/notebook-source.js +71 -0
  37. package/dist/commands/notebook-source.js.map +1 -0
  38. package/dist/commands/plan.d.ts +9 -0
  39. package/dist/commands/plan.js +59 -0
  40. package/dist/commands/plan.js.map +1 -0
  41. package/dist/commands/run.d.ts +2 -0
  42. package/dist/commands/run.js +76 -0
  43. package/dist/commands/run.js.map +1 -0
  44. package/dist/commands/status.d.ts +2 -0
  45. package/dist/commands/status.js +15 -0
  46. package/dist/commands/status.js.map +1 -0
  47. package/dist/commands/topic.d.ts +2 -0
  48. package/dist/commands/topic.js +53 -0
  49. package/dist/commands/topic.js.map +1 -0
  50. package/dist/core/attach/launch-managed-chrome.d.ts +27 -0
  51. package/dist/core/attach/launch-managed-chrome.js +136 -0
  52. package/dist/core/attach/launch-managed-chrome.js.map +1 -0
  53. package/dist/core/attach/manage-targets.d.ts +49 -0
  54. package/dist/core/attach/manage-targets.js +179 -0
  55. package/dist/core/attach/manage-targets.js.map +1 -0
  56. package/dist/core/ingest/frontmatter.d.ts +4 -0
  57. package/dist/core/ingest/frontmatter.js +30 -0
  58. package/dist/core/ingest/frontmatter.js.map +1 -0
  59. package/dist/core/ingest/html-to-markdown.d.ts +5 -0
  60. package/dist/core/ingest/html-to-markdown.js +53 -0
  61. package/dist/core/ingest/html-to-markdown.js.map +1 -0
  62. package/dist/core/ingest/ingest-source.d.ts +11 -0
  63. package/dist/core/ingest/ingest-source.js +115 -0
  64. package/dist/core/ingest/ingest-source.js.map +1 -0
  65. package/dist/core/notebooklm/adapter.d.ts +17 -0
  66. package/dist/core/notebooklm/adapter.js +2 -0
  67. package/dist/core/notebooklm/adapter.js.map +1 -0
  68. package/dist/core/notebooklm/auth.d.ts +30 -0
  69. package/dist/core/notebooklm/auth.js +105 -0
  70. package/dist/core/notebooklm/auth.js.map +1 -0
  71. package/dist/core/notebooklm/browser-agent-adapter.d.ts +21 -0
  72. package/dist/core/notebooklm/browser-agent-adapter.js +37 -0
  73. package/dist/core/notebooklm/browser-agent-adapter.js.map +1 -0
  74. package/dist/core/notebooklm/browser-agent.d.ts +121 -0
  75. package/dist/core/notebooklm/browser-agent.js +1604 -0
  76. package/dist/core/notebooklm/browser-agent.js.map +1 -0
  77. package/dist/core/notebooklm/config.d.ts +20 -0
  78. package/dist/core/notebooklm/config.js +133 -0
  79. package/dist/core/notebooklm/config.js.map +1 -0
  80. package/dist/core/notebooklm/fixture-adapter.d.ts +13 -0
  81. package/dist/core/notebooklm/fixture-adapter.js +32 -0
  82. package/dist/core/notebooklm/fixture-adapter.js.map +1 -0
  83. package/dist/core/notebooklm/response-extraction.d.ts +23 -0
  84. package/dist/core/notebooklm/response-extraction.js +348 -0
  85. package/dist/core/notebooklm/response-extraction.js.map +1 -0
  86. package/dist/core/notebooks/bind-notebook.d.ts +21 -0
  87. package/dist/core/notebooks/bind-notebook.js +95 -0
  88. package/dist/core/notebooks/bind-notebook.js.map +1 -0
  89. package/dist/core/notebooks/manage-managed-notebooks.d.ts +70 -0
  90. package/dist/core/notebooks/manage-managed-notebooks.js +491 -0
  91. package/dist/core/notebooks/manage-managed-notebooks.js.map +1 -0
  92. package/dist/core/notebooks/manage-notebook-source-manifests.d.ts +25 -0
  93. package/dist/core/notebooks/manage-notebook-source-manifests.js +127 -0
  94. package/dist/core/notebooks/manage-notebook-source-manifests.js.map +1 -0
  95. package/dist/core/operator/workspace-operator.d.ts +82 -0
  96. package/dist/core/operator/workspace-operator.js +610 -0
  97. package/dist/core/operator/workspace-operator.js.map +1 -0
  98. package/dist/core/outputs/compose-run.d.ts +11 -0
  99. package/dist/core/outputs/compose-run.js +98 -0
  100. package/dist/core/outputs/compose-run.js.map +1 -0
  101. package/dist/core/runs/load-artifacts.d.ts +14 -0
  102. package/dist/core/runs/load-artifacts.js +51 -0
  103. package/dist/core/runs/load-artifacts.js.map +1 -0
  104. package/dist/core/runs/question-planner.d.ts +20 -0
  105. package/dist/core/runs/question-planner.js +276 -0
  106. package/dist/core/runs/question-planner.js.map +1 -0
  107. package/dist/core/runs/render-run-note.d.ts +13 -0
  108. package/dist/core/runs/render-run-note.js +111 -0
  109. package/dist/core/runs/render-run-note.js.map +1 -0
  110. package/dist/core/runs/run-qa.d.ts +28 -0
  111. package/dist/core/runs/run-qa.js +393 -0
  112. package/dist/core/runs/run-qa.js.map +1 -0
  113. package/dist/core/topics/manage-topics.d.ts +27 -0
  114. package/dist/core/topics/manage-topics.js +314 -0
  115. package/dist/core/topics/manage-topics.js.map +1 -0
  116. package/dist/core/vault/notes.d.ts +29 -0
  117. package/dist/core/vault/notes.js +147 -0
  118. package/dist/core/vault/notes.js.map +1 -0
  119. package/dist/core/vault/paths.d.ts +31 -0
  120. package/dist/core/vault/paths.js +44 -0
  121. package/dist/core/vault/paths.js.map +1 -0
  122. package/dist/core/workspace/bootstrap.d.ts +16 -0
  123. package/dist/core/workspace/bootstrap.js +443 -0
  124. package/dist/core/workspace/bootstrap.js.map +1 -0
  125. package/dist/core/workspace/constants.d.ts +3 -0
  126. package/dist/core/workspace/constants.js +16 -0
  127. package/dist/core/workspace/constants.js.map +1 -0
  128. package/dist/core/workspace/init-workspace.d.ts +15 -0
  129. package/dist/core/workspace/init-workspace.js +86 -0
  130. package/dist/core/workspace/init-workspace.js.map +1 -0
  131. package/dist/core/workspace/load-workspace.d.ts +6 -0
  132. package/dist/core/workspace/load-workspace.js +51 -0
  133. package/dist/core/workspace/load-workspace.js.map +1 -0
  134. package/dist/core/workspace/schema.d.ts +19 -0
  135. package/dist/core/workspace/schema.js +19 -0
  136. package/dist/core/workspace/schema.js.map +1 -0
  137. package/dist/index.d.ts +2 -0
  138. package/dist/index.js +41 -0
  139. package/dist/index.js.map +1 -0
  140. package/dist/lib/cli-output.d.ts +2 -0
  141. package/dist/lib/cli-output.js +7 -0
  142. package/dist/lib/cli-output.js.map +1 -0
  143. package/dist/lib/obsidian.d.ts +4 -0
  144. package/dist/lib/obsidian.js +23 -0
  145. package/dist/lib/obsidian.js.map +1 -0
  146. package/dist/lib/slugify.d.ts +1 -0
  147. package/dist/lib/slugify.js +10 -0
  148. package/dist/lib/slugify.js.map +1 -0
  149. package/dist/lib/write-json.d.ts +1 -0
  150. package/dist/lib/write-json.js +5 -0
  151. package/dist/lib/write-json.js.map +1 -0
  152. package/dist/schemas/attach.d.ts +118 -0
  153. package/dist/schemas/attach.js +33 -0
  154. package/dist/schemas/attach.js.map +1 -0
  155. package/dist/schemas/managed-notebook.d.ts +47 -0
  156. package/dist/schemas/managed-notebook.js +30 -0
  157. package/dist/schemas/managed-notebook.js.map +1 -0
  158. package/dist/schemas/notebook-source.d.ts +31 -0
  159. package/dist/schemas/notebook-source.js +23 -0
  160. package/dist/schemas/notebook-source.js.map +1 -0
  161. package/dist/schemas/notebook.d.ts +26 -0
  162. package/dist/schemas/notebook.js +18 -0
  163. package/dist/schemas/notebook.js.map +1 -0
  164. package/dist/schemas/run.d.ts +169 -0
  165. package/dist/schemas/run.js +80 -0
  166. package/dist/schemas/run.js.map +1 -0
  167. package/dist/schemas/source.d.ts +18 -0
  168. package/dist/schemas/source.js +13 -0
  169. package/dist/schemas/source.js.map +1 -0
  170. package/dist/schemas/topic.d.ts +37 -0
  171. package/dist/schemas/topic.js +25 -0
  172. package/dist/schemas/topic.js.map +1 -0
  173. package/package.json +44 -0
package/README.md ADDED
@@ -0,0 +1,401 @@
1
+ # SourceLoop
2
+
3
+ **A local-first research runtime for Codex, Claude Code, and Gemini CLI.**
4
+
5
+ SourceLoop helps AI tools work through NotebookLM with a managed browser, repeatable question planning, and local Markdown archives.
6
+
7
+ It is built for a simple idea:
8
+
9
+ - use AI for research
10
+ - keep grounding in real sources
11
+ - keep the workflow reusable
12
+ - keep human ownership over judgment and expression
13
+
14
+ SourceLoop is not a NotebookLM replacement. It is the workflow and archive layer around NotebookLM-based research.
15
+
16
+ ## Why This Exists
17
+
18
+ Most research workflows break in three places:
19
+
20
+ - **weak questions**
21
+ - the model can answer well only if someone asks the right questions
22
+ - **untrusted answers**
23
+ - generic AI answers drift, summarize poorly, or hallucinate beyond the source base
24
+ - **no durable archive**
25
+ - browser-only Q&A disappears into a tab and becomes hard to reuse later
26
+
27
+ SourceLoop exists to make that workflow repeatable.
28
+
29
+ It gives your AI tool:
30
+
31
+ - a topic model
32
+ - a managed NotebookLM browser path
33
+ - notebook creation or binding
34
+ - source import and source declaration
35
+ - planned question batches
36
+ - local answer and citation archives
37
+
38
+ ## The IPO Model
39
+
40
+ SourceLoop follows a simple **Input -> Process -> Output** model.
41
+
42
+ ### Input
43
+
44
+ - local notes, files, transcripts, and URLs
45
+ - a NotebookLM notebook
46
+ - a managed research browser session
47
+
48
+ ### Process
49
+
50
+ - plan better questions
51
+ - run NotebookLM Q&A against grounded sources
52
+ - capture answers and citations into local files
53
+
54
+ ### Output
55
+
56
+ - a reusable Markdown research archive
57
+ - question batches you can rerun or extend
58
+ - material that can become memos, articles, scripts, decks, or teaching assets
59
+
60
+ In short:
61
+
62
+ ```text
63
+ Sources
64
+ -> NotebookLM
65
+ -> Planned questions
66
+ -> Grounded answers with citations
67
+ -> Local Markdown archive
68
+ -> Your own memo, deck, article, or presentation
69
+ ```
70
+
71
+ ## What SourceLoop Gives Your AI Tool
72
+
73
+ - topic-first research workspaces
74
+ - managed Chrome setup for NotebookLM work
75
+ - notebook create or notebook bind flows
76
+ - source import for local files and supported remote URLs
77
+ - source declaration when material already exists in NotebookLM
78
+ - default 10-question planning
79
+ - full-batch execution by default unless you explicitly want a partial run
80
+ - local Markdown storage for runs, answers, and citations
81
+
82
+ ## Why NotebookLM
83
+
84
+ SourceLoop uses NotebookLM as the answer engine because NotebookLM is already strong at document-grounded research.
85
+
86
+ - **Gemini-powered preprocessing**
87
+ - upload source material once and work from prepared source context
88
+ - **natural-language Q&A**
89
+ - go beyond keyword lookup into explanation, synthesis, and comparison
90
+ - **multi-source reasoning**
91
+ - connect ideas across a notebook worth of source material
92
+ - **built-in citations**
93
+ - answers come with traceable source references
94
+ - **no separate RAG infrastructure**
95
+ - no vector database, embedding pipeline, chunking strategy, or retrieval tuning stack to maintain
96
+
97
+ SourceLoop does not try to replace those strengths. It makes them operational for AI tools.
98
+
99
+ ## Markdown-First Output
100
+ ![alt text](docs/graph-sample.png)
101
+ SourceLoop is designed so the result does not disappear into a browser tab.
102
+
103
+ Every run is captured as local Markdown artifacts:
104
+
105
+ - planned questions
106
+ - NotebookLM answers
107
+ - citation-backed notes
108
+ - run-level archives
109
+
110
+ This makes the output:
111
+
112
+ - **easy to reuse**
113
+ - turn answers into memos, decks, scripts, articles, or teaching material
114
+ - **easy to search**
115
+ - keep everything in local files instead of browser history
116
+ - **easy to extend**
117
+ - use previous runs as source material for later research
118
+ - **easy to organize**
119
+ - keep an Obsidian-friendly archive that can grow into a real knowledge base
120
+ - **easy to version**
121
+ - fit naturally into Git-based workflows
122
+
123
+ SourceLoop does not just help you get answers. It helps you keep them in a form you can build on.
124
+
125
+ ## Security Model
126
+
127
+ SourceLoop recommends using a dedicated SourceLoop-managed Chrome profile for research work.
128
+
129
+ - do not use your normal personal Chrome profile as the preferred research path
130
+ - `sourceloop chrome launch` creates a separate research browser profile
131
+ - after signing in to Google and NotebookLM once, you can keep reusing that research session
132
+ - this keeps research activity separate from your personal cookies, tabs, and extension context
133
+ - if the preferred SourceLoop browser is unavailable, another Chrome session can still be used, but only after explicit user approval
134
+
135
+ In short:
136
+
137
+ - preferred path: a dedicated research browser
138
+ - fallback path: another existing Chrome session
139
+ - fallback use requires explicit user confirmation
140
+
141
+ ## Installation
142
+
143
+ ```bash
144
+ # Install the CLI globally
145
+ npm install -g sourceloop
146
+
147
+ # Go to your project
148
+ cd /path/to/your/project
149
+
150
+ # Initialize SourceLoop
151
+ sourceloop init
152
+
153
+ # Install project-local AI bootstrap
154
+ sourceloop init --ai codex
155
+ sourceloop init --ai claude
156
+ sourceloop init --ai gemini
157
+ ```
158
+
159
+ ## Usage
160
+
161
+ Use SourceLoop through your AI tool in plain language.
162
+
163
+ ### Start New Research
164
+
165
+ You can say:
166
+
167
+ ```text
168
+ Start research on attention in transformers.
169
+ ```
170
+
171
+ Or:
172
+
173
+ ```text
174
+ Start research on attention in transformers and use this video first:
175
+ https://www.youtube.com/watch?v=eMlx5fFNoYc
176
+ ```
177
+
178
+ SourceLoop helps the AI tool:
179
+
180
+ - prepare a managed research browser
181
+ - create a topic and notebook
182
+ - import the provided sources
183
+ - plan a question batch
184
+ - archive answers and citations locally
185
+
186
+ ### Continue Existing Research
187
+
188
+ You can say:
189
+
190
+ ```text
191
+ Continue research from this NotebookLM notebook:
192
+ https://notebooklm.google.com/notebook/<real-notebook-id>
193
+ ```
194
+
195
+ SourceLoop helps the AI tool:
196
+
197
+ - bind the existing notebook
198
+ - inspect the current research state
199
+ - continue planning or running from there
200
+
201
+ ### If You Prefer Direct CLI
202
+
203
+ Use the Golden Path below.
204
+
205
+ ## Golden Path
206
+
207
+ ```bash
208
+ mkdir my-research-workspace
209
+ cd my-research-workspace
210
+ sourceloop init --ai codex
211
+
212
+ sourceloop status --json
213
+ sourceloop doctor --json
214
+
215
+ sourceloop topic create --name "AI agents market" --json
216
+
217
+ # visible setup step: launch a dedicated research browser,
218
+ # sign in yourself, then validate NotebookLM home access
219
+ sourceloop chrome launch --name work-chrome
220
+ sourceloop attach validate attach-work-chrome
221
+
222
+ sourceloop notebook-create \
223
+ --name "AI Agents" \
224
+ --topic-id topic-ai-agents-market \
225
+ --attach-target attach-work-chrome \
226
+ --json
227
+
228
+ # read the returned binding id from JSON or status output
229
+ sourceloop ingest ./research-notes.md --topic topic-ai-agents-market
230
+
231
+ sourceloop notebook-import \
232
+ --notebook <managed-notebook-binding-id> \
233
+ --source-id <source-id> \
234
+ --json
235
+
236
+ sourceloop notebook-import \
237
+ --notebook <managed-notebook-binding-id> \
238
+ --url "https://youtube.com/watch?v=..." \
239
+ --json
240
+
241
+ sourceloop plan topic-ai-agents-market --max-questions 10 --json
242
+ sourceloop run <run-id> --json
243
+ ```
244
+
245
+ ## Operator Defaults
246
+
247
+ If you use SourceLoop through Codex, Claude Code, Gemini CLI, or another local AI tool, these are the intended defaults:
248
+
249
+ - start with `sourceloop status --json` and `sourceloop doctor --json`
250
+ - ask for the topic first if the user did not provide one
251
+ - if the user provided a topic but not sources, ask which sources to use before collecting or importing anything
252
+ - mention that planning defaults to 10 questions unless the user wants another count
253
+ - prefer `sourceloop chrome launch` over attaching to an unrelated Chrome profile
254
+ - treat `sourceloop attach validate <target>` as NotebookLM home validation
255
+ - use `--notebook-url` only when you specifically need to validate an existing notebook detail page
256
+ - after initial setup, prefer hidden notebook actions by default and use `--show-browser` only for debugging or when the user wants to watch
257
+ - if the plan was created for 10 questions and the user did not ask for a partial pass, run the planned batch end to end
258
+ - use `--limit` only for explicit partial runs
259
+ - tell the user briefly that NotebookLM actions can take a bit before waiting
260
+ - if the wait becomes long, ask whether to keep waiting or report the current state
261
+ - if the preferred SourceLoop browser is unavailable, ask whether to continue with the current Chrome or switch back to the SourceLoop browser
262
+
263
+ ## Existing Notebook Path
264
+
265
+ If the notebook already exists and already has sources loaded in NotebookLM:
266
+
267
+ ```bash
268
+ sourceloop notebook-bind \
269
+ --name "AI Agents" \
270
+ --topic-id topic-ai-agents-market \
271
+ --url "https://notebooklm.google.com/notebook/<real-notebook-id>" \
272
+ --attach-target attach-work-chrome \
273
+ --json
274
+
275
+ sourceloop notebook-source declare \
276
+ --topic-id topic-ai-agents-market \
277
+ --notebook <notebook-binding-id> \
278
+ --kind mixed \
279
+ --title "AI agents market source set" \
280
+ --json
281
+ ```
282
+
283
+ ## Partial Runs and Backfills
284
+
285
+ Use partial execution only when you explicitly want it.
286
+
287
+ ```bash
288
+ sourceloop run <run-id> --limit 2 --json
289
+ sourceloop run <run-id> --from-question <question-id> --json
290
+ sourceloop run <run-id> --question-id <question-id> --json
291
+ sourceloop import-latest <run-id> --question-id <question-id> --show-browser
292
+ ```
293
+
294
+ ## Machine-Readable Workflow
295
+
296
+ Core operator commands support `--json`:
297
+
298
+ - `topic create|list|show`
299
+ - `notebook-create`
300
+ - `notebook-bind`
301
+ - `notebook-import`
302
+ - `notebook-source declare|list|show`
303
+ - `plan`
304
+ - `run`
305
+ - `status`
306
+ - `doctor`
307
+
308
+ Example:
309
+
310
+ ```bash
311
+ sourceloop status --json
312
+ sourceloop doctor --json
313
+ sourceloop topic create --name "AI agents market" --json
314
+ sourceloop chrome launch --name work-chrome
315
+ sourceloop attach validate attach-work-chrome
316
+ sourceloop notebook-create --name "AI Agents" --topic-id topic-ai-agents-market --attach-target attach-work-chrome --json
317
+ sourceloop notebook-import --notebook <managed-notebook-binding-id> --url "https://youtube.com/watch?v=..." --json
318
+ sourceloop plan topic-ai-agents-market --max-questions 10 --json
319
+ sourceloop run <run-id> --json
320
+ ```
321
+
322
+ ## Vault Layout
323
+
324
+ ```text
325
+ vault/
326
+ ├─ chrome-targets/
327
+ ├─ notebook-imports/
328
+ ├─ notebook-setups/
329
+ ├─ notebooks/
330
+ ├─ notebook-sources/
331
+ ├─ runs/
332
+ ├─ sources/
333
+ └─ topics/
334
+ ```
335
+
336
+ Main result:
337
+
338
+ ```text
339
+ vault/runs/<run-id>/
340
+ ├─ index.md
341
+ ├─ questions.md
342
+ └─ exchanges/
343
+ ├─ q01....md
344
+ ├─ q02....md
345
+ └─ ...
346
+ ```
347
+
348
+ ## Project Boundary
349
+
350
+ SourceLoop stops at research packaging and Q&A archive creation.
351
+
352
+ - humans choose the topic
353
+ - NotebookLM answers from the bound notebook
354
+ - SourceLoop stores the research trace
355
+ - humans turn that archive into slides, scripts, memos, lessons, or deliverables
356
+
357
+ This is the intended split:
358
+
359
+ - use AI for research
360
+ - use humans for judgment and expression
361
+
362
+ ## Current Status
363
+
364
+ Current focus:
365
+
366
+ - topic-first NotebookLM workflow
367
+ - managed notebook setup workflow
368
+ - attached Chrome execution
369
+ - Obsidian-friendly Markdown archive
370
+
371
+ Still rough around:
372
+
373
+ - NotebookLM UI selector stability
374
+ - citation capture fidelity
375
+ - automatic NotebookLM source introspection beyond operator-declared manifests
376
+
377
+ ## Development
378
+
379
+ ```bash
380
+ pnpm install
381
+ pnpm build
382
+ pnpm test
383
+ ```
384
+
385
+ For local CLI usage:
386
+
387
+ ```bash
388
+ pnpm install
389
+ pnpm build
390
+ pnpm link --global
391
+
392
+ sourceloop init --ai codex
393
+ sourceloop --help
394
+ ```
395
+
396
+ Reference docs:
397
+
398
+ - [Architecture](./docs/architecture.md)
399
+ - [LLM Playbook](./docs/llm-playbook.md)
400
+ - [Tasks](./docs/tasks.md)
401
+ - [Test Plan](./docs/test-plan.md)
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const attachCommand: Command;
@@ -0,0 +1,103 @@
1
+ import { Command } from "commander";
2
+ import { listChromeAttachTargets, loadChromeAttachTarget, registerChromeEndpointTarget, registerChromeProfileTarget, removeChromeAttachTarget, upsertChromeAttachTarget } from "../core/attach/manage-targets.js";
3
+ import { validateChromeAttachTarget } from "../core/notebooklm/browser-agent.js";
4
+ import { chromeProfileIsolationSchema } from "../schemas/attach.js";
5
+ export const attachCommand = new Command("attach").description("Register and inspect attached Chrome targets for NotebookLM execution");
6
+ attachCommand
7
+ .command("profile")
8
+ .description("Register a Chrome profile directory to launch and attach for NotebookLM runs")
9
+ .requiredOption("--name <name>", "attach target name")
10
+ .requiredOption("--profile-dir <path>", "Chrome user data directory that is already signed in")
11
+ .option("--profile-isolation <isolation>", "Chrome profile isolation posture: isolated, unknown, or shared", "unknown")
12
+ .option("--chrome-path <path>", "explicit Google Chrome executable path")
13
+ .option("--port <port>", "preferred remote debugging port for launched Chrome")
14
+ .option("--launch-arg <arg...>", "additional Chrome launch arguments")
15
+ .option("--description <description>", "target description")
16
+ .option("--force", "overwrite an existing attach target with the same id", false)
17
+ .action(async (options) => {
18
+ const result = await registerChromeProfileTarget({
19
+ name: options.name,
20
+ profileDirPath: options.profileDir,
21
+ profileIsolation: chromeProfileIsolationSchema.parse(options.profileIsolation),
22
+ launchArgs: options.launchArg ?? [],
23
+ force: options.force,
24
+ ...(options.chromePath ? { chromeExecutablePath: options.chromePath } : {}),
25
+ ...(options.port ? { remoteDebuggingPort: Number(options.port) } : {}),
26
+ ...(options.description ? { description: options.description } : {})
27
+ });
28
+ process.stdout.write(`Registered attach target ${result.target.id} at ${result.markdownPath}\n`);
29
+ });
30
+ attachCommand
31
+ .command("endpoint")
32
+ .description("Register an existing Chrome remote debugging endpoint for NotebookLM runs")
33
+ .requiredOption("--name <name>", "attach target name")
34
+ .requiredOption("--endpoint <url>", "Chrome remote debugging endpoint, for example http://127.0.0.1:9222")
35
+ .option("--profile-isolation <isolation>", "Chrome profile isolation posture behind the endpoint: isolated, unknown, or shared", "unknown")
36
+ .option("--description <description>", "target description")
37
+ .option("--force", "overwrite an existing attach target with the same id", false)
38
+ .action(async (options) => {
39
+ const result = await registerChromeEndpointTarget({
40
+ name: options.name,
41
+ endpoint: options.endpoint,
42
+ profileIsolation: chromeProfileIsolationSchema.parse(options.profileIsolation),
43
+ force: options.force,
44
+ ...(options.description ? { description: options.description } : {})
45
+ });
46
+ process.stdout.write(`Registered attach target ${result.target.id} at ${result.markdownPath}\n`);
47
+ });
48
+ attachCommand
49
+ .command("list")
50
+ .description("List registered Chrome attach targets")
51
+ .action(async () => {
52
+ const targets = await listChromeAttachTargets();
53
+ if (targets.length === 0) {
54
+ process.stdout.write("No Chrome attach targets registered.\n");
55
+ return;
56
+ }
57
+ for (const target of targets) {
58
+ const summary = target.targetType === "profile" ? target.profileDirPath : target.endpoint;
59
+ process.stdout.write(`${target.id}\t${target.targetType}\t${target.profileIsolation}\t${summary}\n`);
60
+ }
61
+ });
62
+ attachCommand
63
+ .command("show")
64
+ .description("Show one registered Chrome attach target")
65
+ .argument("<target-id>", "attach target id")
66
+ .action(async (targetId) => {
67
+ const { target } = await loadChromeAttachTarget(targetId);
68
+ process.stdout.write(`${JSON.stringify(target, null, 2)}\n`);
69
+ });
70
+ attachCommand
71
+ .command("validate")
72
+ .description("Validate that a Chrome attach target can reach NotebookLM")
73
+ .argument("<target-id>", "attach target id")
74
+ .option("--notebook-url <url>", "NotebookLM notebook URL to preflight")
75
+ .option("--show-browser", "show Chrome while validating a profile attach target", false)
76
+ .action(async (targetId, options) => {
77
+ const { target } = await loadChromeAttachTarget(targetId);
78
+ const result = await validateChromeAttachTarget({
79
+ target,
80
+ ...(options.notebookUrl ? { notebookUrl: options.notebookUrl } : {}),
81
+ showBrowser: options.showBrowser
82
+ });
83
+ if (result.ok) {
84
+ const validatedTarget = {
85
+ ...target,
86
+ notebooklmReadiness: "validated",
87
+ notebooklmValidatedAt: new Date().toISOString()
88
+ };
89
+ await upsertChromeAttachTarget(validatedTarget);
90
+ process.stdout.write(`Attach target ${targetId} is ready for NotebookLM execution.\n`);
91
+ return;
92
+ }
93
+ throw new Error(`[${result.code}] ${result.message}`);
94
+ });
95
+ attachCommand
96
+ .command("remove")
97
+ .description("Remove a registered Chrome attach target")
98
+ .argument("<target-id>", "attach target id")
99
+ .action(async (targetId) => {
100
+ await removeChromeAttachTarget({ targetId });
101
+ process.stdout.write(`Removed attach target ${targetId}\n`);
102
+ });
103
+ //# sourceMappingURL=attach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.js","sourceRoot":"","sources":["../../src/commands/attach.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const authCommand: Command;
@@ -0,0 +1,33 @@
1
+ import { Command } from "commander";
2
+ import { clearNotebookAuth, getNotebookAuthStatus, setupNotebookAuth } from "../core/notebooklm/auth.js";
3
+ export const authCommand = new Command("auth").description("Legacy NotebookLM auth helpers (deprecated: use attach-first workflow instead)");
4
+ authCommand
5
+ .command("setup")
6
+ .description("Legacy login bootstrap for NotebookLM (deprecated; use attach profile/endpoint instead)")
7
+ .option("--profile <profile>", "browser profile alias", "default")
8
+ .option("--timeout-minutes <minutes>", "login timeout in minutes", "10")
9
+ .action(async (options) => {
10
+ process.stderr.write("Warning: auth setup is deprecated. Preferred workflow: sign in to Chrome yourself, register it with `sourceloop attach`, then run NotebookLM batches.\n");
11
+ const status = await setupNotebookAuth({
12
+ profile: options.profile,
13
+ timeoutMinutes: Number(options.timeoutMinutes)
14
+ });
15
+ process.stdout.write(`NotebookLM auth ready for profile ${status.profile} (${status.stateFilePath})\n`);
16
+ });
17
+ authCommand
18
+ .command("status")
19
+ .description("Check legacy NotebookLM authentication status")
20
+ .option("--profile <profile>", "browser profile alias", "default")
21
+ .action(async (options) => {
22
+ const status = await getNotebookAuthStatus({ profile: options.profile });
23
+ process.stdout.write(`${status.profile}: ${status.authenticated ? "authenticated" : "not authenticated"} (${status.stateFilePath})\n`);
24
+ });
25
+ authCommand
26
+ .command("clear")
27
+ .description("Clear legacy NotebookLM authentication state for a profile")
28
+ .option("--profile <profile>", "browser profile alias", "default")
29
+ .action(async (options) => {
30
+ const status = await clearNotebookAuth({ profile: options.profile });
31
+ process.stdout.write(`Cleared NotebookLM auth for profile ${status.profile}\n`);
32
+ });
33
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEzG,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CACxD,gFAAgF,CACjF,CAAC;AAEF,WAAW;KACR,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,yFAAyF,CAAC;KACtG,MAAM,CAAC,qBAAqB,EAAE,uBAAuB,EAAE,SAAS,CAAC;KACjE,MAAM,CAAC,6BAA6B,EAAE,0BAA0B,EAAE,IAAI,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,OAAoD,EAAE,EAAE;IACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,yJAAyJ,CAC1J,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC;QACrC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC;KAC/C,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qCAAqC,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,aAAa,KAAK,CAClF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,WAAW;KACR,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,qBAAqB,EAAE,uBAAuB,EAAE,SAAS,CAAC;KACjE,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;IAC7C,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACzE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,mBAAmB,KAAK,MAAM,CAAC,aAAa,KAAK,CACjH,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,WAAW;KACR,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,4DAA4D,CAAC;KACzE,MAAM,CAAC,qBAAqB,EAAE,uBAAuB,EAAE,SAAS,CAAC;KACjE,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;IAC7C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;AAClF,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const chromeCommand: Command;
@@ -0,0 +1,30 @@
1
+ import { Command } from "commander";
2
+ import { launchManagedChrome } from "../core/attach/launch-managed-chrome.js";
3
+ import { writeJsonOutput, writeTextOutput } from "../lib/cli-output.js";
4
+ export const chromeCommand = new Command("chrome").description("Launch and inspect SourceLoop-managed Chrome browser workflows");
5
+ chromeCommand
6
+ .command("launch")
7
+ .description("Launch a dedicated isolated Chrome research profile and register it as an attach target")
8
+ .option("--name <name>", "managed Chrome launch target name", "research-browser")
9
+ .option("--chrome-path <path>", "explicit Google Chrome executable path")
10
+ .option("--port <port>", "preferred remote debugging port")
11
+ .option("--launch-arg <arg...>", "additional Chrome launch arguments")
12
+ .option("--description <description>", "target description")
13
+ .option("--force", "replace an existing attach target with the same id", false)
14
+ .option("--json", "emit machine-readable JSON", false)
15
+ .action(async (options) => {
16
+ const result = await launchManagedChrome({
17
+ name: options.name,
18
+ ...(options.chromePath ? { chromeExecutablePath: options.chromePath } : {}),
19
+ ...(options.port ? { remoteDebuggingPort: Number(options.port) } : {}),
20
+ ...(options.launchArg ? { launchArgs: options.launchArg } : {}),
21
+ ...(options.description ? { description: options.description } : {}),
22
+ force: options.force
23
+ });
24
+ if (options.json) {
25
+ writeJsonOutput(result);
26
+ return;
27
+ }
28
+ writeTextOutput(`${result.launched ? "Launched" : "Reused"} managed Chrome ${result.target.id} at ${result.endpoint} using ${result.profileDirPath}`);
29
+ });
30
+ //# sourceMappingURL=chrome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../src/commands/chrome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAExE,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAC5D,gEAAgE,CACjE,CAAC;AAEF,aAAa;KACV,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,yFAAyF,CAAC;KACtG,MAAM,CAAC,eAAe,EAAE,mCAAmC,EAAE,kBAAkB,CAAC;KAChF,MAAM,CAAC,sBAAsB,EAAE,wCAAwC,CAAC;KACxE,MAAM,CAAC,eAAe,EAAE,iCAAiC,CAAC;KAC1D,MAAM,CAAC,uBAAuB,EAAE,oCAAoC,CAAC;KACrE,MAAM,CAAC,6BAA6B,EAAE,oBAAoB,CAAC;KAC3D,MAAM,CAAC,SAAS,EAAE,oDAAoD,EAAE,KAAK,CAAC;KAC9E,MAAM,CAAC,QAAQ,EAAE,4BAA4B,EAAE,KAAK,CAAC;KACrD,MAAM,CACL,KAAK,EAAE,OAQN,EAAE,EAAE;IACH,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC;QACvC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,eAAe,CAAC,MAAM,CAAC,CAAC;QACxB,OAAO;IACT,CAAC;IAED,eAAe,CACb,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,mBAAmB,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,MAAM,CAAC,QAAQ,UAAU,MAAM,CAAC,cAAc,EAAE,CACrI,CAAC;AACJ,CAAC,CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const composeCommand: Command;
@@ -0,0 +1,14 @@
1
+ import { Command } from "commander";
2
+ import { composeRun } from "../core/outputs/compose-run.js";
3
+ export const composeCommand = new Command("compose")
4
+ .description("Compose a run archive into an Obsidian-friendly output artifact")
5
+ .argument("<run-id>", "run id to compose")
6
+ .requiredOption("--format <format>", "output format: brief or outline")
7
+ .action(async (runId, options) => {
8
+ const result = await composeRun({
9
+ runId,
10
+ format: options.format
11
+ });
12
+ process.stdout.write(`Composed ${result.artifact.format} at ${result.markdownPath}\n`);
13
+ });
14
+ //# sourceMappingURL=compose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/commands/compose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAE5D,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,iEAAiE,CAAC;KAC9E,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;KACzC,cAAc,CAAC,mBAAmB,EAAE,iCAAiC,CAAC;KACtE,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,OAAwC,EAAE,EAAE;IACxE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;QAC9B,KAAK;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,QAAQ,CAAC,MAAM,OAAO,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC;AACzF,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const doctorCommand: Command;
@@ -0,0 +1,15 @@
1
+ import { Command } from "commander";
2
+ import { buildDoctorReport, formatDoctorReport } from "../core/operator/workspace-operator.js";
3
+ import { writeJsonOutput, writeTextOutput } from "../lib/cli-output.js";
4
+ export const doctorCommand = new Command("doctor")
5
+ .description("Diagnose missing or broken SourceLoop workflow prerequisites")
6
+ .option("--json", "emit machine-readable JSON", false)
7
+ .action(async (options) => {
8
+ const report = await buildDoctorReport();
9
+ if (options.json) {
10
+ writeJsonOutput(report);
11
+ return;
12
+ }
13
+ writeTextOutput(formatDoctorReport(report));
14
+ });
15
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC/F,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAExE,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,QAAQ,EAAE,4BAA4B,EAAE,KAAK,CAAC;KACrD,MAAM,CAAC,KAAK,EAAE,OAA0B,EAAE,EAAE;IAC3C,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IAEzC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,eAAe,CAAC,MAAM,CAAC,CAAC;QACxB,OAAO;IACT,CAAC;IAED,eAAe,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const importLatestCommand: Command;