clankerbend 0.1.0 → 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.
package/DEVELOPERS.md CHANGED
@@ -1,11 +1,11 @@
1
- # OneWhack Developers
1
+ # ClankerBend Developers
2
2
 
3
3
  ## Local Commands
4
4
 
5
5
  For protocol-only local testing without Codex Desktop:
6
6
 
7
7
  ```sh
8
- npx clankerbend codex --mock
8
+ npx clankerbend --mock
9
9
  ```
10
10
 
11
11
  For local development:
@@ -30,18 +30,18 @@ context visibility.
30
30
 
31
31
  ## Useful Docs
32
32
 
33
- - `docs/protocol.md`: OneWhack protocol
33
+ - `docs/protocol.md`: ClankerBend protocol
34
34
  - `docs/app-manifest.md`: app manifest format
35
- - `docs/author-guide.md`: writing OneWhack apps
35
+ - `docs/author-guide.md`: writing ClankerBend apps
36
36
  - `docs/launcher-profiles.md`: launcher profiles
37
37
  - `docs/app-lifecycle.md`: app installation and lifecycle model
38
38
 
39
39
  ## Release
40
40
 
41
- OneWhack publishes the same package payload under two npm names:
41
+ ClankerBend publishes the same package payload under two npm names:
42
42
 
43
43
  - `@onewillai/clankerbend`: scoped canonical package
44
- - `clankerbend`: short launcher name for `npx clankerbend codex`
44
+ - `clankerbend`: short launcher name for `npx clankerbend`
45
45
 
46
46
  ```sh
47
47
  npm test
package/README.md CHANGED
@@ -1,17 +1,21 @@
1
- # OneWhack
1
+ # ClankerBend
2
2
 
3
3
  <p align="center">
4
- <img src="./assets/onewhack.jpg" alt="OneWhack: mod your clanker with OneWill.ai" width="720">
4
+ <img src="./assets/clankerbend-banner.webp" alt="ClankerBend: mod your clankers with OneWill.ai" width="720">
5
5
  </p>
6
6
 
7
- OneWhack lets you build Codex Desktop plugins without rebuilding or re-signing
7
+ ClankerBend lets you build Codex Desktop plugins without rebuilding or re-signing
8
8
  Codex Desktop itself. It uses [CDP](https://x.com/OpenAIDevs/status/2065226355495895521)
9
9
  to provide a more stable API for tasks such as transcript navigation, chat annotation,
10
10
  attaching a file to the prompt window, opening the side panel, and so on.
11
11
 
12
- DEMO VIDEO TODO
12
+ <p align="center">
13
+ <a href="https://www.youtube.com/watch?v=FcQUxiL6enc">
14
+ <img src="./assets/clankerbend-demo-thumbnail.webp" alt="Watch the ClankerBend demo video" width="720">
15
+ </a>
16
+ </p>
13
17
 
14
- OneWhack is an independent [OneWill](https://onewill.ai) project compatible
18
+ ClankerBend is an independent [OneWill](https://onewill.ai) project compatible
15
19
  with OpenAI Codex Desktop on macOS. It is not affiliated with or endorsed by
16
20
  OpenAI (unless... 🥺).
17
21
 
@@ -21,10 +25,10 @@ You'll need macOS with [Codex Desktop](https://chatgpt.com/codex/)
21
25
  and [nodejs](https://nodejs.org/en/download). Then just:
22
26
 
23
27
  ```sh
24
- npx clankerbend codex
28
+ npx clankerbend
25
29
  ```
26
30
 
27
- That starts Codex Desktop with the default OneWhack profile and bundled apps:
31
+ That starts Codex Desktop with the default ClankerBend profile and bundled apps:
28
32
 
29
33
  - **VimNav**: Vim-style transcript navigation, number rails, role jumps, search,
30
34
  and a side panel.
@@ -35,15 +39,15 @@ That starts Codex Desktop with the default OneWhack profile and bundled apps:
35
39
 
36
40
  ## Runtime State
37
41
 
38
- OneWhack writes runtime state outside the package:
42
+ ClankerBend writes runtime state outside the package:
39
43
 
40
- - macOS: `~/Library/Application Support/OneWill/OneWhack`
44
+ - macOS: `~/Library/Application Support/OneWill/ClankerBend`
41
45
 
42
- Override with `ONEWILL_ONEWHACK_STATE_DIR`.
46
+ Override with `ONEWILL_CLANKERBEND_STATE_DIR`.
43
47
 
44
48
  ## Security
45
49
 
46
- OneWhack binds to `127.0.0.1` on an OS-assigned ephemeral port. The launcher
50
+ ClankerBend binds to `127.0.0.1` on an OS-assigned ephemeral port. The launcher
47
51
  prints the exact host URL, for example `Host: http://127.0.0.1:49152`.
