@linzumi/cli 0.0.19-beta → 0.0.22-beta

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
@@ -16,27 +16,25 @@
16
16
  ║║ \"/` ___ ;_________║║_.'
17
17
  ║║ ` ^^ ^^ ║║
18
18
  ──────────╨╨─────────────··────··────────╨╨──────────────
19
- your agent, your laptop, PRs in minutes
19
+ your agent, your laptop, coding live
20
20
  ```
21
21
 
22
- Copy this into your terminal from the repo you want changed:
22
+ Copy this into your terminal:
23
23
 
24
24
  ```bash
25
- codex -c sandbox_workspace_write.network_access=true --ask-for-approval never --sandbox workspace-write --add-dir ~/.linzumi --add-dir ~/.kandan --add-dir ~/.npm --add-dir ~/.codex -- 'Follow https://linzumi.com/agents.md to get me up and running'
25
+ codex --ask-for-approval never --sandbox danger-full-access -- 'Get me up and running with Linzumi from https://linzumi.com/agents.md. Read it with curl.'
26
26
  ```
27
27
 
28
28
  That's the launch path: the first Codex is only the bootstrapper. It
29
- opens the agent instructions, collects the email up front, asks you for
30
- the emailed code when it arrives, connects Linzumi to this repo, creates
31
- the shared support channel, starts a Linzumi Codex session in a work
32
- thread, and opens the browser editor. The Linzumi Codex session does the
33
- branch, test, push, and PR work.
34
-
35
- The snippet uses Codex's normal workspace sandbox with network access
36
- enabled, automatic command approval, and explicit writable access to
37
- Linzumi's persistent local auth/config, editor runtime cache, npm cache,
38
- and Codex's own local session state. It is intentionally not the dangerous
39
- sandbox-bypass mode.
29
+ opens the agent instructions, confirms your email and workspace details,
30
+ asks you for the emailed code when it arrives, creates `/tmp/hello_linzumi`,
31
+ starts that hot-reload app on your computer, creates the shared support
32
+ channel, starts a Linzumi Codex session in a work thread, and opens the
33
+ browser editor pointed at the demo app.
34
+
35
+ The snippet uses automatic command approval and full local process access
36
+ because the bootstrapper must start a real runner and browser editor on this
37
+ computer. It is intentionally not the dangerous sandbox-bypass mode.
40
38
 
41
39
  Today, your AI coding agent has two homes, both bad.
42
40
 
@@ -49,26 +47,27 @@ agent" rarely means "works on your laptop." You merge, pull, run the
49
47
  test suite, and find out at 4pm.
50
48
 
51
49
  Linzumi gives it a third home: **your real laptop, in a thread your
52
- team can watch live**. Real env vars, real branches, real dotfiles,
50
+ team can watch live**. Real processes, real env vars, real dotfiles,
53
51
  real teamwork. Diffs land in chat as the agent makes them. Your
54
52
  reviewer opens a browser VS Code pointed at *your folder* and has an
55
53
  opinion before the agent's even finished. You approve from your phone
56
54
  on the way to lunch.
57
55
 
58
- In three minutes from now you'll have it.
56
+ In three minutes from now you'll have it working end to end.
59
57
 
60
58
  ## What you'll have in three minutes
61
59
 
62
- - **An AI coding agent running on your real laptop**, in a thread
63
- your team can read along with.
64
- - **A browser VS Code editor** pointed at the same folder, share-able
65
- by link no clone, no deploy, no "let me push a branch real
66
- quick."
60
+ - **An AI coding agent running on your real laptop**, editing the
61
+ generated Hello Linzumi app in a thread your team can read along with.
62
+ - **A browser VS Code editor** pointed at `/tmp/hello_linzumi`,
63
+ share-able by link with no clone and no deploy.
64
+ - **A tunneled local preview** of the app running on your computer with
65
+ hot reload.
67
66
  - **A private support channel with the Linzumi team**, in case
68
67
  anything goes sideways.
69
68
 
