@kensaurus/skills 2.1.0 → 2.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.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Playbooks your coding agent runs from a plain-English request.",
9
- "version": "2.1.0"
9
+ "version": "2.1.1"
10
10
  },
11
11
  "plugins": [
12
12
  {
@@ -2,7 +2,7 @@
2
2
  "name": "kenji",
3
3
  "displayName": "kenji skills",
4
4
  "description": "You say the job; the playbook runs. 159 agent skills, 63 slash commands, 6 subagents, and MCP templates for Claude Code, Cursor, Codex CLI, and Gemini CLI. Tuned for React / Next.js / Supabase; works on most stacks. Effort-routed for Claude Opus 5.5.",
5
- "version": "2.1.0",
5
+ "version": "2.1.1",
6
6
  "author": {
7
7
  "name": "kensaurus",
8
8
  "email": "kensaurus@gmail.com"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kenji",
3
3
  "displayName": "kenji skills",
4
- "version": "2.1.0",
4
+ "version": "2.1.1",
5
5
  "description": "You say the job; the playbook runs. 159 agent skills, 63 slash commands, 6 subagents, and MCP templates for Claude Code, Cursor, Codex CLI, and Gemini CLI. Tuned for React / Next.js / Supabase; works on most stacks.",
6
6
  "author": {
7
7
  "name": "kensaurus"
package/CHANGELOG.md CHANGED
@@ -6,6 +6,20 @@ All notable additions and changes to kenji (`kensaurus/skills`, named `cursor-ke
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.1.1] — 2026-10-01
10
+
11
+ ### Fixed
12
+
13
+ - **Installs on Windows survive a briefly held file.** An open editor
14
+ watching `~/.cursor` or `~/.claude`, or an antivirus scan, can hold a file
15
+ for a moment right after it is written. Windows then failed the next copy
16
+ with `EPERM`, which aborted the install and left the target half-copied:
17
+ Cursor failed three runs in a row on a different `SKILL.md` each time. The
18
+ installer now retries a copy, write or delete on `EPERM`, `EBUSY` or
19
+ `EACCES` for up to about 3 seconds per file. If the lock never clears it
20
+ still fails, and says which file is held and that closing the editor fixes
21
+ it. Other platforms are unchanged.
22
+
9
23
  ## [2.1.0] — 2026-10-01
10
24
 
11
25
  UX laws as a measured fix pass, and the Miller misreading removed from the
package/bin/install.mjs CHANGED
@@ -37,14 +37,47 @@
37
37
  */
38
38
 
39
39
  import {
40
- existsSync, mkdirSync, cpSync, rmSync, symlinkSync, readdirSync, statSync,
41
- readFileSync, writeFileSync,
40
+ existsSync, mkdirSync, cpSync as cpSyncOnce, rmSync as rmSyncOnce, symlinkSync,
41
+ readdirSync, statSync, readFileSync, writeFileSync as writeFileSyncOnce,
42
42
  } from 'node:fs';
43
43
  import { createHash } from 'node:crypto';
44
44
  import { join, resolve, dirname } from 'node:path';
45
45
  import { homedir, platform } from 'node:os';
46
46
  import { fileURLToPath } from 'node:url';
47
47
 
48
+ // ---- transient Windows file locks -----------------------------------------
49
+ // An open editor watching ~/.cursor or ~/.claude, or an antivirus scan, can
50
+ // hold a file for a moment right after it is written. Windows then fails the
51
+ // next copy over it with EPERM or EBUSY, and one held file used to abort the
52
+ // run with the target half-copied. Retry the same codes graceful-fs retries on
53
+ // Windows, with a bounded backoff (about 2.75 s per file). symlinkSync stays
54
+ // unwrapped: its EPERM means "no symlink privilege" and place() must fall back
55
+ // to a copy at once.
56
+ const LOCK_CODES = new Set(['EPERM', 'EBUSY', 'EACCES']);
57
+ const LOCK_RETRIES = 10;
58
+ const sleepSync = (ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
59
+ function retryLocked(fn) {
60
+ if (platform() !== 'win32') return fn;
61
+ return (...args) => {
62
+ for (let attempt = 1; ; attempt++) {
63
+ try {
64
+ return fn(...args);
65
+ } catch (err) {
66
+ if (!LOCK_CODES.has(err.code)) throw err;
67
+ if (attempt > LOCK_RETRIES) {
68
+ console.error(`\n ${err.code}: another program is holding ${err.dest ?? err.path ?? 'a destination file'}.`);
69
+ console.error(' Usually an open editor (Cursor, VS Code) or an antivirus scan. Close it and run the installer again.\n');
70
+ throw err;
71
+ }
72
+ sleepSync(50 * attempt);
73
+ }
74
+ }
75
+ };
76
+ }
77
+ const cpSync = retryLocked(cpSyncOnce);
78
+ const rmSync = retryLocked(rmSyncOnce);
79
+ const writeFileSync = retryLocked(writeFileSyncOnce);
80
+
48
81
  const __dir = fileURLToPath(new URL('..', import.meta.url));
49
82
  const argv = process.argv.slice(2);
50
83
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kensaurus/skills",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "You say the job; the playbook runs. 159 agent skills, 63 slash commands, 6 subagents, and MCP templates for Claude Code, Cursor, Codex CLI, and Gemini CLI. Tuned for React / Next.js / Supabase; works on most stacks.",
5
5
  "type": "module",
6
6
  "bin": {