48
- `/onewhack/*` endpoints require a bearer token by default. For local protocol
49
- debugging, you can set `ONEWILL_ONEWHACK_DISABLE_AUTH=1`.
52
+ `/clankerbend/*` endpoints require a bearer token by default. For local protocol
53
+ debugging, you can set `ONEWILL_CLANKERBEND_DISABLE_AUTH=1`.
package/apps/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # OneWhack Apps
1
+ # ClankerBend Apps
2
2
 
3
- This directory contains public OneWhack reference apps.
3
+ This directory contains public ClankerBend reference apps.
4
4
 
5
5
  - `vim-nav/`: Vim-like transcript navigation for Codex Desktop transcript
6
6
  anchors.
7
7
  - `sticky-notes/`: selected transcript notes and composer context chips through
8
- the shared OneWhack host API.
8
+ the shared ClankerBend host API.
9
9
 
10
10
  The public `apps/` tree should contain standalone, auditable apps without
11
11
  project-specific state or action vocabulary.
@@ -1,10 +1,10 @@
1
1
  # Sticky Notes
2
2
 
3
- Sticky Notes is a public OneWhack reference app for selected transcript text,
3
+ Sticky Notes is a public ClankerBend reference app for selected transcript text,
4
4
  anchored note overlays, composer context chips, and follow-up draft insertion.
5
5
 
6
6
  The app does not inspect or mutate Codex Desktop DOM. It contributes selection
7
- actions and handles note business logic through the OneWhack host API.
7
+ actions and handles note business logic through the ClankerBend host API.
8
8
 