70
- One pasted command. No cloud VM. Your code, your terminal, and your dev
71
- server stay on your laptop the whole time.
69
+ One pasted command. No cloud VM. The editor, agent, and dev server stay
70
+ on your laptop the whole time.
72
71
 
73
72
  ## Manual Runner Setup
74
73
 
@@ -76,9 +75,9 @@ The agent-first command above is the launch path. Use this manual path
76
75
  when you want to connect your laptop yourself before starting work from
77
76
  the browser.
78
77
 
79
- You'll need **Node.js 20+**, **Bun 1.2+**, the **Codex CLI**, and a
80
- Chromium-based browser (Chrome, Edge, Arc, or Brave). Safari mostly
81
- works; live collaboration is smoother in Chromium.
78
+ You'll need **Node.js 20+**, the **Codex CLI**, and a Chromium-based browser
79
+ (Chrome, Edge, Arc, or Brave). Safari mostly works; live collaboration is
80
+ smoother in Chromium.
82
81
 
83
82
  ```bash
84
83
  npm install -g @linzumi/cli@latest
@@ -101,72 +100,79 @@ That's it for manual setup. The rest of this README is detail.
101
100
 
102
101
  That one prompt is the launch path. The canonical agent instructions are
103
102
  hosted at `https://linzumi.com/agents.md`; `https://linzumi.com/skills.md`
104
- stays available for compatibility. The bootstrap agent will collect your
105
- email up front, ask for the emailed code after signup sends it, say
106
- hello to `@sean` in the shared support channel, start the runner in the
107
- current folder, start a Linzumi Codex session in a work thread, and open
108
- the browser editor. The Linzumi Codex session then posts the PR or
109
- reviewable branch.
103
+ stays available for compatibility. The bootstrap agent will confirm your
104
+ email and workspace choice up front, ask for the emailed code after signup
105
+ sends it, say hello to `@sean` in the shared support channel,
106
+ generate `/tmp/hello_linzumi`, start its hot-reload Node server, start the
107
+ runner for that folder, start a Linzumi Codex session in a work thread, and
108
+ open the browser editor. The Linzumi Codex session then adds confetti to the
109
+ demo page while you watch. Workspace names are plain display names from 2 to
110
+ 100 characters; Linzumi generates the URL-safe workspace slug.
110
111
 
111
112
  Under the hood, the npm package exposes these commands for the bootstrap
112
113
  agent to run. They are not extra human setup steps after the one pasted
113
114
  Codex command.
114
115
 
115
116
  ```bash
116
- npx -y @linzumi/cli@latest signup --email alice@example.com --agent-name BuildBot
117
+ npx -y @linzumi/cli@latest signup --email alice@example.com --workspace-name "Alice's Linzumi" --agent-name BuildBot
117
118
  npx -y @linzumi/cli@latest claim --pending <pending_id> --code <XXXX-XXXX>
118
119
  npx -y @linzumi/cli@latest channel post <support_channel_id> "Hello @sean, starting this launch run."
119
- npx -y @linzumi/cli@latest thread new "Hello world PR" --message "Starting now."
120
- npx -y @linzumi/cli@latest agent runner "$PWD" \
121
- --runner-id hello-world-agent \
122
- --allowed-cwd "$PWD" \
123
- --sandbox workspace-write \
120
+ npx -y @linzumi/cli@latest hello
121
+ (cd /tmp/hello_linzumi && npm run dev > /tmp/hello_linzumi/dev.log 2>&1 &)
122
+ npx -y @linzumi/cli@latest thread new "Hello Linzumi confetti" --message "Please add confetti when the page loads."
123
+ npx -y @linzumi/cli@latest agent runner /tmp/hello_linzumi \
124
+ --runner-id hello-linzumi-agent \
125
+ --allowed-cwd /tmp/hello_linzumi \
126
+ --forward-port 8787 \
127
+ --sandbox danger-full-access \
124
128
  --approval-policy never
125
129
  ```
