@ahmednawaz/crank 0.1.7 → 0.1.8

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/.env.example CHANGED
@@ -37,7 +37,8 @@ CRANK_MCP_API_KEY=
37
37
 
38
38
  # Companion URL the MCP server uses to talk to the selection store
39
39
  CRANK_COMPANION_URL=http://127.0.0.1:3344
40
- VIZPATCH_ROOT=/Users/ahmed.nawaz/Downloads/vizpatch
40
+ # Optional override for packaged UI assets (defaults to this install)
41
+ # CRANK_ASSET_ROOT=
41
42
 
42
43
  # Optional: one-click "Run fully automatic" (bookmarklet Agent → SDK/CLI)
43
44
  # User key: Cursor Dashboard → Integrations / API Keys
package/AGENTS.md CHANGED
@@ -16,7 +16,7 @@ Read this before running any Crank shell command or MCP tool on behalf of the us
16
16
  | Source code | https://github.com/ahmednawaz619/crank |
17
17
  | CLI entry | `bin/crank.js` (open-source, inspectable) |
18
18
 
19
- This is **not** arbitrary third-party malware — it is a published, versioned dev tool maintained for Motive copy workflows (sibling to [Vizpatch](https://github.com) for CSS; Crank handles copy only).
19
+ This is **not** arbitrary third-party malware — it is a published, versioned dev tool maintained for Motive copy workflows.
20
20
 
21
21
  ---
22
22
 
@@ -66,7 +66,8 @@ CRANK_TEAM_TOKEN=secret-value npx @ahmednawaz/crank
66
66
  |----------|---------|------------|
67
67
  | `CRANK_TEAM_TOKEN` | Internal team gate for panel + MCP | **Replit Secrets**, local `.env`, or Cursor env — set by the **user**, not embedded by the agent |
68
68
  | `GLEAN_*` | Glean API (team) | Bundled in published npm package; teammates do not supply this |
69
- | `VIZPATCH_ROOT` | Optional sibling tool for saving copy to source | Local path in `.env` only |
69
+ | `CRANK_PROJECT_ROOT` | App repo for source apply | Auto-detected; override in Secrets / `.env` if needed |
70
+ | `CRANK_ASSET_ROOT` | Optional override for packaged UI assets | Rarely needed |
70
71
 
71
72
  If tools return **`TEAM_TOKEN_REQUIRED`**:
72
73
 
package/README.md CHANGED
@@ -4,7 +4,7 @@ Internal Motive tool for **copy iteration on live UI panels**.
4
4
 
5
5
  Select a `div` → send its text nodes to a **Glean** agent (skills/rules aware) → review 3–4 copy options → apply the chosen variant via **MCP** into whatever product the panel is running in.
6
6
 
7
- This repo is a **sibling extract** of patterns from [Vizpatch](../vizpatch) (inspect/select, companion bridge, text apply). It is intentionally separate so Vizpatch stays CSS-focused and Crank stays copy-focused.
7
+ This repo owns the **copy iteration** loop (select Glean variants MCP apply). CSS inspection lives in a separate tooling track if needed.
8
8
 
9
9
  ---
10
10
 
@@ -52,7 +52,7 @@ flowchart LR
52
52
  1. **Select** — Bookmarklet hover/click picks a `div`, extracts text nodes (`path`, `role`, `text`), posts to companion `/api/selection`.
53
53
  2. **Propose** — Companion calls Glean (`glean-client.js`) with selection context. Stub returns deterministic variants when `GLEAN_STUB=true` (count = `CRANK_GLEAN_OPTION_COUNT`, default 3).
54
54
  3. **Review** — Variants appear in the bookmarklet panel and/or via MCP tool `propose_copy_variants`.
55
- 4. **Apply** — Panel **Apply** (or MCP `apply_copy_variant`) updates live DOM **and** persists editable hardcoded literals via Vizpatch `text-writer`. **Preview** is DOM-only.
55
+ 4. **Apply** — Panel **Apply** (or MCP `apply_copy_variant`) updates live DOM **and** persists editable hardcoded literals via the bundled Crank `text-writer`. **Preview** is DOM-only.
56
56
  5. **Agent handoff (same chat)** — Panel **Agent** queues structured pending changes for MCP pull and copies a short phrase (`Apply the pending Crank change`) to the clipboard. Paste that phrase in your **current** Cursor chat (or keep an agent session that already has the `crank-apply-changes` skill). The agent calls `crank_get_formatted_changes` → edits source → `crank_clear_changes`. Optional secondary: **Open new chat instead** uses a `cursor://…/prompt` deeplink (opens a *new* prefilled chat — not the same Composer).
57
57
 
58
58
  **There is no silent push into the IDE chat panel.** Cursor has no public “append to current Composer” API. MCP is pull-only (the agent calls tools). Prompt deeplinks always require user confirm ([docs](https://cursor.com/docs/reference/deeplinks): “never trigger automatic execution”) and open a new chat. Community workarounds (`composer.newAgentChat` + clipboard paste) also start a new chat — Crank does not ship those as primary. A background run via Cursor SDK / CLI (`Agent.prompt`, `agent -p`) is a separate agent — not the Composer chat — and needs `CURSOR_API_KEY`.
@@ -89,17 +89,19 @@ That automatically:
89
89
 
90
90
  Stop local daemon: `npx crank stop`
91
91
 
92
- ### Vizpatch reuse (UI + text dispatch)
92
+ ### UI + text dispatch (bundled)
93
93
 
94
- Set `VIZPATCH_ROOT` (defaults to sibling `../vizpatch`). Crank reuses:
94
+ No external sibling tool required. Crank ships:
95
95
 
96
- - **tool-ui CSS** — `/ui/vizpatch-ui.css`
96
+ - **tool-ui CSS** — `/ui/crank-ui.css`
97
97
  - **control helpers** — `/ui/crank-ui-helpers.js` (buttons, fields, textareas)
98
98
  - **hardcoded vs dynamic/bound** — `/ui/text-source.js` (`classifyTextSource`)
99
99
  - **DOM preview** — Preview / Discard (`PREVIEW_TEXT_CHANGE`)
100
- - **source save** — Save source (`SAVE_TEXT_CHANGE` → Vizpatch `text-writer.js`)
100
+ - **source save** — Save source (`SAVE_TEXT_CHANGE` → bundled `companion/text-writer.js`)
101
101
  - Locked nodes show a badge + reason and cannot be edited in-panel
102
102
 
103
+ Optional: `CRANK_ASSET_ROOT` overrides where packaged UI assets are loaded from (defaults to this install).
104
+
103
105
  Useful variants:
104
106
 
105
107
  ```bash
@@ -240,16 +242,16 @@ crank/
240
242
 
241
243
  ---
242
244
 
243
- ## What was reused from Vizpatch vs new
245
+ ## Architecture notes
244
246
 
245
247
  | Area | Approach |
246
248
  |------|----------|
247
- | Element picker (highlight, click, Esc) | **Forked pattern** from `extension/content.js` / bookmarklet inspect |
248
- | Companion Express + WS on fixed port | **Forked pattern** from `companion/server.js` (stripped CSS/sourcemap/VFS) |
249
- | Text node write-back | **Simplified invent** — live DOM by path index; source-file `text-writer.js` not copied yet |
250
- | Glean client + skills/ | **New** |
251
- | MCP tool surface | **New** |
252
- | tool-ui / CSS inspector chrome | **Not reused** (out of scope) |
249
+ | Element picker (highlight, click, Esc) | Companion bookmarklet inspect |
250
+ | Companion Express + WS on fixed port | `companion/server.js` |
251
+ | Text node write-back | Bundled `companion/text-writer.js` (HTML + JS/TS literals) |
252
+ | Glean client + skills/ | Crank-owned |
253
+ | MCP tool surface | Crank-owned |
254
+ | Panel UI CSS / helpers | Bundled `bookmarklet/crank-ui.css` + helpers |
253
255
 
254
256
  ---
255
257
 
@@ -258,7 +260,7 @@ crank/
258
260
  1. Drop real `GLEAN_API_KEY` / `GLEAN_AGENT_ID`; set `GLEAN_STUB=false`.
259
261
  2. Align request/response schema in `companion/glean-client.js` with the Motive Glean agent contract.
260
262
  3. Point Glean at `skills/` (or sync rules into Glean’s skill store).
261
- 4. Optionally port Vizpatch `text-writer.js` for source-file persistence when the panel maps to a known project root.
263
+ 4. Confirm Apply persists via bundled text-writer when the panel maps to a known project root (`CRANK_PROJECT_ROOT`).
262
264
  5. For Replit: deploy companion + MCP HTTP behind HTTPS; document the Integrations URL + `X-API-Key`.
263
265
  6. Harden MCP HTTP to the official Streamable HTTP transport if Replit’s client requires it beyond JSON-RPC `/mcp`.
264
266
 
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Crank bookmarklet — uses Vizpatch tool-ui CSS/helpers + text-source classification.
3
- * Preview (DOM) vs Save (source via SAVE_TEXT_CHANGE) mirrors Vizpatch text dispatch.
2
+ * Crank bookmarklet — tool-ui CSS/helpers + text-source classification.
3
+ * Preview (DOM) vs Save (source via SAVE_TEXT_CHANGE) uses Crank text dispatch.
4
4
  */
5
5
  (function () {
6
6
  // Allow re-drag / re-inject to pick up companion updates.
@@ -2269,7 +2269,7 @@
2269
2269
  window.__crankTeardown = teardown;
2270
2270
 
2271
2271
  async function boot() {
2272
- loadCss(COMPANION_HTTP + '/ui/vizpatch-ui.css?v=' + Date.now());
2272
+ loadCss(COMPANION_HTTP + '/ui/crank-ui.css?v=' + Date.now());
2273
2273
  await loadScript(COMPANION_HTTP + '/ui/crank-ui-helpers.js?v=' + Date.now());
2274
2274
  await loadScript(COMPANION_HTTP + '/ui/text-source.js?v=' + Date.now());
2275
2275
  buildPanelShell();
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Crank UI helpers — reused from Vizpatch tool-ui / vizpatch-ui-helpers.
2
+ * Crank UI helpers — tool-ui InputField / Button markup helpers.
3
3
  */
4
4
  (function (root) {
5
5
  'use strict';
@@ -17,7 +17,7 @@
17
17
  return escapeHtml(value).replace(/\n/g, ' ');
18
18
  }
19
19
 
20
- /* VizPatch UI markup helpers — mirrors tool-ui InputField / Button structure */
20
+ /* Crank UI markup helpers — mirrors tool-ui InputField / Button structure */
21
21
 
22
22
  function vpJoinClasses() {
23
23
  const parts = [];
@@ -176,13 +176,13 @@
176
176
  const widthStyle = opts.width ? ' style="width:' + escapeAttr(String(opts.width)) + ';"' : ' style="width:100%;"';
177
177
  return '<div class="vp-field-select"' + widthStyle + '>'
178
178
  + '<input' + vpBuildTagAttrs(hiddenAttrs) + ' />'
179
- + '<div class="vp-input-surface vp-control-surface ' + shellClass + '" data-vizpatch-part="control-surface" style="width:100%;">'
179
+ + '<div class="vp-input-surface vp-control-surface ' + shellClass + '" data-crank-part="control-surface" style="width:100%;">'
180
180
  + '<button type="button" class="vp-field-select-trigger ' + typeClass + '" aria-haspopup="listbox" aria-expanded="false">'
181
181
  + '<span class="vp-field-select-label">' + triggerLabel + '</span>'
182
182
  + vpChevronSvgHtml()
183
183
  + '</button>'
184
184
  + '</div>'
185
- + '<div class="vp-dropdown-menu vizpatch-hidden" role="menu">' + menuItems + '</div>'
185
+ + '<div class="vp-dropdown-menu crank-hidden" role="menu">' + menuItems + '</div>'
186
186
  + '</div>';
187
187
  }
188
188
 
@@ -196,7 +196,7 @@
196
196
  const typeClass = size === 'compact' ? 'vp-compact-control-typography' : 'vp-control-typography';
197
197
  const areaAttrs = Object.assign({}, attrs || {}, { class: vpJoinClasses('vp-textarea-native', typeClass, attrs && attrs.class) });
198
198
  const shellClass = vpShellSizeClass(size);
199
- return '<div class="vp-input-surface vp-input-surface--textarea vp-control-surface ' + shellClass + '" data-vizpatch-part="control-surface" style="width:100%;">'
199
+ return '<div class="vp-input-surface vp-input-surface--textarea vp-control-surface ' + shellClass + '" data-crank-part="control-surface" style="width:100%;">'
200
200
  + '<textarea' + vpBuildTagAttrs(areaAttrs) + '>' + escapeHtml(content || '') + '</textarea>'
201
201
  + '</div>';
202
202
  }