9
9
  ```sh
10
10
  npm --prefix apps/sticky-notes test
@@ -1,5 +1,5 @@
1
1
  {
2
- "oneWhackVersion": "0.1",
2
+ "clankerbendVersion": "0.1",
3
3
  "appId": "onewill.sticky-notes",
4
4
  "version": "0.1.0",
5
5
  "name": "OneWill Sticky Notes",
@@ -1,11 +1,11 @@
1
1
  {
2
- "name": "onewhack-sticky-notes",
2
+ "name": "clankerbend-sticky-notes",
3
3
  "version": "0.1.0",
4
4
  "type": "module",
5
- "description": "OneWhack public reference app for transcript range notes and composer context.",
5
+ "description": "ClankerBend public reference app for transcript range notes and composer context.",
6
6
  "license": "MIT",
7
7
  "scripts": {
8
- "test": "node test-onewhack.mjs",
8
+ "test": "node test-clankerbend.mjs",
9
9
  "test:desktop-real": "node test-desktop-real.mjs"
10
10
  },
11
11
  "engines": {
@@ -18,7 +18,7 @@ els.insertContext.addEventListener("click", () => runAction("sticky.compose.inse
18
18
  bootstrap();
19
19
 
20
20
  async function bootstrap() {
21
- const state = await getJson("/onewhack/state");
21
+ const state = await getJson("/clankerbend/state");
22
22
  render(state);
23
23
  connectEvents();
24
24
  }
@@ -49,15 +49,15 @@ async function runAction(type, payload = {}) {
49
49
  payload,
50
50
  requestedAt: new Date().toISOString()
51
51
  };
52
- const result = await postJson(`/onewhack/apps/${encodeURIComponent(APP_ID)}/actions`, { action });
53
- const state = await getJson("/onewhack/state");
52
+ const result = await postJson(`/clankerbend/apps/${encodeURIComponent(APP_ID)}/actions`, { action });
53
+ const state = await getJson("/clankerbend/state");
54
54
  render(state);
55
55
  return result;
56
56
  }
57
57
 
58
58
  function readToken() {
59
59
  const params = new URLSearchParams(location.hash.startsWith("#") ? location.hash.slice(1) : location.hash);
60
- const value = params.get("onewhack_token") || "";
60
+ const value = params.get("clankerbend_token") || "";
61
61
  if (value) history.replaceState(null, "", location.pathname + location.search);
62
62
  return value;
63
63
  }
@@ -71,12 +71,12 @@ function headers(extra = {}) {
71
71
 
72
72
  function connectEvents() {
73
73
  if (!token) {
74
- const events = new EventSource("/onewhack/events");
74
+ const events = new EventSource("/clankerbend/events");
75
75
  events.addEventListener("state", (event) => render(JSON.parse(event.data)));
76
- events.addEventListener("action", () => getJson("/onewhack/state").then(render));
76
+ events.addEventListener("action", () => getJson("/clankerbend/state").then(render));
77
77
  return;
78
78
  }
79
- fetch("/onewhack/events", { headers: headers() }).then(async (res) => {
79
+ fetch("/clankerbend/events", { headers: headers() }).then(async (res) => {
80
80
  const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
81
81
  let buffer = "";
82
82
  while (true) {
@@ -90,7 +90,7 @@ function connectEvents() {
90
90
  const event = chunk.split(/\n/).find((line) => line.startsWith("event: "))?.slice(7);
91
91
  const data = chunk.split(/\n/).filter((line) => line.startsWith("data: ")).map((line) => line.slice(6)).join("\n");
92
92
  if (event === "state" && data) render(JSON.parse(data));
93
- if (event === "action") getJson("/onewhack/state").then(render);
93
+ if (event === "action") getJson("/clankerbend/state").then(render);
94
94
  }
95
95
  }
96
96
  });
@@ -35,7 +35,7 @@ export function createStickyNotesApp(options = {}) {
35
35
 
36
36
  getManifest(context) {
37
37
  return {
38
- oneWhackVersion: context.protocolVersion,
38
+ clankerbendVersion: context.protocolVersion,
39
39
  appId: STICKY_NOTES_APP_ID,
40
40
  name: "Sticky Notes",
41
41
  entry: context.entry,
@@ -170,11 +170,17 @@ function openNoteOverlay(action, context, selection) {
170
170
  label: "Add note",
171
171
  value: action.payload?.body || ""
172
172
  }],
173
- actions: [{
174
- label: "Save",
175
- type: "sticky.note.create",
176
- payload: { selection }
177
- }]
173
+ actions: [
174
+ {
175
+ label: "Cancel",
176
+ type: "overlay.close"
177
+ },
178
+ {
179
+ label: "Save",
180
+ type: "sticky.note.create",
181
+ payload: { selection }
182
+ }
183
+ ]
178
184
  }, { broadcast: false }).overlay;
179
185
  return applied(action, { overlay });
180
186
  }
@@ -232,27 +238,17 @@ function attachNoteFile(notes, noteId, context) {
232
238
 
233
239
  function noteMarkdown(note) {
234
240
  return [
235
- "# Sticky Note",
236
- "",
237
- `Note ID: ${note.noteId}`,
238
- `Status: ${note.status}`,
239
- `Anchor: ${note.anchorId}`,
240
- `Created: ${note.createdAt}`,
241
- `Updated: ${note.updatedAt}`,
241
+ "# Note",
242
242
  "",
243
- "## Note",
243
+ "The user made a note on the transcript above.",
244
244
  "",
245
- note.body,
246
- "",
247
- "## Highlighted Text",
245
+ "## Highlighted text",
248
246
  "",
249
247
  blockquote(note.quote),
250
248
  "",
251
- "## Range",
249
+ "## User notes",
252
250
  "",
253
- "```json",
254
- JSON.stringify(note.range || null, null, 2),
255
- "```",
251
+ note.body,
256
252
  ""
257
253
  ].join("\n");
258
254
  }
@@ -1,22 +1,22 @@
1
- # OneWhack Vim Navigator
1
+ # ClankerBend VimNav
2
2
 
