langflower 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.
package/README.md CHANGED
@@ -57,9 +57,29 @@ hosting a service.
57
57
 
58
58
  ## Quick start
59
59
 
60
- Requires **Node.js 22**. Live agent runs need an OpenAI-compatible
61
- provider in Settings (API keys via `{env:VAR_NAME}`). Simple nodes and
62
- the Fake LLM work without one.
60
+ If you do not want to bother with a terminal, use the **desktop
61
+ launcher**. Pick a project folder, click **Start**, and the editor opens
62
+ in the browser you already have. Several folders can run at once, each
63
+ on its own port. The launcher takes care of missing Node.js and
64
+ Langflower, and checks for Langflower updates for you. It does not
65
+ update itself — download a newer zip when you want a new window.
66
+
67
+ ![Langflower desktop launcher](https://raw.githubusercontent.com/earthdmitriy/langflower/master/docs/img/launcher.png)
68
+
69
+ Download a Windows or macOS zip from
70
+ [GitHub Releases](https://github.com/earthdmitriy/langflower/releases).
71
+ Unpack and run `langflower-launcher.exe` or `langflower-launcher`. It is
72
+ a portable app: no installation. The binary is unsigned, so Windows
73
+ Defender and macOS Gatekeeper might warn. On macOS: right-click the
74
+ file → **Open**. No Linux zip yet. Manual:
75
+ [Desktop launcher](https://github.com/earthdmitriy/langflower/blob/master/docs/public/launcher.md).
76
+
77
+ Langflower does not host a model. Live agent runs need you to **bring
78
+ your own key** (BYOK): add an OpenAI-compatible provider in Settings (gear icon)
79
+ and paste the API key there. Pointing at an environment variable is
80
+ optional. Simple nodes and the Fake LLM work without a key.
81
+
82
+ From a terminal:
63
83
 
64
84
  One-shot OS installers (Node LTS if needed + global `langflower`):
65
85
  [install/](install/) (`windows.ps1`, `linux.sh`, `macos.sh`).
@@ -78,9 +98,9 @@ npm run install-local
78
98
  npx langflower
79
99
  ```
80
100
 
81
- Langflower opens a local UI at `http://127.0.0.1:4010` (or `--port` / the port
82
- in `.langflower/config.json`) for the selected folder. Use `-p` to run several
83
- instances from different folders at once.
101
+ The CLI opens a local UI at `http://127.0.0.1:4010` (or `--port` / the
102
+ port in `.langflower/config.json`) for the selected folder. Use `-p` to
103
+ run several instances from different folders at once.
84
104
 
85
105
  Full walkthrough: [Getting started](https://github.com/earthdmitriy/langflower/blob/master/docs/public/getting-started.md).
86
106
 
@@ -124,6 +144,7 @@ Shipped with the npm package under [`docs/public/`](https://github.com/earthdmit
124
144
 
125
145
  | Want to… | Start here |
126
146
  | -------------------------------- | ---------------------------------------------------------------------------------------------------------- |
147
+ | Start without a terminal | [Desktop launcher](https://github.com/earthdmitriy/langflower/blob/master/docs/public/launcher.md) |
127
148
  | Install and first run | [Getting started](https://github.com/earthdmitriy/langflower/blob/master/docs/public/getting-started.md) |
128
149
  | Understand the product | [Product overview](https://github.com/earthdmitriy/langflower/blob/master/docs/public/product.md) |
129
150
  | Use the canvas and runs | [Using the editor](https://github.com/earthdmitriy/langflower/blob/master/docs/public/using-the-editor.md) |
package/dist/index.js CHANGED
@@ -58487,6 +58487,7 @@ var {
58487
58487
  } = import_index.default;
58488
58488
 
58489
58489
  // packages/cli/dist/start-command.js
58490
+ import { writeSync } from "node:fs";
58490
58491
  import fs23 from "node:fs/promises";
58491
58492
  import path22 from "node:path";
58492
58493
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -80385,6 +80386,11 @@ var parseListenPort = (raw) => {
80385
80386
  }
80386
80387
  return port;
80387
80388
  };
80389
+ var formatReadyLine = (input) => `LANGFLOWER_READY ${JSON.stringify({
80390
+ url: input.url,
80391
+ port: input.port,
80392
+ projectDir: input.projectDir
80393
+ })}`;
80388
80394
  var startProject = async (projectDirArg, opts) => {
80389
80395
  const projectDir = path22.resolve(projectDirArg);
80390
80396
  if (!await hasLangflowerProject(projectDir)) {
@@ -80408,8 +80414,17 @@ var startProject = async (projectDirArg, opts) => {
80408
80414
  console.warn(`Warning: --dev with --port ${String(opts.port)}: ng serve proxy still targets http://127.0.0.1:${String(DEFAULT_PORT)}/ws`);
80409
80415
  }
80410
80416
  } else {
80411
- await open_default(`http://127.0.0.1:${port}`);
80412
- console.log(`Langflower running at http://127.0.0.1:${port}`);
80417
+ const url = `http://127.0.0.1:${port}`;
80418
+ if (opts.noOpen !== true) {
80419
+ await open_default(url);
80420
+ }
80421
+ console.log(`Langflower running at ${url}`);
80422
+ writeSync(1, `${formatReadyLine({
80423
+ url,
80424
+ port,
80425
+ projectDir
80426
+ })}
80427
+ `);
80413
80428
  }
80414
80429
  console.log(`Project: ${projectDir}`);
80415
80430
  };
@@ -80418,6 +80433,7 @@ var runStartAction = async (projectDir, opts) => {
80418
80433
  const port = opts.port !== void 0 ? parseListenPort(opts.port) : void 0;
80419
80434
  await startProject(projectDir, {
80420
80435
  dev: opts.dev === true,
80436
+ noOpen: opts.open === false,
80421
80437
  ...port !== void 0 ? { port } : {}
80422
80438
  });
80423
80439
  } catch (error) {
@@ -80430,9 +80446,14 @@ var PORT_OPTION = [
80430
80446
  "-p, --port <number>",
80431
80447
  "HTTP listen port (overrides .langflower/config.json for this run)"
80432
80448
  ];
80449
+ var NO_OPEN_OPTION = [
80450
+ "--no-open",
80451
+ "Do not open the system browser after listen"
80452
+ ];
80453
+ var applyStartOptions = (command) => command.option("--dev", "Dev mode: API-only server, UI served by ng serve").option(...PORT_OPTION).option(...NO_OPEN_OPTION);
80433
80454
  var registerStartCommand = (program2) => {
80434
- program2.argument("[project-dir]", "Project directory", process.cwd()).option("--dev", "Dev mode: API-only server, UI served by ng serve").option(...PORT_OPTION).action(runStartAction);
80435
- program2.command("start").description("Start Langflower server and open UI in browser (alias)").argument("[project-dir]", "Project directory", process.cwd()).option("--dev", "Dev mode: API-only server, UI served by ng serve").option(...PORT_OPTION).action(runStartAction);
80455
+ applyStartOptions(program2.argument("[project-dir]", "Project directory", process.cwd())).action(runStartAction);
80456
+ applyStartOptions(program2.command("start").description("Start Langflower server and open UI in browser (alias)").argument("[project-dir]", "Project directory", process.cwd())).action(runStartAction);
80436
80457
  };
80437
80458
 
80438
80459
  // packages/cli/dist/cli.js
@@ -7,6 +7,7 @@ package).
7
7
  | Manual | Topic |
8
8
  | ------------------------------------------ | ----------------------------------------- |
9
9
  | [Getting started](getting-started.md) | Install, first run, ports |
10
+ | [Desktop launcher](launcher.md) | Folder picker window, Start / Stop / Open |
10
11
  | [Product overview](product.md) | Local node graph: pitch, compare, lacks |
11
12
  | [Using the editor](using-the-editor.md) | Canvas, runs, human review, reconnect |
12
13
  | [Workflow ideas](workflows.md) | Common scenarios you can build |
@@ -23,7 +23,14 @@ langflower ./my-project
23
23
  ```
24
24
 
25
25
  Langflower starts a local server and opens the UI in your browser (default
26
- `http://127.0.0.1:4010`).
26
+ `http://127.0.0.1:4010`). An optional desktop **launcher** can pick folders
27
+ and start the same CLI without a terminal — several projects at once, each
28
+ on its own port. User manual:
29
+ [Desktop launcher](launcher.md). Unsigned
30
+ Windows and macOS zips are on
31
+ [GitHub Releases](https://github.com/earthdmitriy/langflower/releases)
32
+ (tags `launcher-v*`, not the npm `v*` tags). You still need Node.js and
33
+ `npm install -g langflower`. On macOS, right-click the binary → Open.
27
34
 
28
35
  Stop the process with Ctrl+C when you are done. There is no cloud account and
29
36
  no background daemon.
@@ -0,0 +1,110 @@
1
+ # Desktop launcher
2
+
3
+ The launcher is a small window that starts Langflower **without a
4
+ terminal**. It picks a project folder, can install Node.js and the
5
+ global `langflower` CLI, then runs the **same** CLI a terminal user
6
+ would run. The editor still opens in your **system browser**.
7
+
8
+ This window is not the canvas. It does not embed the editor, and it
9
+ does not include Node.js or the CLI inside the zip.
10
+
11
+ ## Download
12
+
13
+ Unsigned Windows and macOS zips are on
14
+ [GitHub Releases](https://github.com/earthdmitriy/langflower/releases)
15
+ (tags `launcher-v*`, not the npm `v*` tags).
16
+
17
+ - `langflower-launcher-windows-x64.zip`
18
+ - `langflower-launcher-windows-arm64.zip`
19
+ - `langflower-launcher-macos-arm64.zip`
20
+ - `langflower-launcher-macos-x64.zip`
21
+
22
+ Unpack and run `langflower-launcher.exe` (Windows) or
23
+ `langflower-launcher` (macOS). Windows SmartScreen and macOS Gatekeeper
24
+ will warn because the binary is unsigned. On macOS: right-click the
25
+ file → **Open**.
26
+
27
+ Linux has no published zip in v1.
28
+
29
+ ## First run
30
+
31
+ You still need:
32
+
33
+ 1. **Node.js ≥ 22**
34
+ 2. The global CLI: `npm install -g langflower`
35
+
36
+ If Node is missing or too old, the window shows **Install Node.js**
37
+ (Windows: winget LTS; macOS: official Node `.pkg` from nodejs.org, which
38
+ asks for administrator permission). If Node is fine but Langflower is
39
+ missing, it shows **Install Langflower**. If a newer CLI is on npm, it
40
+ offers **Update** and **Skip**. Skip lasts for this session only.
41
+
42
+ Install buttons are hidden while any project the launcher started is
43
+ still running. Stop those first.
44
+
45
+ The **?** button in the title row opens this page on GitHub.
46
+
47
+ ## Start a project
48
+
49
+ 1. **Browse** to a folder, type a path, or click a **Recent** row.
50
+ **×** on a row removes it from recents only (it does not Stop a
51
+ running project).
52
+ 2. Click **Start Langflower** (or press Enter in the path field).
53
+ 3. Wait until the hint says the project is running on a port.
54
+ 4. The system browser opens `http://127.0.0.1:<port>` after the CLI is
55
+ ready. Use **Open Langflower ↗** (or **Open UI ↗** on a recent row)
56
+ if you closed the tab.
57
+
58
+ An empty folder is fine: the CLI creates `.langflower/` on first start.
59
+ Your other files are left alone.
60
+
61
+ **Start** stays disabled until Node meets the minimum, a global
62
+ `langflower` is installed, and a folder is chosen.
63
+
64
+ ## Several projects at once
65
+
66
+ Each folder gets its own Langflower process and port (starting at
67
+ **4010**, then the next free port through **4109**). Start, Stop, and
68
+ Open apply to the **selected** folder. Other rows keep running.
69
+
70
+ You cannot start the same folder twice. Select another recent and Start
71
+ it while the first is still up.
72
+
73
+ ## Stop and close
74
+
75
+ - **Stop Langflower** ends the selected process only.
76
+ - **Closing the launcher window** stops **every** process this window
77
+ started.
78
+ - Closing a **browser tab** does not stop the server. Reopen the URL
79
+ while that row still says Running.
80
+
81
+ Processes you started from a terminal are not stopped by this window.
82
+
83
+ ## Details
84
+
85
+ Open **Details** at the bottom for the CLI and installer log. **Copy**
86
+ puts the log on the clipboard (the text itself is not selectable).
87
+
88
+ Prefixes:
89
+
90
+ - `[launcher]` — version check and launcher messages
91
+ - `[install]` — Node or Langflower install output
92
+ - `[folder-name]` — that project’s CLI output
93
+
94
+ If Node and Langflower are already current, the first line says they
95
+ already have current versions — that is not an install.
96
+
97
+ ## If something goes wrong
98
+
99
+ | What you see | What to try |
100
+ | -------------------------------- | --------------------------------------------------------- |
101
+ | Start stays grey | Install Node and/or Langflower; choose a folder |
102
+ | “That folder could not be found” | Browse again; the path must exist |
103
+ | “No free port is available” | Stop other Langflower instances using 4010–4109 |
104
+ | Gatekeeper / SmartScreen | Unsigned zip — Open anyway as above |
105
+ | Editor does not load | Wait for Running; open Details; try Open ↗ |
106
+ | Update offer every launch | Skip is session-only; Update installs `langflower@latest` |
107
+
108
+ Need the terminal path instead? See
109
+ [Getting started](getting-started.md). Once a project is running, use
110
+ [Using the editor](using-the-editor.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langflower",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Visual LLM-chain builder",
5
5
  "type": "module",
6
6
  "bin": {
Binary file
Binary file
Binary file
@@ -5,6 +5,9 @@
5
5
  <title>Langflower</title>
6
6
  <base href="/">
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <link rel="icon" href="favicon.ico" sizes="any">
9
+ <link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
10
+ <link rel="apple-touch-icon" href="apple-touch-icon.png">
8
11
  <style>@layer properties;:root{--ngd-colors-gray-100:#ffffff;--ngd-colors-gray-200:#f7f7f7;--ngd-colors-gray-300:#edeff3;--ngd-colors-gray-400:#d5d8e0;--ngd-colors-gray-450:#c2c0c0;--ngd-colors-gray-500:#6f7480;--ngd-colors-gray-600:#4d5059;--ngd-colors-gray-650:#383a40;--ngd-colors-gray-700:#27282b;--ngd-colors-gray-800:#151516;--ngd-colors-gray-900-5:rgba(7, 7, 8, .05);--ngd-colors-gray-900-20:rgba(7, 7, 8, .2);--ngd-colors-gray-900-50:rgba(7, 7, 8, .5);--ngd-colors-acc1-400:#a977ff;--ngd-colors-acc1-500:#9140ff;--ngd-colors-acc1-500-40:rgba(145, 64, 255, .4);--ngd-colors-acc1-500-50:rgba(145, 64, 255, .5);--ngd-colors-acc1-600:#891aff;--ngd-colors-acc4-500:#1096e7}:root{--ngd-shadow:var(--ngd-colors-gray-900-20);--ngd-txt-primary-default:var(--ngd-colors-gray-800);--ngd-nav-button-primary-default:var(--ngd-colors-gray-600);--ngd-nav-button-primary-pressed:var(--ngd-colors-acc1-600);--ngd-nav-button-primary-hover:var(--ngd-colors-gray-900-5);--ngd-nav-button-primary-disabled:var(--ngd-colors-gray-450);--ngd-diagram-background-color:var(--ngd-colors-gray-200);--ngd-ui-bg-primary-default:var(--ngd-colors-gray-100);--ngd-ui-bg-tertiary-default:var(--ngd-colors-gray-200);--ngd-ui-stroke-primary-focus:var(--ngd-colors-gray-500);--ngd-pt-stroke-primary-default:var(--ngd-colors-gray-600);--ngd-node-bg-primary-default:var(--ngd-colors-gray-100);--ngd-node-stroke-primary-default:var(--ngd-colors-gray-400);--ngd-node-stroke-primary-hover:var(--ngd-colors-acc1-500);--ngd-node-port-fill-default:var(--ngd-colors-gray-100);--ngd-node-port-fill-active:var(--ngd-colors-acc1-500);--ngd-node-port-stroke-default:var(--ngd-colors-gray-500);--ngd-node-port-stroke-active:var(--ngd-colors-gray-100);--ngd-transform-box:var(--ngd-colors-acc4-500);--ngd-focus-ring-node-active:var(--ngd-colors-acc1-500-40);--ngd-button-gray-bg-default:var(--ngd-colors-gray-500);--ngd-button-gray-bg-hover:var(--ngd-colors-gray-600);--ngd-button-gray-bg-active:var(--ngd-colors-gray-650);--ngd-default-edge-label-bg-primary-default:var(--ngd-colors-gray-100);--ngd-background-line-minor-color:var(--ngd-colors-gray-450);--ngd-background-line-major-color:var(--ngd-colors-gray-500);--ngd-ui-border-color:var(--ngd-colors-gray-300);--ngd-minimap-bg-primary-default:var(--ngd-colors-gray-100);--ngd-minimap-stroke-primary-default:var(--ngd-colors-gray-400)}:root{--ngd-node-background-color:var(--ngd-node-bg-primary-default);--ngd-node-border-color:var(--ngd-node-stroke-primary-default);--ngd-node-border-color-hover:var(--ngd-node-stroke-primary-hover);--ngd-node-border-radius:.75rem;--ngd-node-border-size:.0625rem;--ngd-group-border-color:var(--ngd-ui-stroke-primary-focus);--ngd-group-border-color-hover:var(--ngd-pt-stroke-primary-default);--ngd-group-border-color-highlight:var(--ngd-colors-acc1-500);--ngd-group-box-shadow-color-highlight:var(--ngd-colors-acc1-500-50);--ngd-group-background-color-highlight:var(--ngd-colors-gray-400);--ngd-group-border-radius:.75rem;--ngd-group-highlight-size:1.25rem;--ngd-selected-node-box-shadow:0 0 0 .25rem var(--ngd-focus-ring-node-active);--ngd-rotate-handle-size:2rem;--ngd-rotate-handle-distance:2rem;--ngd-rotate-handle-background-color:var(--ngd-button-gray-bg-default);--ngd-rotate-handle-background-color-hover:var(--ngd-button-gray-bg-hover);--ngd-rotate-handle-background-color-active:var(--ngd-button-gray-bg-active);--ngd-rotate-handle-xy:calc(-.7071 * var(--ngd-rotate-handle-distance));--ngd-rotate-handle-top:var(--ngd-rotate-handle-xy);--ngd-rotate-handle-right:var(--ngd-rotate-handle-xy);--ngd-resize-line-border-width:.0625rem;--ngd-resize-line-border-style:solid;--ngd-resize-line-border-color:var(--ngd-transform-box);--ngd-resize-handle-size:.375rem;--ngd-resize-handle-background-color:var(--ngd-ui-bg-primary-default);--ngd-resize-handle-border-size:.0625rem;--ngd-resize-handle-border-style:solid;--ngd-resize-handle-border-color:var(--ngd-transform-box);--ngd-resize-handle-border-radius:0;--ngd-port-size:.25rem;--ngd-port-background-color:var(--ngd-node-port-fill-default);--ngd-port-border-color:var(--ngd-node-port-stroke-default);--ngd-port-border-size:.125rem;--ngd-port-border-radius:50%;--ngd-port-background-color-hover:var(--ngd-node-port-fill-active);--ngd-port-border-color-hover:var(--ngd-node-port-stroke-active);--ngd-port-border-size-hover:.25rem;--ngd-default-edge-stroke:var(--ngd-colors-gray-500);--ngd-default-edge-stroke-hover:var(--ngd-colors-gray-700);--ngd-default-edge-stroke-selected:var(--ngd-colors-acc1-500);--ngd-box-selection-border-color:#961ce7;--ngd-box-selection-border-size:1px;--ngd-box-selection-background:rgba(43, 91, 213, .12);--ngd-default-edge-label-background-color:var(--ngd-default-edge-label-bg-primary-default);--ngd-default-edge-label-color:var(--ngd-txt-primary-default);--ngd-default-edge-label-border-color:var(--ngd-colors-gray-500);--ngd-background-dot-color:var(--ngd-colors-gray-500);--ngd-background-line-minor-width:.5;--ngd-background-line-major-width:1;--ngd-background-line-minor-opacity:.5;--ngd-background-line-major-opacity:.6;--ngd-minimap-background:var(--ngd-minimap-bg-primary-default);--ngd-minimap-border-color:var(--ngd-minimap-stroke-primary-default);--ngd-minimap-shadow-color:var(--ngd-shadow);--ngd-minimap-border-radius:1rem;--ngd-minimap-padding:.5rem;--ngd-minimap-margin:1rem;--ngd-minimap-node-color:var(--ngd-colors-gray-400);--ngd-minimap-node-opacity:.8;--ngd-minimap-diagram-bounds-opacity:.3;--ngd-minimap-diagram-bounds-color:var(--ngd-colors-gray-400);--ngd-minimap-viewport-stroke-color:var(--ngd-colors-gray-400);--ngd-minimap-viewport-stroke-width:1;--ngd-nav-button-color:var(--ngd-nav-button-primary-default);--ngd-nav-button-size:1.25rem;--ngd-nav-button-border-radius:.5rem;--ngd-nav-button-padding:.6875rem;--ngd-nav-button-background-color-hover:var(--ngd-nav-button-primary-hover);--ngd-nav-button-color-active:var(--ngd-nav-button-primary-pressed);--ngd-nav-button-color-disabled:var(--ngd-nav-button-primary-disabled);--ngd-zoom-controls-font-size:.8125rem;--ngd-zoom-controls-font-weight:500;--ngd-zoom-controls-color:var(--ngd-nav-button-primary-default)}@layer theme,base,components,utilities;@layer theme{:root{--font-sans:Inter, ui-sans-serif, system-ui, sans-serif;--font-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, monospace;--color-red-300:oklch(80.8% .114 19.571);--color-red-700:oklch(50.5% .213 27.518);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-amber-950:oklch(27.9% .077 45.635);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-950:oklch(26.2% .051 172.552);--color-sky-50:oklch(97.7% .013 236.62);--color-sky-100:oklch(95.1% .026 236.824);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-sky-700:oklch(50% .134 242.749);--color-sky-950:oklch(29.3% .066 243.157);--color-violet-400:oklch(70.2% .183 293.541);--color-rose-50:oklch(96.9% .015 12.422);--color-rose-100:oklch(94.1% .03 12.58);--color-rose-300:oklch(81% .117 11.638);--color-rose-400:oklch(71.2% .194 13.428);--color-rose-500:oklch(64.5% .246 16.439);--color-rose-600:oklch(58.6% .253 17.585);--color-rose-700:oklch(51.4% .222 16.935);--color-rose-800:oklch(45.5% .188 13.697);--color-rose-950:oklch(27.1% .105 12.094);--color-zinc-50:oklch(98.5% 0 0);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-zinc-950:oklch(14.1% .005 285.823);--color-white:#fff;--spacing:.25rem;--container-md:28rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-normal:0em;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before{box-sizing:border-box;margin:0;padding:0;border:0 solid}html{line-height:1.5;-webkit-text-size-adjust:100%;tab-size:4;font-family:var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings, normal);font-variation-settings:var(--default-font-variation-settings, normal);-webkit-tap-highlight-color:transparent}}@layer utilities{}:root{--lf-control-h:2rem;--lf-btn-pad:calc(var(--lf-control-h) / 2)}@layer components{}html,body{height:100%;margin:0}body{background-color:var(--color-zinc-50);font-family:var(--font-sans);font-size:var(--text-sm);line-height:var(--tw-leading, var(--text-sm--line-height));color:var(--color-zinc-950);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body:where([data-theme=dark],[data-theme=dark] *){background-color:var(--color-zinc-950)}body:where([data-theme=dark],[data-theme=dark] *){color:var(--color-zinc-100)}@layer base{}@layer components{}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0;}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0;}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0;}@property --tw-rotate-x{syntax:"*";inherits:false;}@property --tw-rotate-y{syntax:"*";inherits:false;}@property --tw-rotate-z{syntax:"*";inherits:false;}@property --tw-skew-x{syntax:"*";inherits:false;}@property --tw-skew-y{syntax:"*";inherits:false;}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0;}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid;}@property --tw-gradient-position{syntax:"*";inherits:false;}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000;}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000;}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000;}@property --tw-gradient-stops{syntax:"*";inherits:false;}@property --tw-gradient-via-stops{syntax:"*";inherits:false;}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%;}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%;}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%;}@property --tw-leading{syntax:"*";inherits:false;}@property --tw-font-weight{syntax:"*";inherits:false;}@property --tw-tracking{syntax:"*";inherits:false;}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000;}@property --tw-shadow-color{syntax:"*";inherits:false;}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%;}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000;}@property --tw-inset-shadow-color{syntax:"*";inherits:false;}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%;}@property --tw-ring-color{syntax:"*";inherits:false;}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000;}@property --tw-inset-ring-color{syntax:"*";inherits:false;}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000;}@property --tw-ring-inset{syntax:"*";inherits:false;}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0px;}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff;}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000;}@property --tw-blur{syntax:"*";inherits:false;}@property --tw-brightness{syntax:"*";inherits:false;}@property --tw-contrast{syntax:"*";inherits:false;}@property --tw-grayscale{syntax:"*";inherits:false;}@property --tw-hue-rotate{syntax:"*";inherits:false;}@property --tw-invert{syntax:"*";inherits:false;}@property --tw-opacity{syntax:"*";inherits:false;}@property --tw-saturate{syntax:"*";inherits:false;}@property --tw-sepia{syntax:"*";inherits:false;}@property --tw-drop-shadow{syntax:"*";inherits:false;}@property --tw-drop-shadow-color{syntax:"*";inherits:false;}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%;}@property --tw-drop-shadow-size{syntax:"*";inherits:false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}</style><link rel="stylesheet" href="styles-VA3HMZK7.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-VA3HMZK7.css"></noscript></head>
9
12
  <body>
10
13
  <lf-root></lf-root>
@@ -70,6 +70,17 @@ You only answer when an LLM provider is already configured. That means coding
70
70
  templates in the skeleton are **already usable** once copied into the project —
71
71
  do not say coding pipelines “don’t exist” or are unavailable.
72
72
 
73
+ - **Can:** Optional **desktop launcher** (Slint) picks a project folder
74
+ and runs the same CLI (`--no-open -p <port>`), then opens the editor in
75
+ the **system browser** after the instance is listening. Several
76
+ projects can run at once, each on its own port. Unsigned Windows/macOS
77
+ zips ship on GitHub Releases (`launcher-v*` tags, not npm `v*`). Closing
78
+ the launcher stops instances **it** started. Closing a browser tab does
79
+ not. The **?** control opens the user manual on GitHub
80
+ (`docs/public/launcher.md`).
81
+ - **Cannot:** Claim the launcher embeds the canvas, or that it is a
82
+ Tauri / Electron / WebView app. (Tauri was tried for the thin window
83
+ and rejected; the shipped launcher is Slint.)
73
84
  - **Can:** `langflower start [project-dir]` (default port **4010**) creates
74
85
  `.langflower/`, config, `instructions.md`, packs `nodes/my-nodes/` and
75
86
  `nodes/hello-embed/`, skills
@@ -13,10 +13,13 @@ this file over inventing infrastructure.
13
13
 
14
14
  ## Layers (user-facing)
15
15
 
16
- 1. CLI — `langflower start` (default port **4010**)
16
+ 1. CLI — `langflower start` (default port **4010**). Optional **Slint
17
+ launcher** can spawn several of these CLIs (one per project folder);
18
+ it does not embed the editor.
17
19
  2. Local **server** — owns runtime, project I/O under `.langflower/`
18
20
  3. **WebSocket bus** — control plane between server and editor
19
21
  4. Angular **editor** — canvas, feed, inspector, Settings, composer
22
+ (system browser; not a WebView inside the launcher)
20
23
 
21
24
  Project product data for Langflower lives under **`.langflower/`**.
22
25