create-egregore 0.19.16 → 0.19.18

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // egregore-launcher-version: 0.19.16
2
+ // egregore-launcher-version: 0.19.18
3
3
  //
4
4
  // egregore — launch and browse Egregore instances from your terminal.
5
5
  // Installed by create-egregore. Reads ~/.egregore/instances.json.
@@ -33,7 +33,7 @@ const crypto = require("node:crypto");
33
33
  const { spawnSync, spawn } = require("node:child_process");
34
34
  const readline = require("node:readline");
35
35
 
36
- const VERSION = "0.19.16";
36
+ const VERSION = "0.19.18";
37
37
  const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
38
38
  const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
39
39
  const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
@@ -41,8 +41,9 @@ const PUBLIC_NPX_PACKAGE = "create-egregore";
41
41
  const UPDATE_REGISTRY_URL =
42
42
  process.env.EGREGORE_UPDATE_REGISTRY_URL ||
43
43
  `https://registry.npmjs.org/${PUBLIC_NPX_PACKAGE}/latest`;
44
- const UPDATE_CACHE_TTL_MS = 6 * 60 * 60 * 1000;
45
- const UPDATE_FAILURE_TTL_MS = 30 * 60 * 1000;
44
+ const UPDATE_AVAILABLE_CACHE_TTL_MS = 6 * 60 * 60 * 1000;
45
+ const UPDATE_CURRENT_CACHE_TTL_MS = 5 * 60 * 1000;
46
+ const UPDATE_FAILURE_CACHE_TTL_MS = 5 * 60 * 1000;
46
47
  const UPDATE_CHECK_TIMEOUT_MS = 1500;
