@brainervirus/workit-cursor 0.7.1 → 0.8.0

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.
@@ -2,7 +2,32 @@
2
2
  "name": "workit",
3
3
  "displayName": "Workit",
4
4
  "description": "OpenCode-style verify, PR, changelog, commit, and session handoff for Cursor",
5
- "version": "0.7.1",
5
+ "version": "0.8.0",
6
+ "author": {
7
+ "name": "Cristhofer Pincetti"
8
+ },
9
+ "publisher": "BrainerVirus",
10
+ "homepage": "https://github.com/BrainerVirus/workit",
11
+ "repository": "https://github.com/BrainerVirus/workit",
12
+ "license": "MIT",
13
+ "logo": "assets/logo.svg",
14
+ "keywords": [
15
+ "agent",
16
+ "cursor",
17
+ "mcp",
18
+ "workflow",
19
+ "workit"
20
+ ],
21
+ "category": "Developer Tools",
22
+ "tags": [
23
+ "workflow",
24
+ "agent",
25
+ "mcp",
26
+ "pr",
27
+ "changelog",
28
+ "commit",
29
+ "handoff"
30
+ ],
6
31
  "skills": [
7
32
  "skills/",
8
33
  "vendor/superpowers/skills/"
package/README.md CHANGED
@@ -1,21 +1,103 @@
1
1
  # @brainervirus/workit-cursor
2
2
 
3
- Cursor plugin for workit — MCP server, hooks, rules, and skills for agentic coding workflows (specs, plans, YouTrack, CI-gated commits).
3
+ Cursor plugin for workit — MCP server, session-start hook, rules, and skills for agentic coding workflows (specs, plans, YouTrack, CI-gated commits).
4
4
 
5
5
  ## Install
6
6
 
7
- Run the installer (recommended) or add the MCP server manually:
7
+ **Wizard (recommended)** — configures Cursor and/or OpenCode and installs the platform packages:
8
8
 
9
9
  ```bash
10
10
  npx @brainervirus/workit-cli init
11
11
  ```
12
12
 
13
+ **npm (package)** — the package is published as `@brainervirus/workit-cursor`; its `.cursor-plugin/plugin.json` identifies the plugin as `workit` (display name `Workit`) and registers its MCP server, hook, rules, and skills. A local (non-npm) install lives at `~/.cursor/plugins/local/workit` and writes `enabled_plugins.workit = true`; the installer migrates exact legacy `workflow-toolkit` entries only after the replacement succeeds.
14
+
15
+ **Marketplace** — see [Marketplace](#marketplace).
16
+
17
+ **Manual** — add the MCP server to `.cursor/mcp.json`:
18
+
19
+ ```json
20
+ {
21
+ "mcpServers": {
22
+ "workit": {
23
+ "command": "npx",
24
+ "args": [
25
+ "-y",
26
+ "--package=@brainervirus/workit-cursor@latest",
27
+ "workit-cursor-mcp",
28
+ "${workspaceFolder}"
29
+ ]
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ ### Requirements
36
+
37
+ - **Node.js ≥ 22** — the MCP server and session-start hook are self-contained Node bundles invoked through `npx`.
38
+ - **Network** — `npx -y …@latest` resolves and downloads the package on first run in each environment; a machine that cannot reach the npm registry cannot start the MCP server or hook (see [Runtime](#runtime)).
39
+
13
40
  ## What it provides
14
41
 
15
- - MCP server (41 `workflow_*` tools)
16
- - Session-start contract hook
17
- - Canonical rules (locale, branch policy, doc delivery)
18
- - The same 12 `wk-*` skills as OpenCode
42
+ - MCP server exposing the `workflow_*` tools (branch setup, PR create/context, docs validate/promote, YouTrack post/log/time, templates, rules, presentation, doctor, handoff).
43
+ - Session-start contract hook.
44
+ - 4 rules and 12 `wk-*` skills (plus 14 sanitized Superpowers skills).
45
+
46
+ ## Host limitations
47
+
48
+ Cursor adapts workit through policy-only confirmation: approvals and commits are recorded as policy decisions (`attested: false`) rather than fabricated delegated identity, and subagent-driven plan execution is not supported on this host. OpenCode records native `question` receipts and runs delegated tasks; see the root [README](../../README.md#host-capabilities) for the full host-capability matrix.
49
+
50
+ ## Configuration
51
+
52
+ - Plugin metadata: `packages/workit-cursor/.cursor-plugin/plugin.json` (`name: "workit"`, `displayName: "Workit"`).
53
+ - MCP server: `mcp.json`.
54
+ - Session-start hook: `hooks/hooks-cursor.json`.
55
+ - Rules: `rules/` (`ask-question-only.mdc`, `cursor-todowrite.mdc`, `no-worktrees.mdc`, `sdd-docs-path.mdc`).
56
+ - Skills: `skills/` (12 `wk-*`) and `vendor/superpowers/skills/` (14).
57
+
58
+ ## Runtime
59
+
60
+ Cursor launches the MCP server and session-start hook through `npx`, so the shipped manifests contain no repository-relative `dist` paths:
61
+
62
+ - **MCP server** — `npx -y --package=@brainervirus/workit-cursor@latest workit-cursor-mcp ${workspaceFolder}`. It speaks the MCP stdio protocol; `stdout` is reserved for protocol messages and diagnostics go to `stderr`.
63
+ - **Session-start hook** — `npx -y --package=@brainervirus/workit-cursor@latest workit-cursor-session-start`. It emits valid hook output and a diagnostic on runtime failure, and remains fail-open where Cursor's hook contract requires startup continuity.
64
+ - `npx` startup or network failure is surfaced by Cursor as an MCP/hook startup failure; Workit never silently substitutes stale local runtime code.
65
+
66
+ The `@latest` tag means the runtime updates independently of the Marketplace metadata: Cursor reviews plugin metadata from Git, while npm serves the runtime. See [Update review](#update-review).
67
+
68
+ ## Security and data handling
69
+
70
+ - **Secrets** — tokens are stored in files with mode 600 (`~/.config/workit/*.token`) and are never printed by tools; edit them locally.
71
+ - **Logs** — a persistent JSONL journal records redacted structured diagnostics under the configuration directory; Cursor keeps `stderr` diagnostics for protocol safety, and `stdout` remains reserved for the MCP/hook protocol (the logger never writes to it).
72
+ - **External interactions** — Git/VCS (branch resolution, PR/MR creation) and YouTrack (task updates, time logging) happen only when you invoke the corresponding tools; local setup copies files under `~/.cursor/plugins/local/workit` and `~/.config/workit/`.
73
+
74
+ ## Plugin layout
75
+
76
+ | Path | Contents |
77
+ | --- | --- |
78
+ | `mcp/` + `dist/mcp-server.js` | MCP server entry (built). |
79
+ | `hooks/` | session-start hook manifest. |
80
+ | `rules/` | 4 `.mdc` rules. |
81
+ | `skills/` | 12 `wk-*` skills. |
82
+ | `vendor/superpowers/skills/` | 14 sanitized Superpowers skills. |
83
+ | `.cursor-plugin/plugin.json` | authoritative plugin manifest. |
84
+
85
+ ## Package scripts
86
+
87
+ ```bash
88
+ bun run build # bundle dist/mcp-server.js, dist/cursor-session-start.js, sanitize vendor skills
89
+ ```
90
+
91
+ From the repository root, `bun run validate:cursor-marketplace` validates the tracked Marketplace artifact against the official Cursor JSON schemas and clean-checkout invariants (component paths, frontmatter, logo, sanitized vendor parity, no ignored-`dist` runtime references).
92
+
93
+ ## Marketplace
94
+
95
+ The repository root carries `.cursor-plugin/marketplace.json`, indexing `packages/workit-cursor` (plugin `workit` / `Workit`). Cursor installs Marketplace plugins from Git and does not build the repository, so all declared skills, rules, and assets are tracked and validated in CI — the runtime is launched from npm as described in [Runtime](#runtime).
96
+
97
+ - **Installing from Marketplace** — a Marketplace admin adds the repository URL through Cursor's authenticated publisher flow; end users then install the plugin from the Cursor Marketplace UI, which reads `.cursor-plugin/plugin.json` and the tracked components directly from Git.
98
+ - **Submission** — Marketplace submission is a separate, later authenticated action at `https://cursor.com/marketplace/publish`. It is **not** performed here and no publication or acceptance is claimed; the repository is kept validated and submission-ready.
99
+ - **Update review** — Git plugin metadata (manifest, rules, skills, assets) is reviewed by Cursor on Marketplace updates, while the npm runtime tagged `@latest` updates independently. Reviewing an npm runtime change is a manual step: pin `--package=@brainervirus/workit-cursor@<version>` in `mcp.json` / `hooks-cursor.json` if you need immutable reviewed code instead of `@latest`.
100
+ - **Troubleshooting** — `workit doctor` (or the `workflow_doctor` tool) reports installation health including runtime, token, VCS/YouTrack, and log-writability checks; it exits nonzero on failure. An MCP/hook startup failure with no network is an `npx`/registry reachability issue, not a Workit defect.
19
101
 
20
102
  ## Docs
21
103
 
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
2
+ <rect width="64" height="64" rx="14" fill="#111827"/>
3
+ <path d="M18 33l10 10 18-20" fill="none" stroke="#34d399" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
@@ -21826,7 +21826,7 @@ var SUPPORT_MATRIX;
21826
21826
  var init_support_matrix = __esm(() => {
21827
21827
  SUPPORT_MATRIX = {
21828
21828
  bun: "1.3.14",
21829
- node: { minimum: "20", current: "22" },
21829
+ node: { minimum: "22", current: "22" },
21830
21830
  opencode: { minimum: "1.15.0", current: "1.17.7" },
21831
21831
  os: ["ubuntu-latest", "macos-latest", "windows-latest"]
21832
21832
  };
@@ -21837,7 +21837,7 @@ function isWorkitPlugin(value) {
21837
21837
  const s = String(value).replaceAll("\\", "/");
21838
21838
  const url = s.startsWith("file://") || s.startsWith("git+file://");
21839
21839
  const pkgPath = s.includes("/packages/workit-opencode/") || s.includes("/packages/workit-cursor/") || s.includes("/node_modules/@brainervirus/workit-opencode/") || s.includes("/node_modules/@brainervirus/workit-cursor/");
21840
- return named(s, "workflow-toolkit") || named(s, "workflow-toolkit-opencode") || named(s, "local/workflow-toolkit") || named(s, "@brainervirus/workit-opencode") || named(s, "@brainervirus/workit-cursor") || url && pkgPath || s.startsWith("git+file://") && s.includes("workflow-toolkit");
21840
+ return named(s, "workflow-toolkit") || named(s, "workflow-toolkit-opencode") || named(s, "local/workflow-toolkit") || named(s, "workit") || named(s, "local/workit") || named(s, "@brainervirus/workit-opencode") || named(s, "@brainervirus/workit-cursor") || url && pkgPath || s.startsWith("git+file://") && s.includes("workflow-toolkit");
21841
21841
  }
21842
21842
  var named = (s, name) => s === name || s.startsWith(`${name}@`);
21843
21843
  var init_registration = () => {};
@@ -21940,7 +21940,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
21940
21940
  opencodeConfig: options.opencodeConfig ?? path9.join(home, ".config", "opencode", "opencode.json"),
21941
21941
  cursorSettings: options.cursorSettings ?? path9.join(home, ".cursor", "settings.json"),
21942
21942
  cursorMcp: options.cursorMcp ?? path9.join(home, ".cursor", "mcp.json"),
21943
- cursorPluginDir: options.cursorPluginDir ?? path9.join(home, ".cursor", "plugins", "local", "workflow-toolkit"),
21943
+ cursorPluginDir: options.cursorPluginDir ?? path9.join(home, ".cursor", "plugins", "local", "workit"),
21944
21944
  env,
21945
21945
  installer: options.installer ?? false
21946
21946
  };
@@ -22108,7 +22108,6 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22108
22108
  return [
22109
22109
  path9.join(pkg, "assets", "templates", "spec-template.md"),
22110
22110
  path9.join(pkg, "mcp.json"),
22111
- path9.join(pkg, "marketplace.json"),
22112
22111
  path9.join(pkg, ".cursor-plugin")
22113
22112
  ];
22114
22113
  case "cli":
@@ -22149,11 +22148,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22149
22148
  return [[path9.join(pkg, "src", "plugin.ts"), path9.join(pkg, "dist", "plugin.js")]];
22150
22149
  case "cursor":
22151
22150
  return [
22152
- [path9.join(pkg, "dist", "mcp-server.js"), path9.join(pkg, "mcp", "run-server.sh")],
22153
- [
22154
- path9.join(pkg, "dist", "cursor-session-start.js"),
22155
- path9.join(pkg, "hooks", "session-start")
22156
- ]
22151
+ [path9.join(pkg, "dist", "mcp-server.js")],
22152
+ [path9.join(pkg, "dist", "cursor-session-start.js")]
22157
22153
  ];
22158
22154
  case "cli":
22159
22155
  return [[path9.join(pkg, "src", "index.tsx"), path9.join(pkg, "dist", "index.js")]];
@@ -22184,9 +22180,19 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22184
22180
  return "invalid";
22185
22181
  }
22186
22182
  const executable = path9.basename(command).toLowerCase();
22183
+ if (executable === "npx" || executable === "npx.exe" || executable === "npx.cmd") {
22184
+ if (args[0] !== "-y")
22185
+ return "invalid";
22186
+ if (args[1] !== "--package=@brainervirus/workit-cursor@latest")
22187
+ return "invalid";
22188
+ if (args[2] !== "workit-cursor-mcp")
22189
+ return "invalid";
22190
+ return { kind: "npx" };
22191
+ }
22187
22192
  if (executable !== "node" && executable !== "node.exe")
22188
22193
  return "invalid";
22189
22194
  return {
22195
+ kind: "node",
22190
22196
  runtime: command,
22191
22197
  entry: path9.isAbsolute(args[0]) ? args[0] : path9.resolve(path9.dirname(res.cursorMcp), args[0])
22192
22198
  };
@@ -22194,12 +22200,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22194
22200
  const dev = res.dev;
22195
22201
  const hosts = hostsFor(res.host);
22196
22202
  const registered = hosts.includes("cursor") ? registeredCursorLauncher(res) : null;
22197
- const runtime = registered && registered !== "invalid" ? registered.runtime : "node";
22203
+ const runtime = registered && registered !== "invalid" && registered.kind === "node" ? registered.runtime : "node";
22198
22204
  const missing = hosts.includes("cursor") ? ["dist/mcp-server.js", "dist/cursor-session-start.js"].map((rel) => path9.join(res.cursorPluginDir, rel)).filter((p) => !validNodeEntry(p, runtime, res.env)).map((p) => `cursor: ${p}`) : [];
22199
22205
  if (hosts.includes("cursor")) {
22200
22206
  if (registered === "invalid") {
22201
22207
  missing.push(`cursor: canonical workit MCP launcher in ${res.cursorMcp}`);
22202
- } else if (registered && !validNodeEntry(registered.entry, registered.runtime, res.env)) {
22208
+ } else if (registered && registered.kind === "node" && !validNodeEntry(registered.entry, registered.runtime, res.env)) {
22203
22209
  missing.push(`cursor: registered ${registered.entry}`);
22204
22210
  }
22205
22211
  }
@@ -22308,7 +22314,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22308
22314
  if (keys.length > 1)
22309
22315
  problems.push(`cursor enables ${keys.length} workit plugin identities (${keys.join(", ")})`);
22310
22316
  }
22311
- const dirs = Array.isArray(settings?.plugin_dirs) ? settings.plugin_dirs.map(String).filter((d) => isWorkitPlugin(d) || d.includes("workflow-toolkit")) : [];
22317
+ const dirs = Array.isArray(settings?.plugin_dirs) ? settings.plugin_dirs.map(String).filter((d) => {
22318
+ const n = d.replaceAll("\\", "/").replace(/\/+$/, "");
22319
+ return isWorkitPlugin(d) || n.endsWith("local/workit") || n.endsWith("local/workflow-toolkit");
22320
+ }) : [];
22312
22321
  if (dirs.length > 1)
22313
22322
  problems.push(`cursor plugin_dirs has ${dirs.length} workit entries`);
22314
22323
  }
@@ -25234,7 +25243,7 @@ var init_setup_state = __esm(() => {
25234
25243
 
25235
25244
  // packages/workit-core/src/core/setup.ts
25236
25245
  import {
25237
- chmodSync,
25246
+ copyFileSync as copyFileSync2,
25238
25247
  cpSync as cpSync2,
25239
25248
  existsSync as existsSync17,
25240
25249
  mkdirSync as mkdirSync11,
@@ -3,8 +3,7 @@
3
3
  "hooks": {
4
4
  "sessionStart": [
5
5
  {
6
- "command": "node",
7
- "args": ["./dist/cursor-session-start.js"]
6
+ "command": "npx -y --package=@brainervirus/workit-cursor@latest workit-cursor-session-start"
8
7
  }
9
8
  ]
10
9
  }
package/mcp.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "mcpServers": {
3
3
  "workit": {
4
- "command": "node",
5
- "args": ["./dist/mcp-server.js", "${workspaceFolder}"]
4
+ "command": "npx",
5
+ "args": ["-y", "--package=@brainervirus/workit-cursor@latest", "workit-cursor-mcp", "${workspaceFolder}"]
6
6
  }
7
7
  }
8
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cursor",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "private": false,
5
5
  "description": "Workit Cursor plugin: MCP server, hooks, rules, marketplace manifest (thin over @brainervirus/workit-core)",
6
6
  "keywords": [
@@ -17,17 +17,18 @@
17
17
  "type": "git",
18
18
  "url": "https://github.com/BrainerVirus/workit.git"
19
19
  },
20
+ "bin": {
21
+ "workit-cursor-mcp": "./dist/mcp-server.js",
22
+ "workit-cursor-session-start": "./dist/cursor-session-start.js"
23
+ },
20
24
  "files": [
21
25
  "dist/",
22
26
  "assets/",
23
- "mcp/run-server.sh",
24
27
  "mcp.json",
25
- "marketplace.json",
26
28
  ".cursor-plugin/",
27
29
  "rules/",
28
30
  "skills/",
29
31
  "vendor/superpowers/skills/",
30
- "hooks/session-start",
31
32
  "hooks/hooks-cursor.json"
32
33
  ],
33
34
  "type": "module",
@@ -38,11 +39,11 @@
38
39
  "build": "bun scripts/build.ts"
39
40
  },
40
41
  "dependencies": {
41
- "@brainervirus/workit-core": "^0.7.1",
42
+ "@brainervirus/workit-core": "^0.8.0",
42
43
  "@modelcontextprotocol/sdk": "^1.12.0",
43
44
  "zod": "^3.24.0"
44
45
  },
45
46
  "engines": {
46
- "node": ">=20"
47
+ "node": ">=22"
47
48
  }
48
49
  }
@@ -18,7 +18,7 @@ Use the returned `tasks[]` as ground truth. Cache each `section_text` for subage
18
18
 
19
19
  ## Step 2 — Load execution contract
20
20
 
21
- Resolve plugin root: `WORKFLOW_TOOLKIT_ROOT` env or `~/.cursor/plugins/local/workflow-toolkit/`.
21
+ Resolve plugin root: `WORKFLOW_TOOLKIT_ROOT` env or `~/.cursor/plugins/local/workit/`.
22
22
 
23
23
  Load `templates/execution-contract.md`. Substitute `<SPEC_PATH>`, `<PLAN_PATH>`, `<BRANCH>`, `<SDD_DIR>`, `<TASK_LIST>` from MCP. If template missing, stop with error.
24
24
 
@@ -1,22 +0,0 @@
1
- #!/usr/bin/env bash
2
- # sessionStart — inject Superpowers workflow contract (RL-09: NO network sync).
3
- # Prefer the self-contained Node bundle (dist/cursor-session-start.js); fall back
4
- # to the dev TS entry via Bun. Fail-open: a missing runtime must not break start.
5
- set -euo pipefail
6
-
7
- SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
8
- if [ -f "$SCRIPT_DIR/../dist/cursor-session-start.js" ] && command -v node >/dev/null 2>&1; then
9
- exec node "$SCRIPT_DIR/../dist/cursor-session-start.js"
10
- fi
11
-
12
- BUN_BIN="${BUN:-}"
13
- if [ -z "$BUN_BIN" ]; then
14
- for candidate in "$HOME/.bun/bin/bun" /usr/local/bin/bun /usr/bin/bun; do
15
- [ -x "$candidate" ] && BUN_BIN="$candidate" && break
16
- done
17
- fi
18
- if [ -z "$BUN_BIN" ] || [ ! -x "$BUN_BIN" ]; then
19
- printf '{}\n'
20
- exit 0
21
- fi
22
- exec "$BUN_BIN" "$SCRIPT_DIR/session-start.ts"
package/marketplace.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "name": "workit",
3
- "displayName": "Workit",
4
- "description": "Workflow rails for agentic coding: specs, plans, YouTrack, CI-gated commits",
5
- "publisher": "cristhofer-pincetti",
6
- "version": "0.7.1",
7
- "homepage": "https://github.com/BrainerVirus/workit",
8
- "repository": "https://github.com/BrainerVirus/workit.git",
9
- "license": "MIT"
10
- }
package/mcp/run-server.sh DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Cursor MCP launcher: prefer the self-contained Node bundle (dist/mcp-server.js);
3
- # fall back to the dev TS entry via Bun.
4
- set -euo pipefail
5
- MCP_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
6
- if [ -f "$MCP_DIR/../dist/mcp-server.js" ] && command -v node >/dev/null 2>&1; then
7
- exec node "$MCP_DIR/../dist/mcp-server.js" "$@"
8
- fi
9
- exec "${BUN:-bun}" "$MCP_DIR/run-server.ts" "$@"