3
- OneWhack is an independent OneWill project compatible with OpenAI Codex
3
+ ClankerBend is an independent OneWill project compatible with OpenAI Codex
4
4
  Desktop. It is not affiliated with or endorsed by OpenAI.
5
5
 
6
- Vim Navigator is the public reference app for OneWhack `0.1`. It demonstrates
7
- how an app registers with a central OneWhack host and uses transcript anchors,
6
+ VimNav is the public reference app for ClankerBend `0.1`. It demonstrates
7
+ how an app registers with a central ClankerBend host and uses transcript anchors,
8
8
  annotations, selection, and app-scoped actions without owning CDP directly.
9
9
 
10
10
  ## Run
11
11
 
12
12
  ```sh
13
- cd onewhack
13
+ cd clankerbend
14
14
  npm start
15
15
  ```
16
16
 
17
- The command starts a loopback OneWhack host on an ephemeral `127.0.0.1` port,
17
+ The command starts a loopback ClankerBend host on an ephemeral `127.0.0.1` port,
18
18
  launches Codex Desktop with CDP, injects transcript markers, and serves the Vim
19
- Navigator panel at `/apps/onewill.vim-nav/`.
19
+ VimNav panel at `/apps/onewill.vim-nav/`.
20
20
 
21
21
  For protocol-only mock mode:
22
22
 
@@ -41,7 +41,7 @@ errors, HTTP status/envelope alignment, and bearer-token behavior.
41
41
  Codex Desktop routes normal typing into the prompt composer, so enter transcript
42
42
  navigation mode first:
43
43
 
44
- - `Ctrl+Alt`: toggle Vim transcript mode
44
+ - `Cmd+Option`: toggle Vim transcript mode
45
45
  - `Escape` or `i`: exit Vim transcript mode
46
46
 
47
47
  While Vim transcript mode is active, plain Vim keys are captured for transcript
@@ -58,12 +58,12 @@ active.
58
58
 
59
59
  The focus-safe chords remain available as a fallback:
60
60
 
61
- - `Ctrl+Alt+j` or `Ctrl+Alt+Down`: next transcript anchor
62
- - `Ctrl+Alt+k` or `Ctrl+Alt+Up`: previous transcript anchor
63
- - `Ctrl+Alt+g` or `Ctrl+Alt+Home`: first transcript anchor
64
- - `Ctrl+Alt+G` or `Ctrl+Alt+End`: last transcript anchor
65
- - `Ctrl+Alt+{` or `Ctrl+Alt+PageUp`: previous user message
66
- - `Ctrl+Alt+}` or `Ctrl+Alt+PageDown`: next user message
61
+ - `Cmd+Option+j` or `Cmd+Option+Down`: next transcript anchor
62
+ - `Cmd+Option+k` or `Cmd+Option+Up`: previous transcript anchor
63
+ - `Cmd+Option+g` or `Cmd+Option+Home`: first transcript anchor
64
+ - `Cmd+Option+G` or `Cmd+Option+End`: last transcript anchor
65
+ - `Cmd+Option+{` or `Cmd+Option+PageUp`: previous user message
66
+ - `Cmd+Option+}` or `Cmd+Option+PageDown`: next user message
67
67
 
68
68
  Panel commands support:
69
69
 
@@ -72,9 +72,9 @@ Panel commands support:
72
72
  - `:42` or `42`: jump by visible ruler number
73
73
  - `:latest assistant` / `:latest user`: jump by role
74
74
 
75
- These commands are implemented as OneWhack app actions, not only as panel-local
75
+ These commands are implemented as ClankerBend app actions, not only as panel-local
76
76
  keyboard parsing. External clients can call the same actions through
77
- `POST /onewhack/apps/onewill.vim-nav/actions`.
77
+ `POST /clankerbend/apps/onewill.vim-nav/actions`.
78
78
 
79
79
  ## Writing Another App
80
80
 
@@ -90,9 +90,9 @@ Create an object with:
90
90
  Then register it with one host:
91
91
 
