@iamdevlinph/codex-kit 1.1.7 → 1.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/README.md +10 -1
- package/bin/codex-kit.js +94 -77
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,6 +60,12 @@ existing active guidance. During reconciliation, Codex merges only applicable
|
|
|
60
60
|
rules into the project's `AGENTS.md` and preserves its local organization and
|
|
61
61
|
adaptations.
|
|
62
62
|
|
|
63
|
+
Both `project init` and `project sync` contact the public npm registry before
|
|
64
|
+
writing project files. If the installed CLI is stale, or npm is unreachable or
|
|
65
|
+
returns invalid metadata, the command fails without changing the project. Rerun
|
|
66
|
+
with `pnpm dlx @iamdevlinph/codex-kit@latest` after the registry is available;
|
|
67
|
+
stale builds print the exact command.
|
|
68
|
+
|
|
63
69
|
## Commands
|
|
64
70
|
|
|
65
71
|
| Action | Command |
|
|
@@ -179,7 +185,10 @@ codex-kit project sync --cwd /path/to/project
|
|
|
179
185
|
- Codex with custom subagent and lifecycle-hook support
|
|
180
186
|
|
|
181
187
|
The published package contains no credentials or runtime dependencies. Version
|
|
182
|
-
checks contact the public npm
|
|
188
|
+
checks and project initialization/synchronization contact the public npm
|
|
189
|
+
registry; project operations fail closed before writing when that check cannot
|
|
190
|
+
verify the latest release. The CLI never auto-installs or executes downloaded
|
|
191
|
+
code.
|
|
183
192
|
|
|
184
193
|
## Security and license
|
|
185
194
|
|
package/bin/codex-kit.js
CHANGED
|
@@ -575,6 +575,87 @@ function uninstallGlobal(options) {
|
|
|
575
575
|
// src/project/commands.ts
|
|
576
576
|
import { existsSync as existsSync6, statSync as statSync2 } from "node:fs";
|
|
577
577
|
import { join as join6 } from "node:path";
|
|
578
|
+
|
|
579
|
+
// src/version.ts
|
|
580
|
+
function parseVersion(value) {
|
|
581
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(value);
|
|
582
|
+
if (!match) throw new Error(`Invalid package version: ${value}`);
|
|
583
|
+
return {
|
|
584
|
+
numbers: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
585
|
+
prerelease: match[4] ?? null
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
function compareVersions(left, right) {
|
|
589
|
+
const a = parseVersion(left);
|
|
590
|
+
const b = parseVersion(right);
|
|
591
|
+
for (const [leftNumber, rightNumber] of [
|
|
592
|
+
[a.numbers[0], b.numbers[0]],
|
|
593
|
+
[a.numbers[1], b.numbers[1]],
|
|
594
|
+
[a.numbers[2], b.numbers[2]]
|
|
595
|
+
])
|
|
596
|
+
if (leftNumber !== rightNumber) return Math.sign(leftNumber - rightNumber);
|
|
597
|
+
if (a.prerelease === b.prerelease) return 0;
|
|
598
|
+
if (!a.prerelease) return 1;
|
|
599
|
+
if (!b.prerelease) return -1;
|
|
600
|
+
return Math.sign(
|
|
601
|
+
a.prerelease.localeCompare(b.prerelease, "en", { numeric: true })
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
async function fetchLatestVersion() {
|
|
605
|
+
const url = `${REGISTRY}/${encodeURIComponent(PACKAGE.name)}/latest`;
|
|
606
|
+
let response;
|
|
607
|
+
try {
|
|
608
|
+
response = await fetch(url, { signal: AbortSignal.timeout(15e3) });
|
|
609
|
+
} catch (error) {
|
|
610
|
+
throw new Error(
|
|
611
|
+
`Unable to check ${REGISTRY}: ${error instanceof Error ? error.message : String(error)}`
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
if (!response.ok)
|
|
615
|
+
throw new Error(
|
|
616
|
+
`Unable to check ${REGISTRY}: ${response.status} ${response.statusText}`
|
|
617
|
+
);
|
|
618
|
+
let value;
|
|
619
|
+
try {
|
|
620
|
+
value = await response.json();
|
|
621
|
+
} catch {
|
|
622
|
+
throw new Error("Registry returned no package version.");
|
|
623
|
+
}
|
|
624
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || typeof value.version !== "string")
|
|
625
|
+
throw new Error("Registry returned no package version.");
|
|
626
|
+
const latest = value.version;
|
|
627
|
+
parseVersion(latest);
|
|
628
|
+
return latest;
|
|
629
|
+
}
|
|
630
|
+
async function getLatestVersion() {
|
|
631
|
+
const override = process.env.CODEX_KIT_LATEST_VERSION;
|
|
632
|
+
if (override) {
|
|
633
|
+
parseVersion(override);
|
|
634
|
+
return override;
|
|
635
|
+
}
|
|
636
|
+
return fetchLatestVersion();
|
|
637
|
+
}
|
|
638
|
+
async function checkVersion() {
|
|
639
|
+
const latest = await getLatestVersion();
|
|
640
|
+
console.log(`Installed: ${PACKAGE.version}`);
|
|
641
|
+
console.log(`Latest: ${latest}`);
|
|
642
|
+
const comparison = compareVersions(PACKAGE.version, latest);
|
|
643
|
+
if (comparison === 0) {
|
|
644
|
+
console.log("codex-kit is up to date.");
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
if (comparison > 0) {
|
|
648
|
+
console.log("This local build is newer than the published package.");
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
console.log(
|
|
652
|
+
`Update available. Run:
|
|
653
|
+
pnpm add --global ${PACKAGE.name}@latest
|
|
654
|
+
codex-kit global install`
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// src/project/commands.ts
|
|
578
659
|
var STATE_FILE2 = ".codex-kit-state.json";
|
|
579
660
|
var PROJECT_BEGIN = "<!-- BEGIN codex-kit:shared-template -->";
|
|
580
661
|
var PROJECT_END = "<!-- END codex-kit:shared-template -->";
|
|
@@ -644,9 +725,17 @@ and validation succeed, confirm codex-kit project status is up to date, then
|
|
|
644
725
|
report any template-worthy generalized promotion.
|
|
645
726
|
===== END CODEX RECONCILIATION PROMPT =====`;
|
|
646
727
|
}
|
|
647
|
-
function syncProject(options) {
|
|
728
|
+
async function syncProject(options, action = "sync") {
|
|
648
729
|
const { cwd } = options;
|
|
649
730
|
requireDirectory(cwd);
|
|
731
|
+
const latest = await getLatestVersion();
|
|
732
|
+
if (compareVersions(PACKAGE.version, latest) < 0)
|
|
733
|
+
throw new Error(
|
|
734
|
+
`Installed: ${PACKAGE.version}
|
|
735
|
+
Latest: ${latest}
|
|
736
|
+
Published guidelines are newer than this local build. Rerun with:
|
|
737
|
+
pnpm dlx ${PACKAGE.name}@latest project ${action} --cwd '${cwd.replaceAll("'", "'\\''")}'`
|
|
738
|
+
);
|
|
650
739
|
const agentsFile = join6(cwd, "AGENTS.md");
|
|
651
740
|
const stagedTemplate = join6(cwd, "TEMPLATE_AGENTS.md");
|
|
652
741
|
const desired = Buffer.from(readText(TEMPLATE_FILE));
|
|
@@ -744,79 +833,6 @@ function markApplied(options) {
|
|
|
744
833
|
console.log(`recorded template reconciliation: ${stagedTemplate}`);
|
|
745
834
|
}
|
|
746
835
|
|
|
747
|
-
// src/version.ts
|
|
748
|
-
function parseVersion(value) {
|
|
749
|
-
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(value);
|
|
750
|
-
if (!match) throw new Error(`Invalid package version: ${value}`);
|
|
751
|
-
return {
|
|
752
|
-
numbers: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
753
|
-
prerelease: match[4] ?? null
|
|
754
|
-
};
|
|
755
|
-
}
|
|
756
|
-
function compareVersions(left, right) {
|
|
757
|
-
const a = parseVersion(left);
|
|
758
|
-
const b = parseVersion(right);
|
|
759
|
-
for (const [leftNumber, rightNumber] of [
|
|
760
|
-
[a.numbers[0], b.numbers[0]],
|
|
761
|
-
[a.numbers[1], b.numbers[1]],
|
|
762
|
-
[a.numbers[2], b.numbers[2]]
|
|
763
|
-
])
|
|
764
|
-
if (leftNumber !== rightNumber) return Math.sign(leftNumber - rightNumber);
|
|
765
|
-
if (a.prerelease === b.prerelease) return 0;
|
|
766
|
-
if (!a.prerelease) return 1;
|
|
767
|
-
if (!b.prerelease) return -1;
|
|
768
|
-
return Math.sign(
|
|
769
|
-
a.prerelease.localeCompare(b.prerelease, "en", { numeric: true })
|
|
770
|
-
);
|
|
771
|
-
}
|
|
772
|
-
async function fetchLatestVersion() {
|
|
773
|
-
const url = `${REGISTRY}/${encodeURIComponent(PACKAGE.name)}/latest`;
|
|
774
|
-
let response;
|
|
775
|
-
try {
|
|
776
|
-
response = await fetch(url, { signal: AbortSignal.timeout(15e3) });
|
|
777
|
-
} catch (error) {
|
|
778
|
-
throw new Error(
|
|
779
|
-
`Unable to check ${REGISTRY}: ${error instanceof Error ? error.message : String(error)}`
|
|
780
|
-
);
|
|
781
|
-
}
|
|
782
|
-
if (!response.ok)
|
|
783
|
-
throw new Error(
|
|
784
|
-
`Unable to check ${REGISTRY}: ${response.status} ${response.statusText}`
|
|
785
|
-
);
|
|
786
|
-
let value;
|
|
787
|
-
try {
|
|
788
|
-
value = await response.json();
|
|
789
|
-
} catch {
|
|
790
|
-
throw new Error("Registry returned no package version.");
|
|
791
|
-
}
|
|
792
|
-
if (!value || typeof value !== "object" || Array.isArray(value) || typeof value.version !== "string")
|
|
793
|
-
throw new Error("Registry returned no package version.");
|
|
794
|
-
const latest = value.version;
|
|
795
|
-
parseVersion(latest);
|
|
796
|
-
return latest;
|
|
797
|
-
}
|
|
798
|
-
async function checkVersion() {
|
|
799
|
-
let latest = process.env.CODEX_KIT_LATEST_VERSION;
|
|
800
|
-
if (!latest) latest = await fetchLatestVersion();
|
|
801
|
-
if (!latest) throw new Error("Registry returned no package version.");
|
|
802
|
-
console.log(`Installed: ${PACKAGE.version}`);
|
|
803
|
-
console.log(`Latest: ${latest}`);
|
|
804
|
-
const comparison = compareVersions(PACKAGE.version, latest);
|
|
805
|
-
if (comparison === 0) {
|
|
806
|
-
console.log("codex-kit is up to date.");
|
|
807
|
-
return;
|
|
808
|
-
}
|
|
809
|
-
if (comparison > 0) {
|
|
810
|
-
console.log("This local build is newer than the published package.");
|
|
811
|
-
return;
|
|
812
|
-
}
|
|
813
|
-
console.log(
|
|
814
|
-
`Update available. Run:
|
|
815
|
-
pnpm add --global ${PACKAGE.name}@latest
|
|
816
|
-
codex-kit global install`
|
|
817
|
-
);
|
|
818
|
-
}
|
|
819
|
-
|
|
820
836
|
// src/cli/options.ts
|
|
821
837
|
import { homedir } from "node:os";
|
|
822
838
|
import { join as join7, resolve as resolve2 } from "node:path";
|
|
@@ -865,8 +881,8 @@ Commands:
|
|
|
865
881
|
global configure Set the orchestrator and normal/Plan reasoning defaults.
|
|
866
882
|
global list Show model settings, routing status, and custom agents.
|
|
867
883
|
global uninstall Restore managed config values and remove package-owned files.
|
|
868
|
-
project init Initialize
|
|
869
|
-
project sync Refresh
|
|
884
|
+
project init Initialize project files after checking the latest npm release.
|
|
885
|
+
project sync Refresh the template after checking the latest npm release.
|
|
870
886
|
project status Show whether template changes still need reconciliation.
|
|
871
887
|
project mark-applied Record the current template as reconciled with AGENTS.md.
|
|
872
888
|
version check Compare the installed version with the latest npm release.
|
|
@@ -891,6 +907,7 @@ Options by command:
|
|
|
891
907
|
|
|
892
908
|
project init, project sync
|
|
893
909
|
--cwd PATH Use a project directory other than the current directory.
|
|
910
|
+
npm access is required; stale or unverifiable builds fail before writes.
|
|
894
911
|
|
|
895
912
|
project status, project mark-applied
|
|
896
913
|
--cwd PATH Use a project directory other than the current directory.
|
|
@@ -919,7 +936,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
919
936
|
else if (scope === "global" && action === "uninstall")
|
|
920
937
|
uninstallGlobal(options);
|
|
921
938
|
else if (scope === "project" && (action === "init" || action === "sync"))
|
|
922
|
-
syncProject(options);
|
|
939
|
+
await syncProject(options, action);
|
|
923
940
|
else if (scope === "project" && action === "status") projectStatus(options);
|
|
924
941
|
else if (scope === "project" && action === "mark-applied")
|
|
925
942
|
markApplied(options);
|