47
48
  const CONNECT_API_URL = (
48
49
  process.env.EGREGORE_CONNECT_API_URL ||
@@ -1048,10 +1049,16 @@ function readUpdateCache() {
1048
1049
  const cache = JSON.parse(fs.readFileSync(UPDATE_CACHE_FILE, "utf-8"));
1049
1050
  if (!cache || !cache.checked_at) return null;
1050
1051
  const age = Date.now() - new Date(cache.checked_at).getTime();
1051
- const ttl = cache.latest ? UPDATE_CACHE_TTL_MS : UPDATE_FAILURE_TTL_MS;
1052
+ const cachedUpdate = cache.latest ? cliUpdateState(cache.latest) : null;
1053
+ if (cache.latest && !cachedUpdate) return null;
1054
+ const ttl = !cache.latest
1055
+ ? UPDATE_FAILURE_CACHE_TTL_MS
1056
+ : cachedUpdate.available
1057
+ ? UPDATE_AVAILABLE_CACHE_TTL_MS
1058
+ : UPDATE_CURRENT_CACHE_TTL_MS;
1052
1059
  if (!Number.isFinite(age) || age < 0 || age > ttl) return null;
1053
1060
  if (!cache.latest) return { current: VERSION, latest: null, available: false };
1054
- return cliUpdateState(cache.latest);
1061
+ return cachedUpdate;
1055
1062
  } catch {
1056
1063
  return null;
1057
1064
  }
@@ -1204,6 +1211,19 @@ function writeJsonFileAtomic(file, value) {
1204
1211
  atomicWrite(file, JSON.stringify(value, null, 2) + "\n", 0o644);
1205
1212
  }
1206
1213
 
1214
+ function normalizeClaudeRegistryDenyRule(instancePath) {
1215
+ const stale = "Write(~/.egregore/instances.json)";
1216
+ const supported = "Edit(~/.egregore/instances.json)";
1217
+ for (const relative of [".claude/settings.json", ".claude/settings.local.json"]) {
1218
+ const file = path.join(instancePath, relative);
1219
+ const settings = readJsonFile(file);
1220
+ const deny = settings?.permissions?.deny;
1221
+ if (!Array.isArray(deny) || !deny.includes(stale)) continue;
1222
+ settings.permissions.deny = [...new Set(deny.map((rule) => rule === stale ? supported : rule))];
1223
+ writeJsonFileAtomic(file, settings);
1224
+ }
1225
+ }
1226
+
1207
1227
  function writeEnvValueAtomic(file, key, value) {
1208
1228
  const lines = fs.existsSync(file)
1209
1229
  ? fs.readFileSync(file, "utf-8").split(/\r?\n/)
@@ -1432,6 +1452,7 @@ async function cmdConnect(args) {
1432
1452
  api_url: claim.data.api_url,
1433
1453
  });
1434
1454
  writeEnvValueAtomic(envFile, "EGREGORE_API_KEY", claim.data.api_key);
1455
+ normalizeClaudeRegistryDenyRule(inst.path);
1435
1456
  persistConnectState(inst, {
1436
1457
  status: "backfilling",
1437
1458
  activation_protocol: claim.data.activation_protocol,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-egregore",
3
- "version": "0.19.16",
3
+ "version": "0.19.18",
4
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": {
@@ -2,6 +2,8 @@
2
2
  hooks = true
3
3
 
4
4
  [tui]
5
+ # Codex currently accepts built-in footer item IDs only. Egregore's dynamic
6
+ # ◆ CONNECTED / ◇ LOCAL identity is rendered by bin/codex-session-start.sh.
5
7
  status_line = [
6
8
  "model-with-reasoning",
7
9
  "git-branch",
@@ -57,6 +57,7 @@ fi
57
57
 
58
58
  LOCAL_MODE="false"
59
59
  [ "$(_detect_mode)" = "local" ] && LOCAL_MODE="true"
60
+ MODE_BADGE="$(_runtime_mode_badge)"
60
61
 
61
62
  if [ "$LOCAL_MODE" != "true" ]; then
62
63
  if [ -f "$ENV_FILE" ] && grep -q '^EGREGORE_API_KEY=.' "$ENV_FILE" 2>/dev/null; then
@@ -133,7 +134,7 @@ EOF
133
134
  render_card() {
134
135
  local separator identity_left identity_right line_width pad footer_left footer_right board_url has_failure failed_services
135
136
  separator=" ..................................................................."
136
- identity_left=" ${GITHUB_ORG:-$ORG_NAME}/${REPO_NAME}"
137
+ identity_left=" ${GITHUB_ORG:-$ORG_NAME}/${REPO_NAME} · ${MODE_BADGE}"
137
138
  identity_right="${DISPLAY_NAME} · ${BRANCH:-?}"
138
139
  line_width=67
139
140
  pad=$((line_width - ${#identity_left} - ${#identity_right}))
@@ -59,13 +59,22 @@ _get_base_branch() {
59
59
  # Detect local vs connected mode
60
60
  _detect_mode() {
61
61
  local config="${CONFIG:-$SCRIPT_DIR/egregore.json}"
62
- local mode
63
- mode=$(jq -r '.mode // empty' "$config" 2>/dev/null || true)
64
- local api_url
65
- api_url=$(jq -r '.api_url // empty' "$config" 2>/dev/null || true)
66
- if [ "$mode" = "local" ] || [ -z "$api_url" ]; then
62
+ if [ -f "$config" ] && jq -e \
63
+ '(.mode // "") != "local" and ((.api_url // "") | length > 0)' \
64
+ "$config" >/dev/null 2>&1; then
65
+ echo "connected"
66
+ else
67
67
  echo "local"
68
+ fi
69
+ }
70
+
71
+ # Compact runtime identity shared by terminal surfaces. The sigils deliberately
72
+ # distinguish an active hosted connection from the self-contained local mode
73
+ # without implying that local Egregore is unhealthy.
74
+ _runtime_mode_badge() {
75
+ if [ "$(_detect_mode)" = "connected" ]; then
76
+ echo "◆ CONNECTED"
68
77
  else
69
- echo "connected"
78
+ echo "◇ LOCAL"
70
79
  fi
71
80
  }
@@ -2,6 +2,8 @@
2
2
  hooks = true
3
3
 
4
4
  [tui]
5
+ # Codex currently accepts built-in footer item IDs only. Egregore's dynamic
6
+ # ◆ CONNECTED / ◇ LOCAL identity is rendered by bin/codex-session-start.sh.
5
7
  status_line = [
6
8
  "model-with-reasoning",
7
9
  "git-branch",
@@ -57,6 +57,7 @@ fi
57
57
 
58
58
  LOCAL_MODE="false"
59
59
  [ "$(_detect_mode)" = "local" ] && LOCAL_MODE="true"
60
+ MODE_BADGE="$(_runtime_mode_badge)"
60
61
 
61
62
  if [ "$LOCAL_MODE" != "true" ]; then
62
63
  if [ -f "$ENV_FILE" ] && grep -q '^EGREGORE_API_KEY=.' "$ENV_FILE" 2>/dev/null; then
@@ -133,7 +134,7 @@ EOF
133
134
  render_card() {
134
135
  local separator identity_left identity_right line_width pad footer_left footer_right board_url has_failure failed_services
135
136
  separator=" ..................................................................."
136
- identity_left=" ${GITHUB_ORG:-$ORG_NAME}/${REPO_NAME}"
137
+ identity_left=" ${GITHUB_ORG:-$ORG_NAME}/${REPO_NAME} · ${MODE_BADGE}"
137
138
  identity_right="${DISPLAY_NAME} · ${BRANCH:-?}"
138
139
  line_width=67
139
140
  pad=$((line_width - ${#identity_left} - ${#identity_right}))
@@ -59,13 +59,22 @@ _get_base_branch() {
59
59
  # Detect local vs connected mode
60
60
  _detect_mode() {
61
61
  local config="${CONFIG:-$SCRIPT_DIR/egregore.json}"
62
- local mode
63
- mode=$(jq -r '.mode // empty' "$config" 2>/dev/null || true)
64
- local api_url
65
- api_url=$(jq -r '.api_url // empty' "$config" 2>/dev/null || true)
66
- if [ "$mode" = "local" ] || [ -z "$api_url" ]; then
62
+ if [ -f "$config" ] && jq -e \
63
+ '(.mode // "") != "local" and ((.api_url // "") | length > 0)' \
64
+ "$config" >/dev/null 2>&1; then
65
+ echo "connected"
66
+ else
67
67
  echo "local"
68
+ fi
69
+ }
70
+
71
+ # Compact runtime identity shared by terminal surfaces. The sigils deliberately
72
+ # distinguish an active hosted connection from the self-contained local mode
73
+ # without implying that local Egregore is unhealthy.
74
+ _runtime_mode_badge() {
75
+ if [ "$(_detect_mode)" = "connected" ]; then
76
+ echo "◆ CONNECTED"
68
77
  else
69
- echo "connected"
78
+ echo "◇ LOCAL"
70
79
  fi
71
80
  }