126
130
 
127
131
  The agent-owned runner reads `~/.linzumi/agent-token.json`, uses the
128
132
  workspace/channel scope from the approval flow, trusts only the selected
129
- folder, and listens only to the approving human unless `--listen-user` is
130
- explicitly passed. The bootstrap agent waits for `Runner connected:` before
131
- starting Codex in the Linzumi thread.
133
+ folder, advertises the explicit preview port, and listens only to the
134
+ approving human unless `--listen-user` is explicitly passed. The bootstrap
135
+ agent waits for `Runner connected:` before starting Codex in the Linzumi
136
+ thread.
132
137
 
133
138
  By default, the runner downloads the Linzumi-approved `code-server`
134
139
  runtime for your platform and verifies its checksum before enabling the
135
140
  browser editor. Linux editor launches are wrapped with `bubblewrap`
136
141
  (`bwrap`) for filesystem confinement.
137
142
 
138
- `linzumi claim` also prints `login_url`. That one-time link logs the human
139
- into `#general` in their own email-named workspace. The claim also provisions
140
- `#linzumi-support`, a shared channel with the Linzumi workspace; the bootstrap
141
- agent posts a hello there with the printed `support_channel_id`.
142
- Keep repository work in task threads; use the support channel when signup,
143
- runner, or browser-editor setup gets stuck.
143
+ `linzumi claim` also prints `workspace_name`, `workspace_id`, and `login_url`.
144
+ That one-time link logs the human into `#general` in their own selected
145
+ workspace. The claim also provisions `#linzumi-support`, a shared channel
146
+ connected to Linzumi's workspace so our team can see setup issues from our
147
+ side; the bootstrap agent posts a hello there with the printed
148
+ `support_channel_id`.
149
+ Keep demo work in task threads; use the support channel when signup, runner,
150
+ preview, or browser-editor setup gets stuck.
144
151
 
145
152
  Once the runner is online, the bootstrap agent can ask Linzumi to start
146
153
  Codex and open the browser editor for the same thread and folder:
147
154
 
148
155
  ```bash
149
156
  npx -y @linzumi/cli@latest codex start <thread_id> \
150
- --runner hello-world-agent \
151
- --cwd "$PWD" \
152
- --work-description "You are the Linzumi Codex agent running inside this Linzumi thread on the user's local runner. Create a small hello-world branch in the current repo, make the smallest reviewable change, run the nearest relevant local test or smoke check, push the branch or open a PR, and post the PR URL or exact review branch back in this Linzumi thread. Keep the human updated in the thread. If you are blocked, post the exact blocker instead of pretending the run succeeded."
157
+ --runner hello-linzumi-agent \
158
+ --cwd /tmp/hello_linzumi \
159
+ --work-description "Work only in /tmp/hello_linzumi. Add tasteful confetti when the Hello Linzumi page loads, keep the hot-reload app working on port 8787, and post the exact files changed."
153
160
 
154
161
  npx -y @linzumi/cli@latest editor open <thread_id> \
155
- --runner hello-world-agent \
156
- --cwd "$PWD"
162
+ --runner hello-linzumi-agent \
163
+ --cwd /tmp/hello_linzumi
157
164
  ```
158
165
 
159
- The launch target for this path is zero-to-hello-world-pr+editor in under
160
- 3 minutes, measured from `signup` through PR/reviewable change link plus
161
- browser VS Code readiness.
166
+ The launch target for this path is zero-to-Hello-Linzumi-editor+preview in
167
+ under 3 minutes, measured from `signup` through browser VS Code readiness,
168
+ forwarded preview readiness, and the first visible Codex edit.
162
169
 
163
170
  ## What just happened
164
171
 
165
172
  You now have:
166
173
 
167
- - **A runner.** Your laptop, listed in the workspace, advertising the
168
- folder you started in (and any others you've added to your trusted
169
- list).
174
+ - **A runner.** Your laptop, listed in the workspace, advertising
175
+ `/tmp/hello_linzumi` and the explicit preview port.
170
176
  - **A workspace** you can invite teammates into. They open the same
