create-egregore 0.19.5 → 0.19.7
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/assets/egregore-launcher.js +411 -25
- package/bin/cli.js +34 -20
- package/lib/local.js +21 -5
- package/lib/pi-runtime.js +186 -0
- package/lib/setup.js +56 -11
- package/lib/ui.js +1 -1
- package/package.json +7 -5
- package/runtime/codex/.codex/spec-manifest.json +1 -1
- package/runtime/codex/AGENTS.md +7 -2
- package/runtime/codex/bin/codex-render-spec.mjs +6 -1
- package/runtime/codex/bin/codex-session-start.sh +5 -59
- package/runtime/codex/bin/codex-skill-render.mjs +7 -5
- package/runtime/codex/bin/lib/context.sh +8 -1
- package/runtime/codex/bin/lib/greeting.sh +12 -108
- package/runtime/codex/bin/lib/metrics.sh +374 -0
- package/runtime/codex/bin/publish-artifact.sh +14 -0
- package/runtime/codex/bin/settings.sh +274 -0
- package/runtime/codex/manifest.json +2 -0
- package/runtime/pi/.codex/config.toml +15 -0
- package/runtime/pi/.codex/hooks/branch-guard.js +242 -0
- package/runtime/pi/.codex/hooks/search-hint.js +65 -0
- package/runtime/pi/.codex/hooks.json +30 -0
- package/runtime/pi/.codex/skills/activity/SKILL.md +70 -0
- package/runtime/pi/.codex/skills/add/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/announce/SKILL.md +54 -0
- package/runtime/pi/.codex/skills/answer/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/archive/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/ask/SKILL.md +59 -0
- package/runtime/pi/.codex/skills/branch/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/checkup/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/commit/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/contribute/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/dark-mode/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/dashboard/SKILL.md +59 -0
- package/runtime/pi/.codex/skills/deep-reflect/SKILL.md +74 -0
- package/runtime/pi/.codex/skills/delete-user/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/egregore-voice/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/emissary/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/env/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/handoff/SKILL.md +67 -0
- package/runtime/pi/.codex/skills/harvest/SKILL.md +107 -0
- package/runtime/pi/.codex/skills/ingest/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/ingest-google/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/ingest-user-interview/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/invite/SKILL.md +40 -0
- package/runtime/pi/.codex/skills/issue/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/me/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/meeting/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/minion/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/note/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/onboarding/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/pr/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/project/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/pull/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/push/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/quest/SKILL.md +77 -0
- package/runtime/pi/.codex/skills/quest-suggest/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/reflect/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/review-pr/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/save/SKILL.md +62 -0
- package/runtime/pi/.codex/skills/scroll/SKILL.md +168 -0
- package/runtime/pi/.codex/skills/scroll/agents/openai.yaml +4 -0
- package/runtime/pi/.codex/skills/scroll/assets/shell.html +542 -0
- package/runtime/pi/.codex/skills/search/SKILL.md +56 -0
- package/runtime/pi/.codex/skills/session-view/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/setup/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/summon/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/sync-repos/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/telegram-connect/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/telemetry/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/test/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/the-spiral/SKILL.md +84 -0
- package/runtime/pi/.codex/skills/thread/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/todo/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/tui-design/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/tutorial/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/update/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/view/SKILL.md +156 -0
- package/runtime/pi/.codex/skills/view/agents/openai.yaml +4 -0
- package/runtime/pi/.codex/skills/view/assets/compose-scaffold.html +221 -0
- package/runtime/pi/.codex/skills/visual-explain/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/wrap/SKILL.md +55 -0
- package/runtime/pi/.codex/spec-manifest.json +114 -0
- package/runtime/pi/.pi/APPEND_SYSTEM.md +255 -0
- package/runtime/pi/.pi/extensions/egregore.ts +324 -0
- package/runtime/pi/.pi/settings.json +6 -0
- package/runtime/pi/.pi/spec-manifest.json +12 -0
- package/runtime/pi/AGENTS.md +350 -0
- package/runtime/pi/bin/activity-data.sh +242 -0
- package/runtime/pi/bin/agent.sh +677 -0
- package/runtime/pi/bin/codex-install-skills.sh +78 -0
- package/runtime/pi/bin/codex-render-spec.mjs +394 -0
- package/runtime/pi/bin/codex-session-start.sh +188 -0
- package/runtime/pi/bin/codex-skill-render.mjs +323 -0
- package/runtime/pi/bin/codex-sync-skills.sh +227 -0
- package/runtime/pi/bin/dashboard-data.sh +178 -0
- package/runtime/pi/bin/graph-batch.sh +60 -0
- package/runtime/pi/bin/graph-op.sh +431 -0
- package/runtime/pi/bin/graph-wal.sh +228 -0
- package/runtime/pi/bin/graph.sh +177 -0
- package/runtime/pi/bin/handoff-pr-backfill.sh +86 -0
- package/runtime/pi/bin/handoff-run.sh +581 -0
- package/runtime/pi/bin/handoff-save-egregore.sh +136 -0
- package/runtime/pi/bin/index-handoff.sh +312 -0
- package/runtime/pi/bin/lib/artifact-id.sh +46 -0
- package/runtime/pi/bin/lib/config.sh +71 -0
- package/runtime/pi/bin/lib/context.sh +542 -0
- package/runtime/pi/bin/lib/dashboard-artifact.sh +142 -0
- package/runtime/pi/bin/lib/ensure-develop.sh +183 -0
- package/runtime/pi/bin/lib/git-sync.sh +288 -0
- package/runtime/pi/bin/lib/greeting.sh +340 -0
- package/runtime/pi/bin/lib/hash.sh +13 -0
- package/runtime/pi/bin/lib/identity.sh +174 -0
- package/runtime/pi/bin/lib/metrics.sh +374 -0
- package/runtime/pi/bin/lib/permissions.sh +106 -0
- package/runtime/pi/bin/lib/time.sh +56 -0
- package/runtime/pi/bin/lib/worktree-links.sh +54 -0
- package/runtime/pi/bin/notify.sh +207 -0
- package/runtime/pi/bin/pi-branch-policy.mjs +15 -0
- package/runtime/pi/bin/pi-product-workflows.mjs +324 -0
- package/runtime/pi/bin/pi-render-spec.mjs +114 -0
- package/runtime/pi/bin/pi-session-start.sh +24 -0
- package/runtime/pi/bin/publish-artifact.sh +201 -0
- package/runtime/pi/bin/publish-references.sh +144 -0
- package/runtime/pi/bin/repo-state.sh +99 -0
- package/runtime/pi/bin/telemetry.sh +391 -0
- package/runtime/pi/bin/worktree-create.sh +118 -0
- package/runtime/pi/bin/worktree-remove.sh +50 -0
- package/runtime/pi/bin/worktree.sh +198 -0
- package/runtime/pi/manifest.json +176 -0
package/bin/cli.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* create-egregore — set up Egregore for your team in one command.
|
|
5
5
|
*
|
|
6
6
|
* - Installs an `egregore` PATH binary instead of a shell alias
|
|
7
|
-
* - Auto-execs into the selected
|
|
7
|
+
* - Auto-execs into the selected harness (Claude Code, Codex, or Pi) at the end
|
|
8
8
|
*
|
|
9
9
|
* Four modes:
|
|
10
10
|
* npx -y create-egregore@latest --token st_xxxx (from website)
|
|
@@ -30,6 +30,11 @@ const {
|
|
|
30
30
|
installCodexRuntime,
|
|
31
31
|
reportCodexRuntimeSummary,
|
|
32
32
|
} = require("../lib/codex-runtime");
|
|
33
|
+
const {
|
|
34
|
+
hasPiRuntimeSupport,
|
|
35
|
+
installPiRuntime,
|
|
36
|
+
reportPiRuntimeSummary,
|
|
37
|
+
} = require("../lib/pi-runtime");
|
|
33
38
|
const {
|
|
34
39
|
install,
|
|
35
40
|
ghApi,
|
|
@@ -96,10 +101,13 @@ function binaryOnPath(bin) {
|
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
function assistantLabel(runtime) {
|
|
99
|
-
|
|
104
|
+
const normalized = normalizeRuntime(runtime);
|
|
105
|
+
if (normalized === "codex") return "Codex";
|
|
106
|
+
if (normalized === "pi") return "Pi";
|
|
107
|
+
return "Claude Code";
|
|
100
108
|
}
|
|
101
109
|
|
|
102
|
-
function
|
|
110
|
+
function upgradePortableRuntimesForExisting(instances) {
|
|
103
111
|
for (const inst of instances) {
|
|
104
112
|
if (!inst || !inst.path || !fs.existsSync(inst.path)) continue;
|
|
105
113
|
try {
|
|
@@ -109,8 +117,14 @@ function upgradeCodexRuntimeForExisting(instances) {
|
|
|
109
117
|
label: `Codex runtime for ${inst.slug || inst.name || path.basename(inst.path)}`,
|
|
110
118
|
includeConflicts: !ready,
|
|
111
119
|
});
|
|
120
|
+
const piSummary = installPiRuntime(inst.path);
|
|
121
|
+
const piReady = hasPiRuntimeSupport(inst.path);
|
|
122
|
+
reportPiRuntimeSummary(piSummary, ui, {
|
|
123
|
+
label: `Pi meta-harness for ${inst.slug || inst.name || path.basename(inst.path)}`,
|
|
124
|
+
includeConflicts: !piReady,
|
|
125
|
+
});
|
|
112
126
|
} catch (err) {
|
|
113
|
-
ui.warn(`Could not
|
|
127
|
+
ui.warn(`Could not refresh shell-runtime support for ${inst.path}: ${err.message}`);
|
|
114
128
|
}
|
|
115
129
|
}
|
|
116
130
|
}
|
|
@@ -127,37 +141,34 @@ async function chooseRuntime(args) {
|
|
|
127
141
|
|
|
128
142
|
if (!process.stdin.isTTY) return "claude-code";
|
|
129
143
|
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
144
|
+
const installedByRuntime = {
|
|
145
|
+
"claude-code": binaryOnPath("claude"),
|
|
146
|
+
codex: binaryOnPath("codex"),
|
|
147
|
+
pi: binaryOnPath("pi"),
|
|
148
|
+
};
|
|
149
|
+
const recommended = Object.keys(installedByRuntime).find((runtime) => installedByRuntime[runtime]) || "claude-code";
|
|
150
|
+
const choices = ["claude-code", "codex", "pi"]
|
|
134
151
|
.map((runtime) => {
|
|
135
|
-
const installed = runtime
|
|
152
|
+
const installed = installedByRuntime[runtime];
|
|
136
153
|
const label = assistantLabel(runtime);
|
|
137
|
-
const missingCopy =
|
|
138
|
-
? "Install Codex later, then run egregore and choose Codex"
|
|
139
|
-
: "Install Claude Code later, then run egregore and choose Claude Code";
|
|
154
|
+
const missingCopy = `Install ${label} later, then run egregore and choose ${label}`;
|
|
140
155
|
return {
|
|
141
156
|
label: `${label}${installed ? "" : " (not installed)"}${recommended === runtime ? " (recommended)" : ""}`,
|
|
142
157
|
description: installed
|
|
143
|
-
? (runtime === "
|
|
158
|
+
? (runtime === "claude-code" ? "Installed · Claude Code integration" : runtime === "pi" ? "Installed · project-local meta-harness" : "Installed · portable agent protocol")
|
|
144
159
|
: missingCopy,
|
|
145
160
|
runtime,
|
|
146
161
|
installed,
|
|
147
162
|
};
|
|
148
163
|
})
|
|
149
164
|
.sort((a, b) => Number(b.installed) - Number(a.installed));
|
|
150
|
-
|
|
151
|
-
choices.push(
|
|
152
|
-
{ label: "Hermes", description: "coming soon", runtime: "hermes", disabled: true },
|
|
153
|
-
{ label: "Pi", description: "coming soon", runtime: "pi", disabled: true },
|
|
154
|
-
);
|
|
165
|
+
choices.push({ label: "Hermes", description: "coming soon", runtime: "hermes", disabled: true });
|
|
155
166
|
const choice = await ui.choose("Which harness do you want to use?", choices);
|
|
156
167
|
return choice.runtime;
|
|
157
168
|
}
|
|
158
169
|
|
|
159
170
|
async function upgradeLauncherFromExisting(instances) {
|
|
160
|
-
|
|
171
|
+
upgradePortableRuntimesForExisting(instances);
|
|
161
172
|
const inst = instances.find((entry) => entry && entry.path && fs.existsSync(entry.path));
|
|
162
173
|
if (!inst) return null;
|
|
163
174
|
try {
|
|
@@ -214,6 +225,8 @@ function parseArgs(argv) {
|
|
|
214
225
|
args.noWelcome = true;
|
|
215
226
|
} else if (argv[i] === "--codex") {
|
|
216
227
|
args.runtime = "codex";
|
|
228
|
+
} else if (argv[i] === "--pi") {
|
|
229
|
+
args.runtime = "pi";
|
|
217
230
|
} else if (argv[i] === "--claude" || argv[i] === "--claude-code") {
|
|
218
231
|
args.runtime = "claude-code";
|
|
219
232
|
} else if (argv[i] === "--runtime" && argv[i + 1]) {
|
|
@@ -376,8 +389,9 @@ function showHelp() {
|
|
|
376
389
|
ui.info(" --token <token> Setup token from egregore.xyz");
|
|
377
390
|
ui.info(" --api <url> Use connected API setup with this URL");
|
|
378
391
|
ui.info(" --codex Prefer Codex for this local install");
|
|
392
|
+
ui.info(" --pi Prefer Pi for this local install");
|
|
379
393
|
ui.info(" --claude Prefer Claude Code for this local install");
|
|
380
|
-
ui.info(" --runtime <name> Harness override: claude-code or
|
|
394
|
+
ui.info(" --runtime <name> Harness override: claude-code, codex, or pi");
|
|
381
395
|
ui.info(" --force Skip the in-repo detection check");
|
|
382
396
|
ui.info(" --no-autolaunch Don't launch the harness at the end (for CI)");
|
|
383
397
|
ui.info(" --no-screens Skip the full-screen welcome/ready bookends");
|
package/lib/local.js
CHANGED
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
tryGhAuthOrLogin,
|
|
17
17
|
} = require("./auth");
|
|
18
18
|
const { installCodexRuntime, reportCodexRuntimeSummary } = require("./codex-runtime");
|
|
19
|
+
const { installPiRuntime, reportPiRuntimeSummary } = require("./pi-runtime");
|
|
19
20
|
const {
|
|
20
21
|
install,
|
|
21
22
|
ghApi,
|
|
@@ -625,13 +626,13 @@ async function maybeSetupTelegramGroup(ui, {
|
|
|
625
626
|
return { setup: true, groupLink: storedGroupLink };
|
|
626
627
|
}
|
|
627
628
|
|
|
628
|
-
// Claude Code workspace cleanup: remove
|
|
629
|
+
// Claude Code workspace cleanup: remove shell-runtime overlays the
|
|
629
630
|
// GitHub template ships, so the agent follows CLAUDE.md rather than a competing
|
|
630
631
|
// startup protocol. Founder-only (we own the repo) — commit + push the removal
|
|
631
632
|
// so it persists for everyone who clones it. A Codex teammate who joins later
|
|
632
633
|
// regenerates AGENTS.md via /update (bin/codex-render-spec.mjs).
|
|
633
634
|
function stripCodexRuntimeForClaude(egregoreDir, ui) {
|
|
634
|
-
const targets = ["AGENTS.md", ".codex", ".agents"];
|
|
635
|
+
const targets = ["AGENTS.md", ".codex", ".agents", ".pi"];
|
|
635
636
|
const present = targets.filter((t) => fs.existsSync(path.join(egregoreDir, t)));
|
|
636
637
|
if (!present.length) {
|
|
637
638
|
ui.success("Claude Code workspace — using CLAUDE.md");
|
|
@@ -639,7 +640,7 @@ function stripCodexRuntimeForClaude(egregoreDir, ui) {
|
|
|
639
640
|
}
|
|
640
641
|
try {
|
|
641
642
|
execFileSync("git", ["rm", "-r", "-q", "--", ...present], { cwd: egregoreDir, stdio: "pipe" });
|
|
642
|
-
run('git commit -m "Claude Code workspace: use CLAUDE.md, drop
|
|
643
|
+
run('git commit -m "Claude Code workspace: use CLAUDE.md, drop shell-runtime overlays"', { cwd: egregoreDir });
|
|
643
644
|
run("git push", { cwd: egregoreDir });
|
|
644
645
|
ui.success(`Claude Code workspace — using CLAUDE.md (removed ${present.join(", ")})`);
|
|
645
646
|
} catch {
|
|
@@ -1355,7 +1356,7 @@ async function localFounderFlow(ui, ctx = {}) {
|
|
|
1355
1356
|
}
|
|
1356
1357
|
}
|
|
1357
1358
|
|
|
1358
|
-
// 16. Runtime overlay. Codex installs commit
|
|
1359
|
+
// 16. Runtime overlay. Codex and Pi installs commit their derived runtime
|
|
1359
1360
|
// so it's TRACKED (symmetric with .claude/). Claude installs do the
|
|
1360
1361
|
// opposite: Claude Code reads CLAUDE.md, not AGENTS.md, so we strip the
|
|
1361
1362
|
// Codex AGENTS.md/.codex the template ships — otherwise a fresh Claude
|
|
@@ -1378,6 +1379,17 @@ async function localFounderFlow(ui, ctx = {}) {
|
|
|
1378
1379
|
run("git push", { cwd: egregoreDir });
|
|
1379
1380
|
}
|
|
1380
1381
|
} catch {}
|
|
1382
|
+
} else if (preferredRuntime === "pi") {
|
|
1383
|
+
const piRuntime = installPiRuntime(egregoreDir);
|
|
1384
|
+
reportPiRuntimeSummary(piRuntime, ui);
|
|
1385
|
+
try {
|
|
1386
|
+
const toCommit = Array.isArray(piRuntime.files) ? [...piRuntime.files] : [];
|
|
1387
|
+
if (toCommit.length) {
|
|
1388
|
+
execFileSync("git", ["add", "--", ...toCommit], { cwd: egregoreDir, stdio: "pipe" });
|
|
1389
|
+
run('git commit -m "Add Pi meta-harness runtime"', { cwd: egregoreDir });
|
|
1390
|
+
run("git push", { cwd: egregoreDir });
|
|
1391
|
+
}
|
|
1392
|
+
} catch {}
|
|
1381
1393
|
} else {
|
|
1382
1394
|
stripCodexRuntimeForClaude(egregoreDir, ui);
|
|
1383
1395
|
}
|
|
@@ -1545,7 +1557,11 @@ async function localFounderFlow(ui, ctx = {}) {
|
|
|
1545
1557
|
return { label: `./${mrName}/`, description: "managed repo" };
|
|
1546
1558
|
}),
|
|
1547
1559
|
];
|
|
1548
|
-
const assistantName = preferredRuntime === "codex"
|
|
1560
|
+
const assistantName = preferredRuntime === "codex"
|
|
1561
|
+
? "Codex"
|
|
1562
|
+
: preferredRuntime === "pi"
|
|
1563
|
+
? "Pi"
|
|
1564
|
+
: "Claude Code";
|
|
1549
1565
|
const setupSummary = {
|
|
1550
1566
|
workspace: "created",
|
|
1551
1567
|
invite: invitedUsers.length
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("node:crypto");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
|
|
7
|
+
const PACKAGE = require("../package.json");
|
|
8
|
+
|
|
9
|
+
const BUNDLE_DIR = path.join(__dirname, "..", "runtime", "pi");
|
|
10
|
+
const BUNDLE_MANIFEST = path.join(BUNDLE_DIR, "manifest.json");
|
|
11
|
+
const LOCAL_MANIFEST = path.join(".egregore", "pi-runtime-manifest.json");
|
|
12
|
+
|
|
13
|
+
const REQUIRED_RUNTIME_PATHS = [
|
|
14
|
+
"AGENTS.md",
|
|
15
|
+
".pi/APPEND_SYSTEM.md",
|
|
16
|
+
".pi/settings.json",
|
|
17
|
+
".pi/extensions/egregore.ts",
|
|
18
|
+
".codex/skills",
|
|
19
|
+
"bin/agent.sh",
|
|
20
|
+
"bin/pi-branch-policy.mjs",
|
|
21
|
+
"bin/pi-session-start.sh",
|
|
22
|
+
"bin/codex-session-start.sh",
|
|
23
|
+
"bin/codex-skill-render.mjs",
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
function hashBuffer(buffer) {
|
|
27
|
+
return crypto.createHash("sha256").update(buffer).digest("hex");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function readJson(file, fallback) {
|
|
31
|
+
try {
|
|
32
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
33
|
+
} catch {
|
|
34
|
+
return fallback;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function listFiles(dir, prefix = "") {
|
|
39
|
+
if (!fs.existsSync(dir)) return [];
|
|
40
|
+
const result = [];
|
|
41
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
42
|
+
const rel = prefix ? path.join(prefix, entry.name) : entry.name;
|
|
43
|
+
const full = path.join(dir, entry.name);
|
|
44
|
+
if (entry.isDirectory()) result.push(...listFiles(full, rel));
|
|
45
|
+
else if (entry.isFile()) result.push(rel);
|
|
46
|
+
}
|
|
47
|
+
return result.sort();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function bundleManifest() {
|
|
51
|
+
return readJson(BUNDLE_MANIFEST, { files: [], skills: [], skillCount: 0 });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function bundleFiles() {
|
|
55
|
+
return listFiles(BUNDLE_DIR).filter((rel) => rel !== "manifest.json");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function installManifestPath(egregoreDir) {
|
|
59
|
+
const gitPath = path.join(egregoreDir, ".git");
|
|
60
|
+
try {
|
|
61
|
+
const stat = fs.lstatSync(gitPath);
|
|
62
|
+
if (stat.isDirectory()) return path.join(gitPath, "info", "egregore-pi-runtime.json");
|
|
63
|
+
if (stat.isFile()) {
|
|
64
|
+
const match = fs.readFileSync(gitPath, "utf8").trim().match(/^gitdir:\s*(.+)$/);
|
|
65
|
+
if (match) {
|
|
66
|
+
const gitDir = path.isAbsolute(match[1]) ? match[1] : path.resolve(egregoreDir, match[1]);
|
|
67
|
+
return path.join(gitDir, "info", "egregore-pi-runtime.json");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} catch {}
|
|
71
|
+
return path.join(egregoreDir, LOCAL_MANIFEST);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function pathExists(file) {
|
|
75
|
+
try {
|
|
76
|
+
fs.lstatSync(file);
|
|
77
|
+
return true;
|
|
78
|
+
} catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function copyFile(src, dest) {
|
|
84
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
85
|
+
fs.copyFileSync(src, dest);
|
|
86
|
+
try { fs.chmodSync(dest, fs.statSync(src).mode & 0o777); } catch {}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function installPiRuntime(egregoreDir) {
|
|
90
|
+
if (!fs.existsSync(BUNDLE_DIR)) throw new Error(`Pi runtime bundle missing: ${BUNDLE_DIR}`);
|
|
91
|
+
|
|
92
|
+
const previousPath = installManifestPath(egregoreDir);
|
|
93
|
+
const previous = readJson(previousPath, { files: {} });
|
|
94
|
+
const previousFiles = previous.files || {};
|
|
95
|
+
const next = {
|
|
96
|
+
package: PACKAGE.name,
|
|
97
|
+
version: PACKAGE.version,
|
|
98
|
+
installedAt: new Date().toISOString(),
|
|
99
|
+
files: {},
|
|
100
|
+
};
|
|
101
|
+
const summary = {
|
|
102
|
+
installed: 0,
|
|
103
|
+
updated: 0,
|
|
104
|
+
skipped: 0,
|
|
105
|
+
conflicted: 0,
|
|
106
|
+
conflicts: [],
|
|
107
|
+
files: [],
|
|
108
|
+
bundleSkills: bundleManifest().skills || [],
|
|
109
|
+
bundleSkillCount: bundleManifest().skillCount || 0,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
for (const rel of bundleFiles()) {
|
|
113
|
+
const src = path.join(BUNDLE_DIR, rel);
|
|
114
|
+
const dest = path.join(egregoreDir, rel);
|
|
115
|
+
const sourceHash = hashBuffer(fs.readFileSync(src));
|
|
116
|
+
const previousHash = previousFiles[rel]?.hash;
|
|
117
|
+
const record = () => {
|
|
118
|
+
next.files[rel] = { hash: sourceHash };
|
|
119
|
+
summary.files.push(rel);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
if (!pathExists(dest)) {
|
|
123
|
+
copyFile(src, dest);
|
|
124
|
+
summary.installed += 1;
|
|
125
|
+
record();
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let stat;
|
|
130
|
+
try { stat = fs.lstatSync(dest); } catch {}
|
|
131
|
+
if (!stat?.isFile()) {
|
|
132
|
+
summary.conflicted += 1;
|
|
133
|
+
summary.conflicts.push(rel);
|
|
134
|
+
if (previousHash) next.files[rel] = { hash: previousHash };
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const currentHash = hashBuffer(fs.readFileSync(dest));
|
|
139
|
+
if (currentHash === sourceHash) {
|
|
140
|
+
try { fs.chmodSync(dest, fs.statSync(src).mode & 0o777); } catch {}
|
|
141
|
+
summary.skipped += 1;
|
|
142
|
+
record();
|
|
143
|
+
} else if (previousHash && currentHash === previousHash) {
|
|
144
|
+
copyFile(src, dest);
|
|
145
|
+
summary.updated += 1;
|
|
146
|
+
record();
|
|
147
|
+
} else {
|
|
148
|
+
summary.conflicted += 1;
|
|
149
|
+
summary.conflicts.push(rel);
|
|
150
|
+
if (previousHash) next.files[rel] = { hash: previousHash };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
fs.mkdirSync(path.dirname(previousPath), { recursive: true });
|
|
155
|
+
fs.writeFileSync(previousPath, JSON.stringify(next, null, 2) + "\n");
|
|
156
|
+
return summary;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function hasPiRuntimeSupport(egregoreDir) {
|
|
160
|
+
return REQUIRED_RUNTIME_PATHS.every((rel) => fs.existsSync(path.join(egregoreDir, rel)));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function reportPiRuntimeSummary(summary, ui, opts = {}) {
|
|
164
|
+
if (!summary || !ui) return;
|
|
165
|
+
const label = opts.label || "Pi meta-harness";
|
|
166
|
+
const changed = summary.installed + summary.updated;
|
|
167
|
+
if (changed > 0) {
|
|
168
|
+
ui.success(`${label} ready (${summary.installed} installed, ${summary.updated} updated, ${summary.skipped} unchanged)`);
|
|
169
|
+
}
|
|
170
|
+
if (opts.includeConflicts !== false && summary.conflicted > 0) {
|
|
171
|
+
const count = summary.conflicted;
|
|
172
|
+
ui.info(ui.dim
|
|
173
|
+
? ui.dim(`${label}: kept ${count} framework file${count === 1 ? "" : "s"} this Egregore already manages.`)
|
|
174
|
+
: `${label}: kept ${count} framework file${count === 1 ? "" : "s"} this Egregore already manages.`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
module.exports = {
|
|
179
|
+
BUNDLE_DIR,
|
|
180
|
+
bundleFiles,
|
|
181
|
+
bundleManifest,
|
|
182
|
+
hasPiRuntimeSupport,
|
|
183
|
+
installManifestPath,
|
|
184
|
+
installPiRuntime,
|
|
185
|
+
reportPiRuntimeSummary,
|
|
186
|
+
};
|
package/lib/setup.js
CHANGED
|
@@ -12,6 +12,11 @@ const {
|
|
|
12
12
|
installCodexRuntime,
|
|
13
13
|
reportCodexRuntimeSummary,
|
|
14
14
|
} = require("./codex-runtime");
|
|
15
|
+
const {
|
|
16
|
+
hasPiRuntimeSupport,
|
|
17
|
+
installPiRuntime,
|
|
18
|
+
reportPiRuntimeSummary,
|
|
19
|
+
} = require("./pi-runtime");
|
|
15
20
|
|
|
16
21
|
const https = require("node:https");
|
|
17
22
|
|
|
@@ -438,7 +443,7 @@ async function install(data, ui, targetDir, opts = {}) {
|
|
|
438
443
|
} catch {}
|
|
439
444
|
}
|
|
440
445
|
|
|
441
|
-
// 4d. Overlay
|
|
446
|
+
// 4d. Overlay the selected shell-runtime support. Claude Code reads
|
|
442
447
|
// CLAUDE.md, not AGENTS.md; overlaying the Codex AGENTS.md/.codex into a Claude
|
|
443
448
|
// workspace gives a wandering agent a competing startup protocol (the
|
|
444
449
|
// xenocracy onboarding regression). Claude joiners keep the cloned repo as-is —
|
|
@@ -447,6 +452,9 @@ async function install(data, ui, targetDir, opts = {}) {
|
|
|
447
452
|
if (preferredRuntime === "codex") {
|
|
448
453
|
const codexRuntime = installCodexRuntime(egregoreDir);
|
|
449
454
|
reportCodexRuntimeSummary(codexRuntime, ui);
|
|
455
|
+
} else if (preferredRuntime === "pi") {
|
|
456
|
+
const piRuntime = installPiRuntime(egregoreDir);
|
|
457
|
+
reportPiRuntimeSummary(piRuntime, ui);
|
|
450
458
|
}
|
|
451
459
|
|
|
452
460
|
// 5. Register instance + install launcher binary
|
|
@@ -675,23 +683,40 @@ function normalizeRuntime(runtime) {
|
|
|
675
683
|
const raw = String(runtime || "claude-code").trim().toLowerCase();
|
|
676
684
|
if (raw === "claude" || raw === "claude-code" || raw === "claude_code") return "claude-code";
|
|
677
685
|
if (raw === "codex" || raw === "openai-codex" || raw === "openai_codex") return "codex";
|
|
686
|
+
if (raw === "pi" || raw === "pi-coding-agent" || raw === "pi_coding_agent") return "pi";
|
|
678
687
|
throw new Error(`Unsupported Egregore runtime: ${runtime}`);
|
|
679
688
|
}
|
|
680
689
|
|
|
681
690
|
function runtimeDisplay(runtime) {
|
|
682
|
-
|
|
691
|
+
const normalized = normalizeRuntime(runtime);
|
|
692
|
+
if (normalized === "codex") return "Codex";
|
|
693
|
+
if (normalized === "pi") return "Pi";
|
|
694
|
+
return "Claude Code";
|
|
683
695
|
}
|
|
684
696
|
|
|
685
697
|
function runtimeBinary(runtime) {
|
|
686
|
-
|
|
698
|
+
const normalized = normalizeRuntime(runtime);
|
|
699
|
+
if (normalized === "codex") return "codex";
|
|
700
|
+
if (normalized === "pi") return "pi";
|
|
701
|
+
return "claude";
|
|
687
702
|
}
|
|
688
703
|
|
|
689
704
|
// One-line install command for the chosen assistant — shown when the
|
|
690
705
|
// install finishes on a machine that doesn't have the assistant yet.
|
|
691
706
|
function assistantInstallCommand(runtime) {
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
707
|
+
const normalized = normalizeRuntime(runtime);
|
|
708
|
+
if (normalized === "codex") return "npm install -g @openai/codex";
|
|
709
|
+
if (normalized === "pi") return "npm install -g --ignore-scripts @earendil-works/pi-coding-agent";
|
|
710
|
+
return "npm install -g @anthropic-ai/claude-code";
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function piTrustArgs() {
|
|
714
|
+
try {
|
|
715
|
+
const help = spawnSync("pi", ["--help"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
716
|
+
return `${help.stdout || ""}\n${help.stderr || ""}`.includes("--approve") ? ["--approve"] : [];
|
|
717
|
+
} catch {
|
|
718
|
+
return [];
|
|
719
|
+
}
|
|
695
720
|
}
|
|
696
721
|
|
|
697
722
|
function runtimeLaunchArgs(runtime, egregoreDir) {
|
|
@@ -703,6 +728,7 @@ function runtimeLaunchArgs(runtime, egregoreDir) {
|
|
|
703
728
|
"--cd", egregoreDir,
|
|
704
729
|
];
|
|
705
730
|
}
|
|
731
|
+
if (normalizeRuntime(runtime) === "pi") return piTrustArgs();
|
|
706
732
|
return ["start"];
|
|
707
733
|
}
|
|
708
734
|
|
|
@@ -790,6 +816,16 @@ function hasCodexCoreSupport(egregoreDir) {
|
|
|
790
816
|
return hasCodexRuntimeSupport(egregoreDir);
|
|
791
817
|
}
|
|
792
818
|
|
|
819
|
+
function piSupportMessage(egregoreDir) {
|
|
820
|
+
return [
|
|
821
|
+
"Pi meta-harness support is missing from this Egregore checkout.",
|
|
822
|
+
` path: ${egregoreDir}`,
|
|
823
|
+
"",
|
|
824
|
+
"Run npx -y create-egregore@latest to install the packaged Pi runtime, then rerun egregore.",
|
|
825
|
+
"Pi loads Egregore through project-local .pi resources and the shared portable skill corpus.",
|
|
826
|
+
].join("\n");
|
|
827
|
+
}
|
|
828
|
+
|
|
793
829
|
function installCodexSkills(egregoreDir) {
|
|
794
830
|
const script = path.join(egregoreDir, "bin", "codex-install-skills.sh");
|
|
795
831
|
if (!fs.existsSync(script)) return false;
|
|
@@ -887,12 +923,11 @@ async function launchOrInstruct(egregoreDir, alias, ui, ctx = {}) {
|
|
|
887
923
|
}
|
|
888
924
|
|
|
889
925
|
if (!commandExists(binary)) {
|
|
890
|
-
const
|
|
891
|
-
const hasCodex = commandExists("codex");
|
|
926
|
+
const available = ["claude-code", "codex", "pi"].filter((candidate) => commandExists(runtimeBinary(candidate)));
|
|
892
927
|
// The user already chose `runtime` at the picker — lead with installing
|
|
893
928
|
// THAT one ("install Codex first"), then offer the other as an alternative.
|
|
894
|
-
const other =
|
|
895
|
-
if (
|
|
929
|
+
const other = available[0] || ["claude-code", "codex", "pi"].find((candidate) => candidate !== runtime);
|
|
930
|
+
if (available.length === 0) {
|
|
896
931
|
ui.warn(`Almost there — install ${display} to start sessions.`);
|
|
897
932
|
ui.info(` Install ${display} first:`);
|
|
898
933
|
ui.info(` ${ui.bold(assistantInstallCommand(runtime))}`);
|
|
@@ -910,7 +945,8 @@ async function launchOrInstruct(egregoreDir, alias, ui, ctx = {}) {
|
|
|
910
945
|
return;
|
|
911
946
|
}
|
|
912
947
|
|
|
913
|
-
|
|
948
|
+
const quitCommand = runtime === "pi" ? "/quit" : "/exit";
|
|
949
|
+
ui.info(`Starting Egregore in ${ui.bold(display)} now — press ${ui.bold("Ctrl+D")} (or ${quitCommand}) to return to your shell.`);
|
|
914
950
|
ui.info(`Next time, ${launcherNextStep(ui, aliasName)}`);
|
|
915
951
|
console.log("");
|
|
916
952
|
|
|
@@ -931,6 +967,15 @@ async function launchOrInstruct(egregoreDir, alias, ui, ctx = {}) {
|
|
|
931
967
|
console.log("");
|
|
932
968
|
return;
|
|
933
969
|
}
|
|
970
|
+
} else if (runtime === "pi") {
|
|
971
|
+
const piRuntime = installPiRuntime(egregoreDir);
|
|
972
|
+
reportPiRuntimeSummary(piRuntime, ui);
|
|
973
|
+
if (!hasPiRuntimeSupport(egregoreDir)) {
|
|
974
|
+
ui.warn(piSupportMessage(egregoreDir));
|
|
975
|
+
ui.info(`Run ${ui.bold(aliasName)} after updating the checkout.`);
|
|
976
|
+
console.log("");
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
934
979
|
}
|
|
935
980
|
|
|
936
981
|
const result = spawnSync(binary, runtimeLaunchArgs(runtime, egregoreDir), {
|
package/lib/ui.js
CHANGED
|
@@ -1358,7 +1358,7 @@ function _renderWelcomeBody({ w, h, version }) {
|
|
|
1358
1358
|
lines.push(`${DIM}└${"─".repeat(panelInner)}┘${RESET}`);
|
|
1359
1359
|
|
|
1360
1360
|
lines.push("");
|
|
1361
|
-
lines.push(`${DIM}
|
|
1361
|
+
lines.push(`${DIM}shared memory across Claude Code, Codex, and Pi${RESET}`);
|
|
1362
1362
|
lines.push("");
|
|
1363
1363
|
lines.push(`${DIM}press ${RESET}${BOLD}↵${RESET}${DIM} to begin · ctrl-c to exit${RESET}`);
|
|
1364
1364
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-egregore",
|
|
3
|
-
"version": "0.19.
|
|
4
|
-
"description": "Set up Egregore for your team in one command — installs the egregore launcher and your choice of Claude Code or
|
|
3
|
+
"version": "0.19.7",
|
|
4
|
+
"description": "Set up Egregore for your team in one command — installs the egregore launcher and your choice of Claude Code, Codex, or Pi.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
7
7
|
"create-egregore": "./bin/cli.js"
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
"node": ">=18"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build:runtime": "node scripts/build-runtime-bundle.mjs",
|
|
14
|
-
"
|
|
13
|
+
"build:runtime": "node scripts/build-runtime-bundle.mjs && node scripts/build-pi-runtime-bundle.mjs",
|
|
14
|
+
"build:pi-runtime": "node scripts/build-pi-runtime-bundle.mjs",
|
|
15
|
+
"test": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/context.test.js test/parse-join-target.test.js test/skip-repos.test.js test/onboarding-shortcircuit.test.js test/welcome-screen.test.js test/runtime-selection.test.js test/command-generation.test.js test/auth-gh.test.js test/gauntlet-fixes.test.js test/codex-runtime.test.js test/pi-runtime.test.js test/pi-product-workflows.test.js test/installer-runtime-source.test.js test/scroll-repro.test.js test/launcher-refocus-redraw.test.js test/multiselect-remote-search.test.js test/back-navigation.test.js test/manifest-form.test.js test/launcher-delete.test.js",
|
|
15
16
|
"test:e2e": "node --test test/e2e-local.test.js",
|
|
16
|
-
"test:all": "node scripts/build-runtime-bundle.mjs --check && node --test test/"
|
|
17
|
+
"test:all": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/"
|
|
17
18
|
},
|
|
18
19
|
"files": [
|
|
19
20
|
"bin/",
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
"egregore",
|
|
26
27
|
"claude",
|
|
27
28
|
"codex",
|
|
29
|
+
"pi",
|
|
28
30
|
"ai",
|
|
29
31
|
"collaboration"
|
|
30
32
|
],
|
package/runtime/codex/AGENTS.md
CHANGED
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
> Egregore skill already covers. This file exists only for runtimes that cannot
|
|
10
10
|
> read `CLAUDE.md`.
|
|
11
11
|
>
|
|
12
|
+
> **If you are Pi** (the `pi` coding-agent harness): **stop here.** Your
|
|
13
|
+
> authoritative Egregore instructions are loaded from
|
|
14
|
+
> `.pi/APPEND_SYSTEM.md`, and your workflows are exposed through the
|
|
15
|
+
> project-local `.pi/` runtime. Do not follow the Codex-specific block below.
|
|
16
|
+
>
|
|
12
17
|
> **If you are Codex or another shell-only agent:** this file is yours — continue.
|
|
13
18
|
|
|
14
19
|
Egregore is no longer only a Claude Code workspace. Claude Code remains the
|
|
@@ -80,7 +85,7 @@ This block is the Codex-native Egregore behavioral spec, rendered from CLAUDE.md
|
|
|
80
85
|
|
|
81
86
|
## Identity & Upstream
|
|
82
87
|
|
|
83
|
-
This is an Egregore instance — a downstream fork of the upstream framework at `egregore-labs/egregore`. The framework (`bin/`, `.claude/skills/`, `.claude/hooks/`, `.claude/context/`, `.claude/agents/`, `loom/`, `CLAUDE.md`, `skills/`) is synced from upstream on every session start and via `$update`. It is not authored in this repo.
|
|
88
|
+
This is an Egregore instance — a downstream fork of the upstream framework at `egregore-labs/egregore`. The framework (`bin/`, `.claude/skills/`, `.claude/hooks/`, `.claude/context/`, `.claude/agents/`, `.pi/`, `loom/`, `CLAUDE.md`, `skills/`) is synced from upstream on every session start and via `$update`. It is not authored in this repo.
|
|
84
89
|
|
|
85
90
|
**Where changes belong:**
|
|
86
91
|
- **Framework is outdated or a skill is missing:** run `$update` first. It pulls the latest from upstream.
|
|
@@ -93,7 +98,7 @@ When a user reports broken or missing framework behavior, the first question is
|
|
|
93
98
|
|
|
94
99
|
## On Launch — MANDATORY FIRST ACTION
|
|
95
100
|
|
|
96
|
-
The `egregore` launcher renders the Egregore startup card (identity,
|
|
101
|
+
The `egregore` launcher renders the Egregore startup card (identity, team momentum, and pending work) via `bin/codex-session-start.sh` before Codex starts, and installs project skills. Do not rerun startup checks and do not narrate startup. The card ends with **"What are you working on?"** — that question is already on screen; treat the user's first message as the answer to it. To re-show the card, run `bash bin/codex-session-start.sh --card`.
|
|
97
102
|
|
|
98
103
|
---
|
|
99
104
|
|
|
@@ -53,6 +53,11 @@ const AGENTS_PREAMBLE = `# Egregore Agent Protocol
|
|
|
53
53
|
> Egregore skill already covers. This file exists only for runtimes that cannot
|
|
54
54
|
> read \`CLAUDE.md\`.
|
|
55
55
|
>
|
|
56
|
+
> **If you are Pi** (the \`pi\` coding-agent harness): **stop here.** Your
|
|
57
|
+
> authoritative Egregore instructions are loaded from
|
|
58
|
+
> \`.pi/APPEND_SYSTEM.md\`, and your workflows are exposed through the
|
|
59
|
+
> project-local \`.pi/\` runtime. Do not follow the Codex-specific block below.
|
|
60
|
+
>
|
|
56
61
|
> **If you are Codex or another shell-only agent:** this file is yours — continue.
|
|
57
62
|
|
|
58
63
|
Egregore is no longer only a Claude Code workspace. Claude Code remains the
|
|
@@ -169,7 +174,7 @@ const INTRO_BODY = `You are a collaborator inside Egregore — a shared intellig
|
|
|
169
174
|
|
|
170
175
|
This block is the Codex-native Egregore behavioral spec, rendered from CLAUDE.md (the source of truth for egregore behavior) by \`bin/codex-render-spec.mjs\`. The per-section adaptation manifest is \`.codex/spec-manifest.json\`. The thin agent protocol above this block applies to every shell-capable agent; this block is the full behavioral contract for Codex sessions.`;
|
|
171
176
|
|
|
172
|
-
const ON_LAUNCH_BODY = `The \`egregore\` launcher renders the Egregore startup card (identity,
|
|
177
|
+
const ON_LAUNCH_BODY = `The \`egregore\` launcher renders the Egregore startup card (identity, team momentum, and pending work) via \`bin/codex-session-start.sh\` before Codex starts, and installs project skills. Do not rerun startup checks and do not narrate startup. The card ends with **"What are you working on?"** — that question is already on screen; treat the user's first message as the answer to it. To re-show the card, run \`bash bin/codex-session-start.sh --card\`.`;
|
|
173
178
|
|
|
174
179
|
const AFTER_GREETING_BODY = `**Mandatory behavioral rule.** When the user describes work, your **first action** — before reading files, exploring code, or anything else — is to get onto a working branch:
|
|
175
180
|
|