92
92
  ```js
93
- import { OneWhackHost, createMockTranscriptAdapter } from "../../host/src/index.js";
93
+ import { ClankerBendHost, createMockTranscriptAdapter } from "../../host/src/index.js";
94
94
 
95
- const host = new OneWhackHost({
95
+ const host = new ClankerBendHost({
96
96
  transcriptAdapter: createMockTranscriptAdapter({ defaultAppId: "example.app" })
97
97
  });
98
98
 
@@ -101,7 +101,7 @@ await host.start();
101
101
  ```
102
102
 
103
103
  The host serves all mounted apps through one central server and routes commands
104
- through `/onewhack/apps/:appId/actions`.
104
+ through `/clankerbend/apps/:appId/actions`.
105
105
 
106
106
  ## Real Desktop Validation
107
107
 
@@ -109,15 +109,15 @@ The default `npm test` path is mock/protocol-only and does not launch Codex
109
109
  Desktop. To run the real Desktop regression harness:
110
110
 
111
111
  ```sh
112
- cd onewhack
112
+ cd clankerbend
113
113
  npm run test:vim-nav:desktop-real
114
114
  ```
115
115
 
116
- The harness starts the Vim Navigator host, launches Codex Desktop with CDP,
116
+ The harness starts the VimNav host, launches Codex Desktop with CDP,
117
117
  creates a fresh chat, seeds deterministic transcript turns, injects the host
118
118
  renderer bridge, and verifies:
119
119
 
120
- - `Ctrl+Alt` toggles Vim transcript mode without moving scroll
120
+ - `Cmd+Option` toggles Vim transcript mode without moving scroll
121
121
  - `G` lands on the last known transcript item
122
122
  - repeated `k` walks to transcript item `1` without skipping or renumbering
123
123
  - `12G`, `gg`, and oversized `number+G` land on the expected anchors