171
177
  browser app, see the same threads, and can start their own runners
172
178
  on their own machines.
@@ -174,18 +180,16 @@ You now have:
174
180
  **cannot** see your repo contents, your tokens, your Codex
175
181
  transcripts, your editor session, or your other threads. Stuck?
176
182
  Post there — we read it.
177
- - **A browser VS Code editor**, available on demand for any Codex
178
- session, posted into the thread when ready.
183
+ - **A browser VS Code editor**, opened against `/tmp/hello_linzumi` and
184
+ ready for shared editing.
179
185
 
180
186
  ## Three things to try first
181
187
 
182
- 1. **Onboard yourself to a new repo.** *"Explain this project and tell
183
- me how to run it."* Linzumi Codex maps the codebase before you've
184
- opened a single file. Days saved on day one.
188
+ 1. **Watch the demo change live.** The Linzumi Codex session edits the
189
+ generated page, and hot reload shows the change in the tunneled preview.
185
190
  2. **Make a real change without context-switching.** The Codex session
186
191
  running in Linzumi edits files on your disk. Watch the diff land in
187
- chat, or jump into the browser editor (it's VS Code in your browser,
188
- pointed at your folder) and shape it yourself.
192
+ chat, or jump into the browser editor and shape it yourself.
189
193
  3. **Show a teammate something on your screen.** Open the browser
190
194
  editor or share your local dev server through a normal HTTPS
191
195
  link. No exposing localhost, no copy-pasting IPs, no "screenshare
@@ -243,9 +247,6 @@ intentionally. Every action is auditable from the thread.
243
247
  - **`linzumi: command not found`** — your global npm bin folder isn't
244
248
  on `PATH`. Run `npm prefix -g`; add the printed path's `bin` folder
245
249
  to your shell.
246
- - **`bun: command not found`** — install Bun, then rerun
247
- `linzumi start`. The `linzumi` binary is a node shim that delegates
248
- to Bun for fast TypeScript startup.
249
250
  - **`codex: command not found`** — install the Codex CLI, or pass
250
251
  `--codex-bin <path>` to `linzumi start`.
251
252
  - **Browser sign-in opens but never returns to the CLI.** Your browser
@@ -260,7 +261,7 @@ intentionally. Every action is auditable from the thread.
260
261
  ## Pinning a version
261
262
 
262
263
  ```bash
263
- npm install -g @linzumi/cli@0.0.19-beta
264
+ npm install -g @linzumi/cli@0.0.22-beta
264
265
  linzumi --version
265
266
  ```
266
267
 
package/bin/linzumi.js CHANGED
@@ -1,23 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { spawnSync } from "node:child_process";
4
- import { dirname, join } from "node:path";
5
- import { fileURLToPath } from "node:url";
3
+ if (globalThis.WebSocket === undefined) {
4
+ const { WebSocket } = await import("ws");
5
+ globalThis.WebSocket = WebSocket;
6
+ }
6
7
 
7
- const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
8
- const entrypoint = join(packageRoot, "src", "index.ts");
9
- const result = spawnSync("bun", ["run", entrypoint, ...process.argv.slice(2)], {
10
- cwd: process.cwd(),
11
- env: process.env,
12
- stdio: "inherit",
13
- });
8
+ const { main } = await import("../dist/index.js");
14
9
 
