@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/CHANGELOG.md +14 -0
- package/bin/install.mjs +35 -2
- package/package.json +1 -1
|
@@ -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.
|
|
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.
|
|
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
|
|
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.
|
|
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": {
|