@@ -1,8 +1,8 @@
1
1
  {
2
- "oneWhackVersion": "0.1",
2
+ "clankerbendVersion": "0.1",
3
3
  "appId": "onewill.vim-nav",
4
4
  "version": "0.1.0",
5
- "name": "OneWill VimNav",
5
+ "name": "VimNav",
6
6
  "description": "Public reference app for keyboard transcript navigation in Codex Desktop.",
7
7
  "distribution": {
8
8
  "kind": "local",
@@ -15,7 +15,7 @@
15
15
  "entrypoint": {
16
16
  "kind": "module",
17
17
  "module": "./src/vim-nav-app.js",
18
- "factory": "createVimNavigatorApp",
18
+ "factory": "createVimNavApp",
19
19
  "publicDir": "./public"
20
20
  },
21
21
  "platform": {
@@ -45,7 +45,7 @@
45
45
  "appServerRollback": false
46
46
  },
47
47
  "panel": {
48
- "title": "Vim Nav",
48
+ "title": "VimNav",
49
49
  "reloadPolicy": "preserve",
50
50
  "preferredWidth": 360
51
51
  },
@@ -1,13 +1,13 @@
1
1
  {
2
- "name": "onewhack-vim-nav",
2
+ "name": "clankerbend-vim-nav",
3
3
  "version": "0.1.0",
4
4
  "type": "module",
5
- "description": "Public OneWhack reference app for Vim-like Codex Desktop transcript navigation.",
5
+ "description": "Public ClankerBend reference app for Vim-like Codex Desktop transcript navigation.",
6
6
  "license": "MIT",
7
7
  "scripts": {
8
8
  "start": "node server.mjs",
9
9
  "start:mock": "node server.mjs --mock",
10
- "test": "node test-onewhack.mjs",
10
+ "test": "node test-clankerbend.mjs",
11
11
  "test:desktop-real": "node test-desktop-real.mjs"
12
12
  },
13
13
  "engines": {
@@ -20,7 +20,7 @@ const token = readToken();
20
20
 
21
21
  els.openPanel.addEventListener("click", async () => {
22
22
  try {
23
- await postJson("/onewhack/panel/open", {});
23
+ await postJson("/clankerbend/panel/open", {});
24
24
  } catch (err) {
25
25
  els.commandStatus.textContent = err.message;
26
26
  }
@@ -36,7 +36,7 @@ bootstrap();
36
36
 
37
37
  async function bootstrap() {
38
38
  try {
39
- const state = await getJson("/onewhack/state");
39
+ const state = await getJson("/clankerbend/state");
40
40
  render(state, true);
41
41
  connectEvents();
42
42
  } catch (err) {
@@ -47,7 +47,7 @@ async function bootstrap() {
47
47
 
48
48
  function readToken() {
49
49
  const params = new URLSearchParams(location.hash.startsWith("#") ? location.hash.slice(1) : location.hash);
50
- const value = params.get("onewhack_token") || "";
50
+ const value = params.get("clankerbend_token") || "";
51
51
  if (value) history.replaceState(null, "", location.pathname + location.search);
52
52
  return value;
53
53
  }
@@ -61,17 +61,17 @@ function headers(extra = {}) {
61
61
 
62
62
  async function connectEvents() {
63
63
  if (!token) {
64
- const events = new EventSource("/onewhack/events");
64
+ const events = new EventSource("/clankerbend/events");
65
65
  events.addEventListener("state", (event) => render(JSON.parse(event.data)));
66
- events.addEventListener("app-state", () => getJson("/onewhack/state").then((state) => render(state)));
67
- events.addEventListener("action", () => getJson("/onewhack/state").then((state) => render(state)));
66
+ events.addEventListener("app-state", () => getJson("/clankerbend/state").then((state) => render(state)));
67
+ events.addEventListener("action", () => getJson("/clankerbend/state").then((state) => render(state)));
68
68
  events.addEventListener("error", () => {
69
69
  els.subtitle.textContent = "event stream interrupted";
70
70
  });
71
71
  return;
72
72
  }
73
73
 
74
- const res = await fetch("/onewhack/events", { headers: headers() });
74
+ const res = await fetch("/clankerbend/events", { headers: headers() });
75
75
  if (!res.ok || !res.body) throw new Error(`events failed: ${res.status}`);
76
76
  const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
77
77
  let buffer = "";
@@ -94,7 +94,7 @@ function handleSseChunk(chunk) {
94
94
  const data = lines.filter((line) => line.startsWith("data: ")).map((line) => line.slice(6)).join("\n");
95
95
  if (!data || event === "heartbeat") return;
96
96
  if (event === "state") render(JSON.parse(data));
97
- if (event === "app-state" || event === "action") getJson("/onewhack/state").then((state) => render(state));
97
+ if (event === "app-state" || event === "action") getJson("/clankerbend/state").then((state) => render(state));
98
98
  }
99
99
 
100
100
  async function runCommand(raw) {
@@ -193,8 +193,8 @@ async function runAction(type, payload = {}, anchorId) {
193
193
  payload,
194
194
  requestedAt: new Date().toISOString()
195
195
  };
196
- const result = await postJson(`/onewhack/apps/${encodeURIComponent(APP_ID)}/actions`, { action });
197
- if (result.ok) getJson("/onewhack/state").then((state) => render(state));
196
+ const result = await postJson(`/clankerbend/apps/${encodeURIComponent(APP_ID)}/actions`, { action });
197
+ if (result.ok) getJson("/clankerbend/state").then((state) => render(state));
198
198
  return result.ok ? { ok: true, message: result.status || "ok" } : { ok: false, error: result.error || "action failed" };
199
199
  }
200
200
 
@@ -3,14 +3,14 @@
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>Vim Nav</title>
6
+ <title>VimNav</title>
7
7
  <link rel="stylesheet" href="./styles.css">
8
8
  </head>
9
9
  <body>
10
10
  <main class="shell">
11
11
  <header class="topbar">
12
12
  <div>
13
- <strong>Vim Nav</strong>
13
+ <strong>VimNav</strong>
14
14
  <p id="subtitle">Transcript keyboard navigation</p>
15
15
  </div>
16
16
  <button id="open-panel" type="button">Panel</button>
@@ -1,10 +1,10 @@
1
1
  import { dirname, join } from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
- import { launchOneWhackCodex } from "../../server.mjs";
3
+ import { launchClankerBendCodex } from "../../server.mjs";
4
4
 
5
5
  const __dirname = dirname(fileURLToPath(import.meta.url));
6
6
 
7
- await launchOneWhackCodex({
7
+ await launchClankerBendCodex({
8
8
  mock: process.argv.includes("--mock"),
9
9
  runDir: join(__dirname, "run")
10
10
  });
@@ -1,9 +1,9 @@
1
1
  export const VIM_NAV_APP_ID = "onewill.vim-nav";
2
2
 
3
- export function createVimNavigatorApp(options = {}) {
3
+ export function createVimNavApp(options = {}) {
4
4
  return {
5
5
  appId: VIM_NAV_APP_ID,
6
- name: "Vim Navigator",
6
+ name: "VimNav",
7
7
  publicDir: options.publicDir,
8
8
  contributes: {
9
9
  panel: true,
@@ -21,16 +21,16 @@ export function createVimNavigatorApp(options = {}) {
21
21
  appServerRollback: false
22
22
  },
23
23
  panel: {
24
- title: "Vim Nav",
24
+ title: "VimNav",
25
25
  reloadPolicy: "preserve",
26
26
  preferredWidth: 360
27
27
  },
28
28
 
29
29
  getManifest(context) {
30
30
  return {
31
- oneWhackVersion: context.protocolVersion,
31
+ clankerbendVersion: context.protocolVersion,
32
32
  appId: VIM_NAV_APP_ID,
33
- name: "Vim Navigator",
33
+ name: "VimNav",
34
34
  entry: context.entry,
35
35
  contributes: this.contributes,
36
36
  permissions: this.permissions,
Binary file
@@ -0,0 +1,26 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 520" role="img" aria-labelledby="title desc">
2
+ <title id="title">ClankerBend</title>
3
+ <desc id="desc">ClankerBend banner: mod your clanker with OneWill.ai</desc>
4
+ <rect width="1200" height="520" fill="#fbfbf8"/>
5
+ <g transform="translate(600 208)">
6
+ <rect x="-162" y="-118" width="324" height="236" rx="42" fill="#f7fbff" stroke="#17324d" stroke-width="10"/>
7
+ <rect x="-108" y="-58" width="216" height="104" rx="28" fill="#17324d"/>
8
+ <circle cx="-48" cy="-7" r="9" fill="#f7fbff"/>
9
+ <path d="M33 -7h50" stroke="#f7fbff" stroke-width="10" stroke-linecap="round"/>
10
+ <path d="M-92 68c34 25 150 25 184 0" fill="none" stroke="#2368a2" stroke-width="12" stroke-linecap="round"/>
11
+ <path d="M-174 -34h-68M174 -34h68" stroke="#17324d" stroke-width="12" stroke-linecap="round"/>
12
+ <circle cx="-256" cy="-34" r="18" fill="#2b83c6" stroke="#17324d" stroke-width="8"/>
13
+ <circle cx="256" cy="-34" r="18" fill="#2b83c6" stroke="#17324d" stroke-width="8"/>
14
+ <path d="M-78 120l-30 64M78 120l30 64" stroke="#17324d" stroke-width="12" stroke-linecap="round"/>
15
+ <circle cx="-118" cy="204" r="26" fill="#2b83c6" stroke="#17324d" stroke-width="8"/>
16
+ <circle cx="118" cy="204" r="26" fill="#2b83c6" stroke="#17324d" stroke-width="8"/>
17
+ <g transform="translate(196 -126) rotate(-28)">
18
+ <rect x="-22" y="-18" width="222" height="36" rx="18" fill="#17324d"/>
19
+ <rect x="-144" y="-55" width="150" height="110" rx="24" fill="#df9441" stroke="#17324d" stroke-width="8"/>
20
+ <path d="M-118 -40v80M-82 -48v96M-46 -44v88" stroke="#f0b56a" stroke-width="7" stroke-linecap="round"/>
21
+ </g>
22
+ </g>
23
+ <text x="600" y="405" text-anchor="middle" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="58" font-weight="800" fill="#080808">mod your clanker</text>
24
+ <text x="600" y="462" text-anchor="middle" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="46" fill="#080808">with OneWill.ai</text>
25
+ <text x="600" y="76" text-anchor="middle" font-family="Arial Black, Arial, sans-serif" font-size="62" font-weight="900" fill="#df6f24" stroke="#742f16" stroke-width="4" paint-order="stroke">CLANKERBEND</text>
26
+ </svg>