devlyn-cli 4.2.13 → 4.2.15
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/README.md +6 -3
- package/bin/devlyn.js +198 -19
- package/bin/instruction-templates.json +8 -0
- package/bin/skill-history.json +1 -0
- package/config/skills/_shared/codex-monitored.sh +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,6 +37,8 @@ In a project, AGENTS.md readers load the skills from `.agents/skills/`; Claude C
|
|
|
37
37
|
|
|
38
38
|
Without prompts, `npx devlyn-cli -y` installs AGENTS.md + `.agents/skills/` plus every target this project already has; add `--claude` for Claude Code. With `--global` it installs for every project on this machine, plus `~/.claude/skills/` with `--claude` or when it already has a devlyn install. After a project install or update, the installer names the changed files to commit, including installed files a `.gitignore` hides, so teammates and `/devlyn-ideate` drains can use them.
|
|
39
39
|
|
|
40
|
+
`npx devlyn-cli update` — Update every devlyn install already here (this project and your global skill folders) to this version; installs nothing new.
|
|
41
|
+
|
|
40
42
|
---
|
|
41
43
|
|
|
42
44
|
## How It Works — Principles and Loops
|
|
@@ -102,8 +104,9 @@ files and rules outside managed blocks retain their contents. Unknown old text
|
|
|
102
104
|
is kept conservatively, even when it may contain obsolete defaults.
|
|
103
105
|
Malformed or duplicate managed markers still stop with an exact `.backup`, new
|
|
104
106
|
defaults in `.incoming`, and a `.merge.md` guide; the original remains unchanged.
|
|
105
|
-
|
|
106
|
-
`node scripts/update-instruction-templates.js
|
|
107
|
+
Portability refreshes the offline fingerprints from Git history using
|
|
108
|
+
`node scripts/update-instruction-templates.js` before testing; publish ships that tested tarball.
|
|
109
|
+
Installation needs no Git or network.
|
|
107
110
|
Use 3.1.3 or newer consistently: older installers still overwrite `CLAUDE.md`.
|
|
108
111
|
|
|
109
112
|
Upgrading to 4.1.0: `npx devlyn-cli -y` in a 4.x project keeps its Claude Code install
|
|
@@ -215,7 +218,7 @@ Selected during install. Run `npx devlyn-cli` again to add more.
|
|
|
215
218
|
|
|
216
219
|
---
|
|
217
220
|
|
|
218
|
-
Installer updates preserve user work: before writing any selected target, devlyn refuses to replace or remove edited skills, directories with extra files (including hidden files), links, or unknown copies. `-y` does not bypass this check. Unedited copies from every published version upgrade automatically, including committed copies, historical install-path stamps and generated Python bytecode caches.
|
|
221
|
+
Installer updates preserve user work: before writing any selected target, devlyn refuses to replace or remove edited skills, directories with extra files (including hidden files), links, or unknown copies. `-y` does not bypass this check. Unedited copies from every published version upgrade automatically, including committed copies, historical install-path stamps and generated Python bytecode caches. Portability derives the offline skill history from Git with `node scripts/update-skill-history.js` before testing; publish ships that tested tarball. Move conflicting folders to a backup and migrate them manually; also remove conflicting tracked paths from the Git index before rerunning.
|
|
219
222
|
|
|
220
223
|
Only `__pycache__` directories containing exclusively regular `*.pyc` files count as generated Python caches. Other entries make the directory ordinary content; links and special files are refused. Standalone `*.pyc` files count as content: none of the 113 published versions through 4.2.5 shipped them. Historical path normalization applies only to the escaped absolute assignment defaults written into Markdown by the 2.8.0–4.0.0 installers.
|
|
221
224
|
|
package/bin/devlyn.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const os = require('os');
|
|
6
|
+
const crypto = require('crypto');
|
|
6
7
|
const { execSync, spawnSync } = require('child_process');
|
|
7
8
|
|
|
8
9
|
const CONFIG_SOURCE = path.join(__dirname, '..', 'config');
|
|
@@ -29,6 +30,7 @@ const RENAMED_SKILLS = {
|
|
|
29
30
|
'devlyn:reap': 'devlyn-reap',
|
|
30
31
|
};
|
|
31
32
|
const DEVLYN_INSTALL_MARKER = '.devlyn-install.json';
|
|
33
|
+
const DEVLYN_INSTALL_LOCK = '.devlyn-install.lock';
|
|
32
34
|
// Project settings earlier releases added for the retired pipeline.
|
|
33
35
|
const RETIRED_STOP_HOOK = 'python3 "$CLAUDE_PROJECT_DIR/.claude/skills/_shared/resolve-stop-hook.py"';
|
|
34
36
|
const RETIRED_ENV = ['CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS'];
|
|
@@ -101,6 +103,26 @@ function skillRoots(target, global) {
|
|
|
101
103
|
return dirs.map((dir) => path.join(global ? os.homedir() : projectDir(), dir, 'skills'));
|
|
102
104
|
}
|
|
103
105
|
|
|
106
|
+
// Core and historical skills count, as does an install in progress. _shared is not
|
|
107
|
+
// unique to devlyn, and a marker alone can outlive its skills; optional addons stand alone.
|
|
108
|
+
function hasDevlynInstall(root) {
|
|
109
|
+
try {
|
|
110
|
+
const stat = (name) => fs.lstatSync(name, { throwIfNoEntry: false });
|
|
111
|
+
if (!stat(root)?.isDirectory()) return false;
|
|
112
|
+
const optional = new Set(OPTIONAL_ADDONS.map((addon) => addon.name));
|
|
113
|
+
const names = [...DEVLYN_CORE_SKILLS, ...DEPRECATED_DIRS.map((name) => path.basename(name)),
|
|
114
|
+
...Object.keys(RENAMED_SKILLS)].filter((name) => name.startsWith('devlyn')
|
|
115
|
+
&& !optional.has(name.replace(/[:\uF03A]/g, '-')));
|
|
116
|
+
return !!stat(path.join(root, DEVLYN_INSTALL_LOCK))
|
|
117
|
+
|| names.some((name) => [...legacySkillPaths(root, name.replace(/^devlyn-/, 'devlyn:')),
|
|
118
|
+
path.join(root, name.replace(/:/g, '-'))].some((full) => stat(full)?.isDirectory()))
|
|
119
|
+
|| (!!stat(path.join(root, DEVLYN_INSTALL_MARKER)) && stat(path.join(root, '_shared'))?.isDirectory());
|
|
120
|
+
} catch (error) {
|
|
121
|
+
if (error.code === 'ENOTDIR') return false;
|
|
122
|
+
throw new InstructionError(`Cannot inspect ${root}: ${error.message}. Check its permissions and run again.`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
104
126
|
// A devlyn Claude install in this scope. Globally only the marker a `--global --claude` run
|
|
105
127
|
// writes counts; in a project also a devlyn skill (0.6.0 and later), command (0.2-0.5) or
|
|
106
128
|
// CLAUDE.md with devlyn defaults, held or imported from AGENTS.md, which a team may commit
|
|
@@ -914,6 +936,76 @@ function installClaudeCore(installedSkills = new Map()) {
|
|
|
914
936
|
return written;
|
|
915
937
|
}
|
|
916
938
|
|
|
939
|
+
// Shared user roots need one writer from ownership checks through the last addon write.
|
|
940
|
+
// Never reap a foreign lock: PID reuse and slow installs make age/liveness unsafe evidence.
|
|
941
|
+
function withUserSkillLocks(roots, action) {
|
|
942
|
+
const locks = [];
|
|
943
|
+
const createdDirs = [];
|
|
944
|
+
try {
|
|
945
|
+
for (const root of roots) {
|
|
946
|
+
const lock = path.join(root, DEVLYN_INSTALL_LOCK);
|
|
947
|
+
try {
|
|
948
|
+
for (const dir of [path.dirname(root), root]) {
|
|
949
|
+
const stat = fs.lstatSync(dir, { throwIfNoEntry: false });
|
|
950
|
+
if (stat && !stat.isDirectory()) throw new Error(`not a real directory: ${dir}`);
|
|
951
|
+
}
|
|
952
|
+
const missing = [];
|
|
953
|
+
for (let dir = root; !fs.existsSync(dir); dir = path.dirname(dir)) {
|
|
954
|
+
missing.push(dir);
|
|
955
|
+
if (path.dirname(dir) === dir) break;
|
|
956
|
+
}
|
|
957
|
+
fs.mkdirSync(root, { recursive: true });
|
|
958
|
+
createdDirs.push(...missing);
|
|
959
|
+
const token = crypto.randomBytes(16).toString('hex');
|
|
960
|
+
const fd = fs.openSync(lock, 'wx', 0o600);
|
|
961
|
+
try {
|
|
962
|
+
fs.writeFileSync(fd, JSON.stringify({ pid: process.pid, token }) + '\n');
|
|
963
|
+
locks.push({ lock, token });
|
|
964
|
+
} catch (error) {
|
|
965
|
+
// A failed initial write may not leave parseable JSON; verify the open file's identity.
|
|
966
|
+
const opened = fs.fstatSync(fd);
|
|
967
|
+
const current = fs.lstatSync(lock, { throwIfNoEntry: false });
|
|
968
|
+
if (current?.dev === opened.dev && current?.ino === opened.ino) fs.unlinkSync(lock);
|
|
969
|
+
throw error;
|
|
970
|
+
} finally {
|
|
971
|
+
fs.closeSync(fd);
|
|
972
|
+
}
|
|
973
|
+
} catch (error) {
|
|
974
|
+
if (error.code === 'EEXIST') {
|
|
975
|
+
let owner;
|
|
976
|
+
try {
|
|
977
|
+
owner = `pid ${JSON.parse(fs.readFileSync(lock, 'utf8')).pid}`;
|
|
978
|
+
} catch (readError) {
|
|
979
|
+
owner = `cannot read lock owner: ${readError.message}`;
|
|
980
|
+
}
|
|
981
|
+
throw new InstructionError(`Another devlyn-cli is changing ${root} (${owner}). `
|
|
982
|
+
+ `If none is running, delete ${lock} and run again.`);
|
|
983
|
+
}
|
|
984
|
+
throw new InstructionError(`Cannot lock ${root}: ${error.message}. Check ${lock} and run again.`);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
return action();
|
|
988
|
+
} finally {
|
|
989
|
+
const errors = [];
|
|
990
|
+
for (const { lock, token } of locks.reverse()) {
|
|
991
|
+
try {
|
|
992
|
+
if (JSON.parse(fs.readFileSync(lock, 'utf8')).token === token) fs.unlinkSync(lock);
|
|
993
|
+
} catch (error) {
|
|
994
|
+
if (error.code !== 'ENOENT') errors.push(`${lock}: ${error.message}`);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
// Refusal must not leave empty roots created just to acquire their locks.
|
|
998
|
+
for (const dir of createdDirs) {
|
|
999
|
+
try {
|
|
1000
|
+
fs.rmdirSync(dir);
|
|
1001
|
+
} catch (error) {
|
|
1002
|
+
if (!['ENOTEMPTY', 'EEXIST', 'ENOENT'].includes(error.code)) errors.push(`${dir}: ${error.message}`);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
if (errors.length) throw new InstructionError(`Cannot release install locks; check these paths:\n${errors.join('\n')}`);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
917
1009
|
// Installs the targets in one scope; returns the skill roots written.
|
|
918
1010
|
function install(targets, global, optionalNames = []) {
|
|
919
1011
|
// In the home folder CLAUDE.md, AGENTS.md (agents read a parent folder's too) and
|
|
@@ -926,23 +1018,25 @@ function install(targets, global, optionalNames = []) {
|
|
|
926
1018
|
+ 'would apply to every project. Run from a project folder, or use --global for skills only.');
|
|
927
1019
|
}
|
|
928
1020
|
const roots = targets.flatMap((target) => skillRoots(target, global));
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
1021
|
+
return withUserSkillLocks(global ? roots : [], () => {
|
|
1022
|
+
const written = [];
|
|
1023
|
+
const installedSkills = new Map();
|
|
1024
|
+
if (!global) readProjectGitignore();
|
|
1025
|
+
preflightSkills(roots, optionalNames,
|
|
1026
|
+
!global && targets.includes('claude') ? path.dirname(skillRoots('claude', false)[0]) : null);
|
|
1027
|
+
// AGENTS.md first, whatever order the menu gave: a new CLAUDE.md holds the block only when AGENTS.md does not.
|
|
1028
|
+
for (const target of ['agents', 'claude'].filter((name) => targets.includes(name))) {
|
|
1029
|
+
if (global) skillRoots(target, true).forEach((root) => installCoreSkills(root));
|
|
1030
|
+
else if (target === 'agents') written.push(...installAgentsProject(targets.includes('claude'), installedSkills));
|
|
1031
|
+
else written.push(...installClaudeCore(installedSkills));
|
|
1032
|
+
}
|
|
1033
|
+
for (const name of optionalNames) installLocalSkill(name, roots, written, installedSkills);
|
|
1034
|
+
log(`\n✅ devlyn ${PKG.version} installed`, 'green');
|
|
1035
|
+
if (global) log('The principles block installs per project: run npx devlyn-cli in the project without --global.');
|
|
1036
|
+
noticeGlobalDrift(roots);
|
|
1037
|
+
if (!global) noticeProjectChanges(written, installedSkills);
|
|
1038
|
+
return roots;
|
|
1039
|
+
});
|
|
946
1040
|
}
|
|
947
1041
|
|
|
948
1042
|
// Advisory only: a successful install stays successful when Git is unavailable or fails.
|
|
@@ -1023,12 +1117,92 @@ function noticeGlobalDrift(installed) {
|
|
|
1023
1117
|
} catch (error) {
|
|
1024
1118
|
version = `(unreadable marker: ${error.message})`;
|
|
1025
1119
|
}
|
|
1120
|
+
if (dir !== '.grok' && version === PKG.version) continue;
|
|
1026
1121
|
// 4.0's Grok root; Grok now reads ~/.agents/skills, so --global never refreshes it.
|
|
1027
1122
|
const advice = dir === '.grok' ? 'delete it' : 'refresh it with --global, or delete it';
|
|
1028
1123
|
log(`Global devlyn ${version} in ${root.replace(os.homedir(), '~')} — ${advice}.`, 'yellow');
|
|
1029
1124
|
}
|
|
1030
1125
|
}
|
|
1031
1126
|
|
|
1127
|
+
// Skip project setup in the home folder, where instructions would affect every project.
|
|
1128
|
+
// Lock user roots, preflight all roots, check versions, then write; user roots go first
|
|
1129
|
+
// so the project's commit guidance remains the last output.
|
|
1130
|
+
function update() {
|
|
1131
|
+
showLogo();
|
|
1132
|
+
log('─'.repeat(44), 'dim');
|
|
1133
|
+
|
|
1134
|
+
const userCandidates = [...skillRoots('agents', true), ...skillRoots('claude', true)];
|
|
1135
|
+
const linkedRoots = new Set();
|
|
1136
|
+
const linkNotices = [];
|
|
1137
|
+
for (const root of new Set([...userCandidates, ...skillRoots('agents', false), ...skillRoots('claude', false)])) {
|
|
1138
|
+
try {
|
|
1139
|
+
if (![path.dirname(root), root].some((dir) => fs.lstatSync(dir, { throwIfNoEntry: false })?.isSymbolicLink())) continue;
|
|
1140
|
+
linkedRoots.add(root);
|
|
1141
|
+
// Follow only for discovery; linked roots never enter the write/lock/preflight paths.
|
|
1142
|
+
if (!fs.statSync(root, { throwIfNoEntry: false })?.isDirectory()) continue;
|
|
1143
|
+
if (!fs.statSync(path.join(root, DEVLYN_INSTALL_MARKER), { throwIfNoEntry: false })
|
|
1144
|
+
&& !fs.readdirSync(root).some((name) => name.startsWith('devlyn')
|
|
1145
|
+
&& fs.statSync(path.join(root, name), { throwIfNoEntry: false })?.isDirectory())) continue;
|
|
1146
|
+
const notice = `Not updated: ${root} is a link — devlyn-cli does not write through links. `
|
|
1147
|
+
+ 'Update the folder it points to, or replace the link with a folder.';
|
|
1148
|
+
linkNotices.push(notice);
|
|
1149
|
+
log(notice, 'yellow');
|
|
1150
|
+
} catch (error) {
|
|
1151
|
+
if (error.code === 'ENOTDIR') continue;
|
|
1152
|
+
throw new InstructionError(`Cannot inspect ${root}: ${error.message}. Check its permissions and run again.`);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
const userRoots = userCandidates.filter((root) => !linkedRoots.has(root) && hasDevlynInstall(root));
|
|
1156
|
+
const home = fs.statSync(os.homedir(), { bigint: true, throwIfNoEntry: false });
|
|
1157
|
+
const here = fs.statSync(projectDir(), { bigint: true });
|
|
1158
|
+
const targets = [];
|
|
1159
|
+
if (home?.dev !== here.dev || home?.ino !== here.ino) {
|
|
1160
|
+
if (!linkedRoots.has(skillRoots('agents', false)[0]) && hasDevlynInstall(skillRoots('agents', false)[0])) targets.push('agents');
|
|
1161
|
+
if (!linkedRoots.has(skillRoots('claude', false)[0]) && hasDevlynClaude(false)) targets.push('claude');
|
|
1162
|
+
}
|
|
1163
|
+
const projectRoots = targets.flatMap((target) => skillRoots(target, false));
|
|
1164
|
+
const roots = [...userRoots, ...projectRoots];
|
|
1165
|
+
if (!roots.length) {
|
|
1166
|
+
throw new InstructionError(['No devlyn install here to update. Run npx devlyn-cli to install.', ...linkNotices].join('\n'));
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
return withUserSkillLocks(userRoots, () => {
|
|
1170
|
+
if (targets.length) {
|
|
1171
|
+
readProjectGitignore();
|
|
1172
|
+
preflightSkills(projectRoots, [], targets.includes('claude') ? path.dirname(skillRoots('claude', false)[0]) : null);
|
|
1173
|
+
}
|
|
1174
|
+
preflightSkills(userRoots);
|
|
1175
|
+
// Ownership preflight has already refused unreadable or invalid markers.
|
|
1176
|
+
const current = PKG.version.split('.').map(BigInt);
|
|
1177
|
+
const newer = roots.flatMap((root) => {
|
|
1178
|
+
const marker = path.join(root, DEVLYN_INSTALL_MARKER);
|
|
1179
|
+
if (!fs.existsSync(marker)) return [];
|
|
1180
|
+
const { version } = JSON.parse(fs.readFileSync(marker, 'utf8'));
|
|
1181
|
+
// SemVer 2.0.0's numbered-group regex: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
|
1182
|
+
const parsed = typeof version === 'string' && version.match(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/);
|
|
1183
|
+
if (!parsed || parsed[0] !== version) {
|
|
1184
|
+
throw new InstructionError(`Update refused; nothing was changed. ${root}: cannot tell which devlyn-cli wrote it `
|
|
1185
|
+
+ '(missing or malformed marker version). Restore the original install marker and run again.');
|
|
1186
|
+
}
|
|
1187
|
+
// This package is a plain release: equal-core prereleases are older, and build metadata is ignored.
|
|
1188
|
+
const parts = parsed.slice(1, 4).map(BigInt);
|
|
1189
|
+
const difference = parts.findIndex((part, index) => part !== current[index]);
|
|
1190
|
+
return difference !== -1 && parts[difference] > current[difference] ? [` - ${root}: ${version}`] : [];
|
|
1191
|
+
});
|
|
1192
|
+
if (newer.length) {
|
|
1193
|
+
throw new InstructionError('Update refused; nothing was changed. Newer devlyn installs:\n'
|
|
1194
|
+
+ newer.join('\n') + '\nRun npx devlyn-cli@latest update.');
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
userRoots.forEach((root) => installCoreSkills(root));
|
|
1198
|
+
if (targets.length) install(targets, false);
|
|
1199
|
+
else {
|
|
1200
|
+
log(`\n✅ devlyn ${PKG.version} installed`, 'green');
|
|
1201
|
+
noticeGlobalDrift(userRoots);
|
|
1202
|
+
}
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1032
1206
|
async function init({ yes, claude, global }) {
|
|
1033
1207
|
showLogo();
|
|
1034
1208
|
log('─'.repeat(44), 'dim');
|
|
@@ -1090,6 +1264,7 @@ function showHelp() {
|
|
|
1090
1264
|
showLogo();
|
|
1091
1265
|
log('Usage:', 'green');
|
|
1092
1266
|
log(' npx devlyn-cli Install/update devlyn: choose what (AGENTS.md, CLAUDE.md) and where (this project or global)');
|
|
1267
|
+
log(' npx devlyn-cli update Update every devlyn install already here (this project and your global skill folders) to this version; installs nothing new');
|
|
1093
1268
|
log(' npx devlyn-cli -y Without prompts: AGENTS.md + .agents/skills, plus CLAUDE.md + .claude/ if this project has them');
|
|
1094
1269
|
log(' npx devlyn-cli -y --claude Also install CLAUDE.md + .claude/ for Claude Code');
|
|
1095
1270
|
log(' npx devlyn-cli -y --global Skills only, for every project on this machine (~/.agents/skills, ~/.codex/skills; ~/.claude/skills with --claude, or when it already has a devlyn install)');
|
|
@@ -1133,13 +1308,17 @@ switch (command) {
|
|
|
1133
1308
|
process.exitCode = 1;
|
|
1134
1309
|
break;
|
|
1135
1310
|
default: {
|
|
1136
|
-
const flags = command === 'init' ? args.slice(1) : args;
|
|
1137
|
-
const unknown = flags.find((flag) => !INSTALL_FLAGS.includes(flag));
|
|
1311
|
+
const flags = command === 'init' || command === 'update' ? args.slice(1) : args;
|
|
1312
|
+
const unknown = command === 'update' ? flags[0] : flags.find((flag) => !INSTALL_FLAGS.includes(flag));
|
|
1138
1313
|
if (unknown !== undefined) {
|
|
1139
1314
|
log(`Unknown command: ${unknown}`, 'yellow');
|
|
1140
1315
|
showHelp();
|
|
1141
1316
|
process.exit(1);
|
|
1142
1317
|
}
|
|
1318
|
+
if (command === 'update') {
|
|
1319
|
+
update();
|
|
1320
|
+
break;
|
|
1321
|
+
}
|
|
1143
1322
|
await init({ yes: flags.includes('-y') || flags.includes('--yes'), claude: flags.includes('--claude'), global: flags.includes('--global') });
|
|
1144
1323
|
}
|
|
1145
1324
|
}
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
"paragraphs": {
|
|
83
83
|
"AGENTS.md": [
|
|
84
84
|
"00044037bbe954aacee48c5edbe01b53aabef90fbe3f0c28c9136dc428fdd7df",
|
|
85
|
+
"0031285b60a5cf5e965df50482969315e5e62b163bb706695622fb4ed63f3dda",
|
|
85
86
|
"0042d7a45818c8e1c451ac255502ee014fda81a2dbd2a4c04e75a66bc3493940",
|
|
86
87
|
"0144d44eb6a0537211159e5f15baf2cacf11cc3275490ac5d295917df22cff27",
|
|
87
88
|
"01e073f6a5722534affe03ab334fe4a394347f13de5ce191b757a0b7c6f51904",
|
|
@@ -91,6 +92,7 @@
|
|
|
91
92
|
"03d85ed66f64ea52f2f96d9fb203b05ac6afc0ba634a4dfb3585429ce1531c44",
|
|
92
93
|
"0467080d13d933b663362006ae5f5a0ad73baaed51ad50faf3f0d3d9f92244a3",
|
|
93
94
|
"0634a245075d1a5aac4e58c1345f40f5f4c3b4909315f86aacd7ab239ea3ce61",
|
|
95
|
+
"072b63f736ee80f28550aec03277f033268a232e349ac86c3f1cab4bad9006c0",
|
|
94
96
|
"0869633a322da8f8d800b1d2c23becc52f5ff592f0823533ea24f09de465c53a",
|
|
95
97
|
"090f003bb30b98e6979865f3eb9bbc66eaa8f0cd74a89ff2eea5ef38cbee13b5",
|
|
96
98
|
"0926622dde30d21c6cafe6b69b0bb0608b31e2528655615c7edbdedc6ae43d7c",
|
|
@@ -163,6 +165,7 @@
|
|
|
163
165
|
"3e87f3023f1ee4810c769a27f63244a4c4825fa3c78417abd8a1a4bfb6350134",
|
|
164
166
|
"3efd55e3caac3e3488b81921446bc9ca4ec92ac766abbcfefafeb183b21464a1",
|
|
165
167
|
"3f05e197006cf9715612c67cb8709690e053262e9a0702723e69798ad29a2c08",
|
|
168
|
+
"3fde1f80f1d0e17ba79a674cb1124b8034df92801e9615c8fa443ce7c7a7672b",
|
|
166
169
|
"41323b1c12be256f604edf8c49ff505acbaa75b6a1b938b76286d5eebec1ce95",
|
|
167
170
|
"41660630582e14f984686f201e6af130e29bbd3fadc3c76a3c6055a7a8f78c4f",
|
|
168
171
|
"41d2ff119ff97961c64e5eb57632c2d04b22794b50eb9227506c4ed763ebca3f",
|
|
@@ -374,6 +377,7 @@
|
|
|
374
377
|
"e237f12ed08800ccc4c6eb4ae57cdd59d61198711f6a3b02dcb668aa08fddb93",
|
|
375
378
|
"e289dbab99dadb30d8315b32b8243154148c82955f238936bce4c1fe1c3ae525",
|
|
376
379
|
"e2bac40f3ff0b39726f95caaa9b19aa3b21596f165ac7a9dc68ebf42681d58cb",
|
|
380
|
+
"e389e1e77cc2da32214e95451b25b45402b1b586b26f5688bb373c492db3fcfb",
|
|
377
381
|
"e3ee2da50e961046da3f5b68b0c328570307fb21a93424ae22536b8f216b55a3",
|
|
378
382
|
"e43e4b5b86044fbf7be8d7fd1e3e27cd2089bfc8243e07dc2c3fc034c19794ea",
|
|
379
383
|
"e44015948c7d04e60f3fed7e348c2052538e7784d8fe7ea3edf9f52de07448dd",
|
|
@@ -652,6 +656,7 @@
|
|
|
652
656
|
"6170d780ab4f3cb5e2ea7d2757f9239d35dbbc1f9398e73877a95d5ef4c582ee",
|
|
653
657
|
"624becc31a3b8619bab2b863a469b8bc6b19fc48acaa7d59a455057ff8d7cce1",
|
|
654
658
|
"635097bbe52855009ba78ab992a905aad63b755a4b5c688179d8d597d5c9da01",
|
|
659
|
+
"65997521bd2bee492eeadc8570bf71f374cf1a05856d4acca499350b3db0dc7c",
|
|
655
660
|
"65b903f779d8879f04e427a400a04bd29ab982ab28a62c2c172620773518242b",
|
|
656
661
|
"6639e9e9622eca3d978923f26bf6f6ba1a95be4059206cc27c62e9deb026146a",
|
|
657
662
|
"6693baa07666a5853ea606c25812f70550d28f6182d9c9dbfc1421270f1ec544",
|
|
@@ -665,6 +670,7 @@
|
|
|
665
670
|
"6a08a11aea6a1dfaa99823a73bc8730e8fff9c483ec8989aaeca669cfc7b3ed6",
|
|
666
671
|
"6a27907ba14fae9ddcacd551007b783b2f813c51c118828c74fd2174e09a7d41",
|
|
667
672
|
"6a5ea10aa15a05ac992bd118adc3c0de48c85cea504aef655065d9678f93717c",
|
|
673
|
+
"6b098e67dbcdbec4569fb950f2067e4c4843a3b5f26a4e8886820102542eddee",
|
|
668
674
|
"6b26d02b3f87d53a964b6fe405992104dd2ee85f8c1b3048951ece574d9005a8",
|
|
669
675
|
"6b65f3883cfca3d531ab716c069c88f3a7d964657c5e026bda25eacdb37f16c5",
|
|
670
676
|
"6b726d35cdc0851401769b6de9c422cfa475dbe7c0d036726706439a2cdbb02a",
|
|
@@ -699,6 +705,7 @@
|
|
|
699
705
|
"7b47b07e3062f3dc839f11397bc3265120e01a35b0fda094d738e28a6729e6c3",
|
|
700
706
|
"7bb5c341115c56592c0d1b5903d01321ce9c324136bc53babf9d438389796d94",
|
|
701
707
|
"7c0dacd603b4381539d6d3cf21f5fe625cf54b05eb4aa750fce658529b11d81d",
|
|
708
|
+
"7c6c98c3dc37aa0760796051b0b81ac10b9ebad7c9d7da3615b3fd764e589766",
|
|
702
709
|
"7c79750557c7d7156df6f135fb582ec09cc5f4987ac8e2af0f5113e42c117224",
|
|
703
710
|
"7d083db061c678113c12453eb73299caa9e207dd6418ad63406154fd330f3309",
|
|
704
711
|
"7d2239e2cd4893c57ac0bf1373a2ef46419f614d0ce18a12df51222bc7795327",
|
|
@@ -916,6 +923,7 @@
|
|
|
916
923
|
"e2070548ec9a6244c569ef0b9a43c2e5dd99cf9c0fa4540a21fd0595b291e444",
|
|
917
924
|
"e29fec7d54a144ea4867a3764fccdee6849d58d0f32eacdd56b2c317863fa1c6",
|
|
918
925
|
"e2e0fc585321ee2013cccaed95d47c49fbca71b54c67abad9080d19d70e3c1a5",
|
|
926
|
+
"e389e1e77cc2da32214e95451b25b45402b1b586b26f5688bb373c492db3fcfb",
|
|
919
927
|
"e3b2f7be15a793f07cbe8e51aa2feeac51d4c67077b94e5e20bad2e14be07fc5",
|
|
920
928
|
"e468c242cc38c390f9679fca61f355848f58d51570249dfbb65b4f2e26a9dfb1",
|
|
921
929
|
"e4bafa0f553e899b65f05feabf4cbe86d8246c57cbba745eb79e6aa858f40a6b",
|
package/bin/skill-history.json
CHANGED
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"59f0ecc2c1fd9620e4cac06be370e0bf9965a35c20616047445dbc42da6a1677",
|
|
60
60
|
"5be2e643f96b6ce503ae8d631c67729f0c24b6c5d2b431c087161b520ccbe417",
|
|
61
61
|
"61ec4c0435a2f0b307df8e88d81d9862c3abc1bf758648f2c18039581596659b",
|
|
62
|
+
"628a40e873d156e9179fd5a6bb3da9f910b6dde0886055804a506cdf8a631aaa",
|
|
62
63
|
"628ee7de57717804cb2b4f4c9357751578276f241eb3ab53fdee49ae92d57513",
|
|
63
64
|
"6320c0d8a5cb5ae82fc08c9c05c9151b00366ef759c824c16d4b777ccc30c771",
|
|
64
65
|
"640500e3ada3d81645c293ddc956e9757f0c4ba0a06e3f914c9bdad4968cbc66",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
# 6. Preserves codex's exact exit code.
|
|
36
36
|
#
|
|
37
37
|
# USAGE:
|
|
38
|
-
# bash codex-monitored.sh -C <repo> -s read-only
|
|
38
|
+
# bash codex-monitored.sh -C <repo> -s read-only "<prompt>"
|
|
39
39
|
# bash codex-monitored.sh resume --last
|
|
40
40
|
# (Args after the script name are passed verbatim to `codex exec`.)
|
|
41
41
|
#
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devlyn-cli",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.15",
|
|
4
4
|
"description": "Loop & harness engineering for AI coding agents (Claude Code, Codex, and any AGENTS.md-driven agent) — core engineering principles for CLAUDE.md/AGENTS.md and a loop designer that splits one intent into tasks agents drain hands-free",
|
|
5
5
|
"homepage": "https://github.com/fysoul17/devlyn-cli#readme",
|
|
6
6
|
"bin": {
|