15
- if (result.error !== undefined) {
16
- process.stderr.write(
17
- `failed to launch linzumi runner with bun: ${result.error.message}\n` +
18
- "Install Bun, then rerun the linzumi command.\n",
19
- );
20
- process.exit(127);
10
+ try {
11
+ await main(process.argv.slice(2));
12
+ } catch (error) {
13
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
14
+ process.exit(1);
21
15
  }
22
-
23
- process.exit(result.status ?? 1);
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="4096" height="4096" aria-label="Linzumi" color="#0e404b"><path fill="currentColor" fill-rule="evenodd" d="M2111 3966c-37 2-34 3-69 2l-141-7c-34-2-36-1-65-5l-107-15c-30-5-43-7-76-15a3031 3031 0 0 1-217-61l-84-31c-26-10-33-11-70-29a2233 2233 0 0 1-423-259 1796 1796 0 0 1-381-416 1962 1962 0 0 1-168-298c-25-57-54-131-74-191-19-59-35-127-45-168-11-40-11-45-16-76-5-30-11-58-16-107-6-48-13-132-16-183q-2-77 1-122c0-31 1-30 3-61 3-31 8-89 13-126 4-37 4-47 14-95a1863 1863 0 0 1 475-956q51-56 92-94c27-26 36-36 71-65s99-79 137-107 62-43 90-61a1539 1539 0 0 1 156-88c31-15 58-31 104-49a1697 1697 0 0 1 492-133c61-9 144-19 202-22s111 1 145 2c34 2 30 6 57 9s70 5 103 9 56 7 96 15q59 10 141 30c54 15 143 44 187 59s47 18 77 31 59 25 102 48 108 59 157 89a2162 2162 0 0 1 210 153c27 23 50 42 88 80s99 101 141 148c41 48 74 91 106 138 33 46 67 104 90 141a1170 1170 0 0 1 92 180c17 40 44 107 59 149 16 41 22 63 32 99a3000 3000 0 0 1 47 195c5 28 9 46 14 95s13 137 16 198c2 62-1 123-4 172-2 50-7 88-11 126l-16 103a3048 3048 0 0 1-62 248c-10 31-17 49-29 80-12 32-22 60-44 108-23 48-64 130-92 180s-57 90-77 121l-45 62a3211 3211 0 0 1-153 182q-32 35-76 76a2201 2201 0 0 1-349 260c-50 28-132 69-180 91-48 23-76 32-108 44-33 12-42 17-84 30-42 12-109 33-168 46-60 12-130 24-187 31-58 6-119 8-157 10m9-294c18-3 10-6 14-12 4-5 4-11 9-19 6-7 16-19 25-27 10-8 14-12 31-18 16-6 50-14 69-17 18-3 33-1 42-2 8-1 6-3 7-4 1-2 10 3 0-4-11-7-46-26-65-40s-37-32-50-44c-13-13-18-17-29-31-12-14-29-41-39-53s-11-17-19-19q-11-3-31 4c-14 3-40 9-53 14s-15 6-23 15c-8 8-20 28-27 35-6 7-5 5-11 7s-18 5-27 4q-15-2-27-9c-6-6-11-18-14-24-3-7-4-9-4-16l3-26q2-17 12-39c7-13 14-26 31-42 16-15 56-41 68-51s5-5 5-10c1-4 4-6-1-17a341 341 0 0 0-80-101c-18-14-41-24-58-32-16-9-15-9-43-18-28-8-98-27-125-36-27-8-21-7-38-15l-61-32c-13-7-10-4-20-12l-41-34a114 114 0 0 1-34-54q-5-17 0-30c3-10 0-9 15-27 16-18 54-59 76-80 23-21 37-30 58-45a1278 1278 0 0 1 126-78c18-9 40-15 53-20q18-9 23-14c4-3 5 4 3-7-3-11-14-37-17-57-3-21-3-46 0-65q4-27 15-50 13-25 29-46 15-19 35-30c13-8 32-15 46-18q18-5 34-3l34 2q15 2 27 7c8 4 19 11 23 15 3 5 5 1-2 12-8 11-31 34-43 53q-18 30-30 65c-7 24-14 65-15 80-2 16 2 9 5 12l12 8q5 2 8-3c3-2 10-4 13-13 4-8 2-19 8-38 6-18 18-54 29-73 10-19 21-28 34-41q20-21 42-35c14-9 24-13 42-17 18-3 46-5 65-5 18 0 29 1 46 7 16 6 39 20 53 30q20 17 32 35c9 12 14 22 19 38s10 38 10 57c0 20-4 45-9 61q-7 25-18 40c-5 10-7 12-16 21-9 10-24 24-37 34-13 9-33 17-41 24-7 6-5 12-4 15q-2 4 7 3c7 1 13 3 34-1 21-3 62-16 91-21a632 632 0 0 1 271 0c24 4 31 8 47 13l45 17c18 8 41 18 61 31a541 541 0 0 1 153 152q18 27 28 50a878 878 0 0 1 35 103c5 21 9 33 12 61s3 88 4 107c2 19 3 8 5 9 2 2-6 8 8 1 13-7 52-29 73-44s34-28 52-46 41-46 56-65q20-26 29-46c8-13 10-14 18-34s22-57 28-84c7-27 7-58 9-80 1-22 0-35-1-54a481 481 0 0 0-53-194c-13-24-31-52-47-73a530 530 0 0 0-114-99q-33-19-58-31a650 650 0 0 0-99-28l-46-3h-107c-20-2-9-5-11-9s-2-12 0-16q1-4 7-7l27-9 46-7 65-2q32-1 65 3c21 3 46 11 64 16a464 464 0 0 1 256 183c13 17 18 23 31 46 12 23 34 69 43 93 10 24 11 28 16 50l14 80c3 14 1 5 3 6q3 3 8 1c2-1 0 5 6-7q11-20 31-65l45-111a2679 2679 0 0 0 76-279 1612 1612 0 0 0 21-343c-1-36-1-62-7-111s-23-142-31-183c-7-40-7-34-14-61-8-27-16-57-31-99s-40-107-60-153-36-77-62-122a1923 1923 0 0 0-184-266c-38-43-90-98-133-138-44-41-96-81-127-106s-39-29-61-44-36-26-72-46c-37-21-97-55-145-78a1921 1921 0 0 0-245-90 1334 1334 0 0 0-336-55c-40-2-99-4-148-3a1957 1957 0 0 0-248 26c-30 6-35 6-73 16s-106 28-156 46a1494 1494 0 0 0-406 211c-40 31-93 73-133 108-39 36-78 77-106 106-27 29-40 46-58 67l-46 59-76 111q-30 47-48 80a2814 2814 0 0 0-75 153c-12 28-17 39-30 76s-33 96-46 145a1912 1912 0 0 0-48 267 2164 2164 0 0 0-4 233 1469 1469 0 0 0 51 328 1340 1340 0 0 0 62 183c12 32 22 59 45 103 22 45 73 138 89 166 17 29 5 6 8 5 2-1 6 1 7-10 2-12 0-33 3-58a1421 1421 0 0 1 30-145 837 837 0 0 1 59-164c13-26 28-59 46-88a1133 1133 0 0 1 242-274 1321 1321 0 0 1 170-106 890 890 0 0 1 229-76q45-11 80-15c25-4 43-4 69-7 26-4 69-10 88-15s21-11 27-14c5-4 5-3 7-8 1-5 2-16 0-21-2-6 8-7-11-13s-72-14-103-22c-31-9-65-21-84-28s-17-7-29-15l-44-30c-7-7-3-6-2-8s-8 1 6-7l76-41c15-8 8-3 12-3s1-2 11 2c10 5 32 18 50 25a340 340 0 0 0 168 18c10-2 10-4 12-9s6-7-1-20c-7-14-33-49-42-63l-9-17q-3-5 0-7c1-2-8-1 9-6 18-4 78-19 96-21s5 0 13 8 23 27 36 39c14 12 33 24 46 32a144 144 0 0 0 69 21c14 0 37-1 53-5 16-3 27-7 42-15s35-20 50-33 26-38 42-45c16-6 37 4 53 7 17 3 37 9 46 12s7 3 7 6c1 3 8-3-2 11l-60 77c-10 14-4 6-5 11s0 15 1 19q2 6 6 8c2 2-1 3 7 4l42 2c17-1 33 1 57-5 25-6 69-22 88-29 20-7 24-10 31-15q9-6 13-11 5-3 10-2c3 0-5-6 11 2s70 37 84 46c15 9 3 6 3 8s5-1-3 5l-41 29c-11 7-8 7-24 14-16 8-49 22-72 30s-30 13-65 20c-35 6-108 13-145 19s-59 10-77 15c-17 5-16 7-26 14-11 8-20 12-37 29s-44 51-65 73-48 45-62 58c-15 12-12 10-25 18l-52 30-30 15-50 16c-18 5-29 9-57 15l-111 21c-27 6-32 8-53 15q-33 12-73 31-36 16-80 45a709 709 0 0 0-238 270c-15 28-22 49-29 69-8 20-12 30-17 49-5 20-11 39-16 69-4 31-11 83-13 115-2 31-2 45 0 76l14 111c5 28 11 44 16 61l14 42q11 29 32 71c16 28 40 68 60 97a712 712 0 0 0 299 246c33 15 81 34 111 44s39 11 69 17q43 8 107 16c42 4 107 8 148 9s78-2 97-4m915-1801-54 1c-17 0-21 2-49-3-28-6-87-21-119-32-31-10-47-20-72-33-26-13-64-34-80-44-16-9 2-2-16-11a1748 1748 0 0 0-190-90c-32-13-69-24-88-30s-17-2-27-5c-9-3-12-7-30-11a914 914 0 0 0-191-30c-29-2-36-2-61-1q-41-1-92 3a1494 1494 0 0 0-175 28 1889 1889 0 0 0-184 60c-24 10-21 6-68 31s-164 91-214 116-65 26-88 33c-23 8-32 9-49 12a606 606 0 0 1-164 2c-19-4-43-12-58-17-15-4-16-5-30-13-15-8-42-24-58-35a286 286 0 0 1-64-58q-15-17-30-41-17-28-32-61a352 352 0 0 1-22-127c0-22 1-50 5-72q6-32 18-61a361 361 0 0 1 164-183 366 366 0 0 1 125-44c19-3 40-1 50-3s10 10 12-7c3-17 0-70 3-95 2-25 6-37 11-54a388 388 0 0 1 66-127 509 509 0 0 1 87-79 578 578 0 0 1 104-48c19-5 52-10 68-13 16-2 14-1 27-1q20-1 50 2 30 2 68 12c26 8 69 30 84 35s3 2 8-7l19-48 15-27c5-9 8-14 19-27 10-12 25-33 42-49q27-25 59-46a384 384 0 0 1 94-44q20-7 50-12a507 507 0 0 1 137-1q30 5 53 13c16 5 26 8 42 16a561 561 0 0 1 96 58c12 10 18 16 31 31l44 57c10 15 10 17 16 30l19 49c5 10-1 10 8 7 9-2 32-15 48-21a410 410 0 0 1 109-26c18-2 28-4 53-2s69 9 95 16c27 7 49 19 65 26 16 8 19 11 31 19a595 595 0 0 1 73 62q17 19 34 42a439 439 0 0 1 47 107c5 17 8 26 10 50s0 78 3 95c2 17 2 5 12 7 11 2 32 0 50 3q27 3 57 13a412 412 0 0 1 137 79c17 13 22 20 32 32a347 347 0 0 1 62 99c8 16 9 17 14 38 4 22 12 61 12 92s-6 72-10 95c-5 24-8 30-16 46a499 499 0 0 1-59 95q-14 18-30 31c-11 10-20 18-35 28a705 705 0 0 1-88 46l-49 16q-23 5-46 6m-1146 957q10-1 16-9c6-5 13-16 17-21 3-6 2-6 3-12 0-5 2-11-2-19-3-7-13-20-19-26q-12-9-22-10c-6-2-8-2-15 0s-21 7-28 13q-10 11-15 23-3 10-1 19c2 8 9 20 13 27q8 8 16 12c4 3 5 3 11 4s19 1 26-1"/></svg>