claude-codex-pair 0.4.0 → 0.4.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/DESIGN.md +3 -1
- package/README.md +4 -2
- package/dist/pair.js +37 -13
- package/package.json +1 -1
package/DESIGN.md
CHANGED
|
@@ -86,7 +86,9 @@ at most once a day, cache the answer under the state directory, and stay quiet o
|
|
|
86
86
|
to stderr after the command's own output, so `pair wait`'s first line is still the delivery or
|
|
87
87
|
timeout line agents read. `pair upgrade` installs with npm, then runs the `init` of the package it
|
|
88
88
|
just installed (found with `npm root --global`), not the first `pair` on PATH, because both this
|
|
89
|
-
process and an older copy on PATH would write the old templates.
|
|
89
|
+
process and an older copy on PATH would write the old templates. It asks `npm view` first, so it uses
|
|
90
|
+
the same registry as the install. Already on the latest version, it only runs the in-process
|
|
91
|
+
refresh. If the check fails, it goes ahead with the install, which reports the actual npm error.
|
|
90
92
|
|
|
91
93
|
Channel operations report `EACCES` and `EPERM` with the affected path and the sandbox
|
|
92
94
|
configuration printed by `init`. Either ordinary permissions or sandbox restrictions can
|
package/README.md
CHANGED
|
@@ -203,8 +203,10 @@ offline or sandboxed.
|
|
|
203
203
|
## Upgrading
|
|
204
204
|
|
|
205
205
|
Run `pair upgrade` in your own terminal, not through an agent: agent sandboxes block the network and
|
|
206
|
-
global installs.
|
|
207
|
-
current worktree if pair is set up there
|
|
206
|
+
global installs. If npm has a newer version, it runs `npm install -g claude-codex-pair@latest`, then
|
|
207
|
+
the new `pair init` in the current worktree if pair is set up there, and prints only the files that
|
|
208
|
+
`init` wrote or kept. Already on the latest version, it installs nothing and only refreshes this
|
|
209
|
+
worktree's stale instructions. Other worktrees refresh their instructions on the next
|
|
208
210
|
`pair send`, `wait`, `history` or `clean`. pair owns these files, so edits inside them are
|
|
209
211
|
overwritten. pair, including `pair init`, never rewrites instructions that a newer pair wrote, so
|
|
210
212
|
worktrees shared by different versions don't flip back and forth. To downgrade, delete them first. Restart Claude Code and Codex afterwards. Running
|
package/dist/pair.js
CHANGED
|
@@ -892,24 +892,31 @@ function status(channel, root) {
|
|
|
892
892
|
* Returns a note for after the command's output: agents read `pair wait`'s first line, with stderr merged.
|
|
893
893
|
*/
|
|
894
894
|
function refreshInstructions(root) {
|
|
895
|
-
const skillPath = join(root, ".claude", "skills", "pair", "SKILL.md");
|
|
896
|
-
const agentsPath = join(root, "AGENTS.md");
|
|
897
|
-
const refreshed = [];
|
|
898
895
|
try {
|
|
899
|
-
|
|
900
|
-
writeFileSync(skillPath, claudeSkill());
|
|
901
|
-
refreshed.push(skillPath);
|
|
902
|
-
}
|
|
903
|
-
if (instructionState(agentsPath, codexSection(), true) === "stale") {
|
|
904
|
-
writeFileSync(agentsPath, readFileSync(agentsPath, "utf8").replace(PAIR_SECTION, () => codexSection()));
|
|
905
|
-
refreshed.push(`${agentsPath} (pair section)`);
|
|
906
|
-
}
|
|
896
|
+
return refreshedNote(refreshStale(root));
|
|
907
897
|
}
|
|
908
898
|
catch (error) {
|
|
909
899
|
// A read-only sandbox: message delivery must still work, so report and go on.
|
|
910
900
|
const reason = error instanceof Error ? error.message : String(error);
|
|
911
901
|
return `pair: couldn't refresh instructions (${reason}); run \`pair init\` in your own terminal`;
|
|
912
902
|
}
|
|
903
|
+
}
|
|
904
|
+
/** The stale instruction files it rewrote. A write failure throws. */
|
|
905
|
+
function refreshStale(root) {
|
|
906
|
+
const skillPath = join(root, ".claude", "skills", "pair", "SKILL.md");
|
|
907
|
+
const agentsPath = join(root, "AGENTS.md");
|
|
908
|
+
const refreshed = [];
|
|
909
|
+
if (instructionState(skillPath, claudeSkill()) === "stale") {
|
|
910
|
+
writeFileSync(skillPath, claudeSkill());
|
|
911
|
+
refreshed.push(skillPath);
|
|
912
|
+
}
|
|
913
|
+
if (instructionState(agentsPath, codexSection(), true) === "stale") {
|
|
914
|
+
writeFileSync(agentsPath, readFileSync(agentsPath, "utf8").replace(PAIR_SECTION, () => codexSection()));
|
|
915
|
+
refreshed.push(`${agentsPath} (pair section)`);
|
|
916
|
+
}
|
|
917
|
+
return refreshed;
|
|
918
|
+
}
|
|
919
|
+
function refreshedNote(refreshed) {
|
|
913
920
|
return refreshed.length > 0
|
|
914
921
|
? `pair: refreshed ${refreshed.join(", ")} to pair ${PACKAGE.version}; reload agent sessions to load them`
|
|
915
922
|
: undefined;
|
|
@@ -964,6 +971,21 @@ async function updateNotice() {
|
|
|
964
971
|
}
|
|
965
972
|
/** Installs the latest pair, then lets the new version refresh this worktree's instructions. */
|
|
966
973
|
function upgrade(root) {
|
|
974
|
+
// npm's own answer, from the registry it installs from; if it fails, the install reports why.
|
|
975
|
+
const view = spawnSync("npm", ["view", PACKAGE.name, "version"], { encoding: "utf8" });
|
|
976
|
+
const latest = view.status === 0 ? view.stdout.trim() : undefined;
|
|
977
|
+
if (latest && !isNewer(latest, PACKAGE.version)) {
|
|
978
|
+
let note;
|
|
979
|
+
try {
|
|
980
|
+
note = refreshedNote(refreshStale(root)); // refreshing is all that is left to do, so a failure fails upgrade
|
|
981
|
+
}
|
|
982
|
+
catch (error) {
|
|
983
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
984
|
+
throw new PairError(`already up to date, but couldn't refresh instructions (${reason})`);
|
|
985
|
+
}
|
|
986
|
+
console.log(`already up to date: ${PACKAGE.name} ${PACKAGE.version}${note ? `\n${note}` : ""}`);
|
|
987
|
+
return 0;
|
|
988
|
+
}
|
|
967
989
|
const install = spawnSync("npm", ["install", "--global", `${PACKAGE.name}@latest`], { stdio: "inherit" });
|
|
968
990
|
if (install.error) {
|
|
969
991
|
throw new PairError(`couldn't run npm: ${install.error.message}`);
|
|
@@ -982,12 +1004,14 @@ function upgrade(root) {
|
|
|
982
1004
|
throw new PairError("installed, but `npm root --global` failed; run `pair init` yourself");
|
|
983
1005
|
}
|
|
984
1006
|
const installed = join(globalRoot.stdout.trim(), PACKAGE.name, "dist", "pair.js");
|
|
985
|
-
const init = spawnSync(process.execPath, [installed, "init"], { cwd: root, stdio: "inherit" });
|
|
1007
|
+
const init = spawnSync(process.execPath, [installed, "init"], { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "inherit"] });
|
|
986
1008
|
if (init.error || init.status !== 0) {
|
|
987
1009
|
throw new PairError(`installed, but the new \`pair init\` failed${init.error ? `: ${init.error.message}` : ""}; run it yourself`);
|
|
988
1010
|
}
|
|
1011
|
+
// Only what it did to the files: the sandbox and `codex mcp add` setup it also prints is already done.
|
|
1012
|
+
console.log(init.stdout.split("\n").filter((line) => /^(?:wrote|kept): /.test(line)).join("\n"));
|
|
989
1013
|
}
|
|
990
|
-
console.log("Restart Claude Code and Codex sessions to load
|
|
1014
|
+
console.log(`upgraded: ${PACKAGE.name} ${PACKAGE.version} → ${latest ?? "latest"}. Restart Claude Code and Codex sessions to load it; other worktrees refresh on their next pair send or wait.`);
|
|
991
1015
|
return 0;
|
|
992
1016
|
}
|
|
993
1017
|
/** Finished threads, most recently finished first. Entries that aren't archived threads are ignored. */
|