@andespindola/brainlink 0.1.0-beta.31 → 0.1.0-beta.33

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
@@ -553,6 +553,8 @@ blink server --host 127.0.0.1 --port 4321 --watch
553
553
  ```
554
554
 
555
555
  By default, the server uses `$HOME/.brainlink/vault`. Pass `--vault ./vault` only when you want to inspect a custom vault.
556
+ By default, `blink server` tries to open the graph in a dedicated app window (`--app=<url>` on compatible browsers).
557
+ If app-window launch is unavailable, it falls back to the default browser. Use `--no-open` to keep it headless.
556
558
 
557
559
  The graph UI shows:
558
560
 
@@ -838,9 +840,12 @@ Watches Markdown files and rebuilds the index when notes change.
838
840
  ```bash
839
841
  blink server --watch
840
842
  blink server --vault ./vault --watch
843
+ blink server --vault ./vault --watch --no-open
841
844
  ```
842
845
 
843
846
  Starts the local read-only graph UI and HTTP API.
847
+ By default, it tries to open a dedicated app window for the graph URL and falls back to browser open when app-window mode is unavailable.
848
+ Use `--no-open` to skip that behavior.
844
849
 
845
850
  The HTTP server only binds to loopback hosts such as `127.0.0.1`, `localhost` or `::1`.
846
851
 
@@ -1,6 +1,9 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { mkdir, writeFile } from 'node:fs/promises';
3
+ import { existsSync } from 'node:fs';
3
4
  import { dirname, relative, resolve } from 'node:path';
5
+ import { platform } from 'node:os';
6
+ import { spawn } from 'node:child_process';
4
7
  import { addNote } from '../../application/add-note.js';
5
8
  import { buildContextPackage } from '../../application/build-context.js';
6
9
  import { importLegacySqliteDatabase } from '../../application/import-legacy-sqlite.js';
@@ -24,6 +27,68 @@ const resolveAddContent = (options) => {
24
27
  }
25
28
  return readFileSync(options.contentFile, 'utf8');
26
29
  };
30
+ const spawnDetached = (command, args) => {
31
+ try {
32
+ const child = spawn(command, args, { detached: true, stdio: 'ignore' });
33
+ child.unref();
34
+ return true;
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ };
40
+ const openGraphInAppWindow = (url) => {
41
+ if (platform() === 'darwin') {
42
+ const macCandidates = [
43
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
44
+ '/Applications/Chromium.app/Contents/MacOS/Chromium',
45
+ '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'
46
+ ]
47
+ .filter((candidate) => existsSync(candidate))
48
+ .map((binary) => ({ binary, args: [`--app=${url}`, '--new-window'] }));
49
+ for (const candidate of macCandidates) {
50
+ if (spawnDetached(candidate.binary, candidate.args)) {
51
+ return true;
52
+ }
53
+ }
54
+ return false;
55
+ }
56
+ if (platform() === 'win32') {
57
+ const appArgument = `--app=${url}`;
58
+ return (spawnDetached('cmd', ['/c', 'start', '', 'chrome', appArgument, '--new-window']) ||
59
+ spawnDetached('cmd', ['/c', 'start', '', 'msedge', appArgument, '--new-window']) ||
60
+ spawnDetached('cmd', ['/c', 'start', '', 'chromium', appArgument, '--new-window']));
61
+ }
62
+ const appArgument = `--app=${url}`;
63
+ return (spawnDetached('google-chrome', [appArgument, '--new-window']) ||
64
+ spawnDetached('chromium-browser', [appArgument, '--new-window']) ||
65
+ spawnDetached('chromium', [appArgument, '--new-window']) ||
66
+ spawnDetached('microsoft-edge', [appArgument, '--new-window']) ||
67
+ spawnDetached('microsoft-edge-stable', [appArgument, '--new-window']));
68
+ };
69
+ const openUrlInBrowser = (url) => {
70
+ const openDisabled = process.env.BRAINLINK_NO_BROWSER === '1' ||
71
+ process.env.BRAINLINK_NO_BROWSER === 'true' ||
72
+ process.env.CI === 'true';
73
+ if (openDisabled) {
74
+ return { opened: false, mode: 'none' };
75
+ }
76
+ if (openGraphInAppWindow(url)) {
77
+ return { opened: true, mode: 'app-window' };
78
+ }
79
+ try {
80
+ if (platform() === 'darwin') {
81
+ return { opened: spawnDetached('open', [url]), mode: 'browser' };
82
+ }
83
+ if (platform() === 'win32') {
84
+ return { opened: spawnDetached('cmd', ['/c', 'start', '', url]), mode: 'browser' };
85
+ }
86
+ return { opened: spawnDetached('xdg-open', [url]), mode: 'browser' };
87
+ }
88
+ catch {
89
+ return { opened: false, mode: 'none' };
90
+ }
91
+ };
27
92
  export const registerWriteCommands = (program) => {
28
93
  program
29
94
  .command('init')
@@ -213,6 +278,7 @@ export const registerWriteCommands = (program) => {
213
278
  .option('-h, --host <host>', 'server host', '127.0.0.1')
214
279
  .option('-p, --port <port>', 'server port', '4321')
215
280
  .option('--no-index', 'skip indexing before starting the server')
281
+ .option('--no-open', 'do not open the graph UI in the default browser')
216
282
  .option('-w, --watch', 'watch markdown files and reindex on changes')
217
283
  .option('--json', 'print machine-readable JSON')
218
284
  .description('start a local web UI for the knowledge graph')
@@ -225,7 +291,20 @@ export const registerWriteCommands = (program) => {
225
291
  shouldIndex: options.index,
226
292
  shouldWatch: Boolean(options.watch)
227
293
  });
228
- print(options.json, { url: server.url, watch: Boolean(options.watch), readonly: true }, () => `Brainlink graph server running at ${server.url}`);
294
+ const openResult = options.open !== false ? openUrlInBrowser(server.url) : { opened: false, mode: 'none' };
295
+ print(options.json, {
296
+ url: server.url,
297
+ watch: Boolean(options.watch),
298
+ readonly: true,
299
+ openedUi: openResult.opened,
300
+ openMode: openResult.mode
301
+ }, () => `Brainlink graph server running at ${server.url}${openResult.opened
302
+ ? openResult.mode === 'app-window'
303
+ ? ' (opened in dedicated app window)'
304
+ : ' (opened in browser)'
305
+ : options.open === false
306
+ ? ' (auto-open disabled)'
307
+ : ''}`);
229
308
  });
230
309
  program
231
310
  .command('quickstart')
@@ -536,9 +536,12 @@ shared: 30 documents
536
536
  ```bash
537
537
  blink server --host 127.0.0.1 --port 4321
538
538
  blink server --vault ./vault --host 127.0.0.1 --port 4321
539
+ blink server --vault ./vault --host 127.0.0.1 --port 4321 --no-open
539
540
  ```
540
541
 
541
542
  This starts a local frontend for inspecting the knowledge graph.
543
+ By default it tries to open the graph in a dedicated app window and falls back to the default browser when app-window mode is unavailable.
544
+ Use `--no-open` to keep the server headless.
542
545
 
543
546
  Without `--vault`, the graph UI serves `$HOME/.brainlink/vault`.
544
547
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.31",
3
+ "version": "0.1.0-beta.33",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",