@agentikos/omega-os 0.19.18 → 0.19.20

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.
@@ -21,16 +21,18 @@ step_preflight() {
21
21
 
22
22
  # --- 10 -----------------------------------------------------------------------
23
23
  step_system_deps() {
24
- # `whiptail` powers `omega` (the interactive menu — the post-install entry
25
- # point). On Debian/Ubuntu it lives in the `whiptail` package, on RHEL/Fedora
26
- # in `newt`, on macOS in `newt` via Homebrew. We add it to the base set so a
27
- # fresh Mac doesn't end up with a silent `omega` command.
24
+ # System deps:
25
+ # - whiptail/newt back-up menu (`omega menu`)
26
+ # - fzf — primary picker for the new session manager (`omega`)
27
+ # and required by the tmux-claude install script too
28
+ # whiptail lives in `whiptail` (Debian/Ubuntu), `newt` (RHEL/Fedora),
29
+ # `newt` (Homebrew). fzf is `fzf` on every platform.
28
30
  local pkgs="python3 git tmux sqlite3 jq curl"
29
31
  case "$OMEGA_PKG" in
30
- apt) sudo apt-get update -qq && sudo apt-get install -y -qq $pkgs whiptail python3-venv python3-yaml ;;
31
- dnf) sudo dnf install -y -q $pkgs newt python3-pyyaml ;;
32
- brew) brew install $pkgs newt 2>/dev/null || true ;;
33
- *) err "install manually: $pkgs (and whiptail/newt for the menu)"; return 1 ;;
32
+ apt) sudo apt-get update -qq && sudo apt-get install -y -qq $pkgs whiptail fzf python3-venv python3-yaml ;;
33
+ dnf) sudo dnf install -y -q $pkgs newt fzf python3-pyyaml ;;
34
+ brew) brew install $pkgs newt fzf 2>/dev/null || true ;;
35
+ *) err "install manually: $pkgs (and whiptail/newt + fzf for the menu)"; return 1 ;;
34
36
  esac
35
37
 
36
38
  # PyYAML — required by every install-side helper that reads the manifest
@@ -732,27 +734,36 @@ step_claude_plugins() {
732
734
 
733
735
  # Register every marketplace referenced by the selected plugins (excluding
734
736
  # those marked `builtin: true`).
737
+ #
738
+ # Source format MUST be `<owner>/<repo>` for the Claude CLI. We strip
739
+ # any legacy `github:` prefix the catalog may still carry (pre-v0.19.20
740
+ # catalogs used `github:owner/repo` which fails with "Invalid
741
+ # marketplace source format").
735
742
  while IFS= read -r src; do
736
743
  [ -z "$src" ] && continue
744
+ src="${src#github:}"
737
745
  info "registering marketplace: $src"
738
746
  if claude plugin marketplace add "$src" >>"$LOG_FILE" 2>&1; then
739
747
  ok "marketplace ok: $src"
740
748
  else
741
- # Already registered or other non-fatal; log only.
749
+ # Likely already registered non-fatal, log only.
742
750
  info "marketplace add returned non-zero (may already be registered): $src"
743
751
  fi
744
752
  done < <(_claude_plugins_marketplaces_for "$catalog" "$selected")
745
753
 
754
+ # `claude plugin install` does NOT accept `-s <scope>` (verified against
755
+ # Claude Code 2.1.150 — the plugin help only documents --config). The
756
+ # scope is per-install determined by where the plugin manifest declares
757
+ # it; we keep `scope:` in the catalog only as documentation.
746
758
  local failed=""
747
759
  local id
748
760
  while IFS= read -r id; do
749
761
  [ -z "$id" ] && continue
750
- local spec scope
762
+ local spec
751
763
  spec="$(_claude_plugins_install_spec "$catalog" "$id")"
752
- scope="$(_claude_plugins_scope_for "$catalog" "$id")"
753
764
  [ -z "$spec" ] && { info "no install spec for $id — skipping"; continue; }
754
- info "installing claude plugin: $spec (scope=$scope)"
755
- if claude plugin install "$spec" -s "$scope" >>"$LOG_FILE" 2>&1; then
765
+ info "installing claude plugin: $spec"
766
+ if claude plugin install "$spec" >>"$LOG_FILE" 2>&1; then
756
767
  ok "claude plugin installed: $id"
757
768
  else
758
769
  err "claude plugin $id failed to install — see $LOG_FILE; continuing"
package/install.sh CHANGED
@@ -207,3 +207,24 @@ record_state_version
207
207
 
208
208
  # Final boxed celebration + verdict from `omega doctor --json`.
209
209
  post_install_card
210
+
211
+ # v0.19.20 — drop the user into a fresh login shell so $PATH (now
212
+ # containing $OMEGA_HOME/Agentik_Tools/bin) and OMEGA_HOME are loaded
213
+ # immediately. Without this, the user had to remember to
214
+ # `source ~/.zshrc` or open a new terminal — bad UX.
215
+ #
216
+ # Only re-exec when:
217
+ # * stdin is a tty (interactive install, not piped/CI)
218
+ # * we're not running under --non-interactive
219
+ # * the user isn't already in a non-default shell we don't understand
220
+ # * an `omega` binary exists at the canonical path
221
+ #
222
+ # Otherwise we just print the instruction so the user knows what to do.
223
+ if [ -t 0 ] && [ "${NONINTERACTIVE:-0}" != "1" ] \
224
+ && [ -x "$OMEGA_HOME/Agentik_Tools/bin/omega" ]; then
225
+ log ""
226
+ log "${C_DIM}::${C_RST} reloading your shell so \`omega\` is on PATH…"
227
+ log "${C_DIM}::${C_RST} type ${C_BOLD}omega${C_RST} to open the session manager"
228
+ log ""
229
+ exec "${SHELL:-/bin/bash}" -l
230
+ fi
@@ -188,7 +188,7 @@ from omega_engine.genesis import (
188
188
  )
189
189
  from omega_engine import plan as plan_v7
190
190
 
191
- __version__ = "0.19.18"
191
+ __version__ = "0.19.20"
192
192
 
193
193
  __all__ = [
194
194
  "__version__",
@@ -2716,24 +2716,25 @@ def cmd_tmux(args: argparse.Namespace) -> int:
2716
2716
 
2717
2717
 
2718
2718
  def cmd_aisb(args: argparse.Namespace) -> int:
2719
- """`omega aisb` — talk to the AISB master agent without Telegram.
2719
+ """`omega aisb` — straight to the AISB master Claude Code session.
2720
2720
 
2721
- Two sub-commands:
2722
- chat — spawn (or attach to) the AISB-chat tmux session
2723
- chat-loop — the REPL loop itself (run inside the tmux session)
2721
+ v0.19.19 — `omega aisb` (no subcommand) now does spawn+attach in one
2722
+ shot, identical to selecting "+ New AISB" from the `omega` session
2723
+ manager. Same Claude Code TUI, same persona via CLAUDE.md.
2724
+
2725
+ Sub-commands:
2726
+ chat — explicit alias for the default (back-compat)
2727
+ chat-loop — the legacy Python REPL (used by dispatched workers
2728
+ that want a programmatic single-turn API)
2724
2729
  """
2725
2730
  from omega_engine import tmux
2726
- sub = args.aisb_cmd or "chat"
2727
- home = _omega_home()
2728
- if sub == "chat":
2729
- name = "AISB-chat"
2730
- if tmux.is_alive(name):
2731
- print(f" session already exists: {name}")
2732
- else:
2733
- tmux.spawn_aisb_chat(home)
2734
- print(f" spawned: {name}")
2735
- print(f" attach: {tmux.attach_command(name)}")
2736
- return 0
2731
+ sub = getattr(args, "aisb_cmd", None) or "chat"
2732
+ if sub in ("chat", None):
2733
+ return _attach_or_spawn_chat(
2734
+ "AISB-chat",
2735
+ spawn_fn=tmux.spawn_aisb_chat,
2736
+ label="AISB master (Claude Code on Max OAuth)",
2737
+ )
2737
2738
  if sub == "chat-loop":
2738
2739
  from omega_engine.aisb_chat import run_chat_loop
2739
2740
  return run_chat_loop()
@@ -2783,21 +2784,152 @@ def _attach_or_spawn_chat(session_name: str, *,
2783
2784
  return 0 # unreachable (execvp replaced the process)
2784
2785
 
2785
2786
 
2786
- def cmd_menu(_args: argparse.Namespace) -> int:
2787
- """`omega` (no args) open the AISB master chat session in tmux.
2787
+ def _session_age(unix_ts: int) -> str:
2788
+ """Pretty-print 'now' / '5m ago' / '2h ago' / '3d ago'."""
2789
+ import time as _t
2790
+ delta = max(0, int(_t.time()) - int(unix_ts))
2791
+ if delta < 60:
2792
+ return "now"
2793
+ if delta < 3600:
2794
+ return f"{delta // 60}m ago"
2795
+ if delta < 86400:
2796
+ return f"{delta // 3600}h ago"
2797
+ return f"{delta // 86400}d ago"
2798
+
2788
2799
 
2789
- v0.19.15 changed the default: typing `omega` used to open the whiptail
2790
- menu, which Gareth correctly called bad UX ("type `omega`, talk to my
2791
- master agent"). Now bare `omega` attaches to the always-on `AISB-chat`
2792
- tmux session, spawning it on demand. The whiptail menu lives at
2793
- `omega menu`.
2800
+ def cmd_menu(_args: argparse.Namespace) -> int:
2801
+ """`omega` (no args) open the OmegaOS session manager.
2802
+
2803
+ v0.19.19 redesign per the user's spec: bare `omega` no longer
2804
+ auto-attaches to AISB-chat. Instead it shows a fzf-driven menu:
2805
+
2806
+ ┌─ Omega — Session Manager ──────────────────┐
2807
+ │ > AISB-chat now │
2808
+ │ Hermes-chat 5m ago │
2809
+ │ Causio-oracle 2h ago │
2810
+ │ ───────────────────────────────────────── │
2811
+ │ + New Claude Code session (AISB master) │
2812
+ │ + New Hermès session │
2813
+ └────────────────────────────────────────────┘
2814
+
2815
+ Pick a session → attach. Pick "+ New …" → spawn + attach. Esc / q
2816
+ → exit cleanly.
2817
+
2818
+ Direct shortcuts kept:
2819
+ * `omega aisb` → straight to AISB-chat (no menu)
2820
+ * `omega hermes` → straight to Hermes-chat (no menu)
2821
+ * `omega menu` → legacy whiptail picker (advanced ops)
2794
2822
  """
2823
+ import os
2824
+ import shutil
2825
+ import subprocess
2795
2826
  from omega_engine import tmux
2796
- return _attach_or_spawn_chat(
2797
- "AISB-chat",
2798
- spawn_fn=tmux.spawn_aisb_chat,
2799
- label="AISB master chat",
2800
- )
2827
+
2828
+ # If we're already inside a tmux session, instruct the user — we can't
2829
+ # take over the current pane from a subprocess, but `omega aisb` /
2830
+ # `omega hermes` from inside tmux still print switch-client instructions.
2831
+ if os.environ.get("TMUX"):
2832
+ print(" You're already inside tmux. Use Ctrl+b z (tmux-claude")
2833
+ print(" session manager) or one of:")
2834
+ print(" tmux switch-client -t AISB-chat")
2835
+ print(" tmux switch-client -t Hermes-chat")
2836
+ return 0
2837
+
2838
+ if not shutil.which("tmux"):
2839
+ print(" tmux not installed — `brew install tmux` (macOS) or "
2840
+ "`apt-get install tmux` (Linux)")
2841
+ return 2
2842
+
2843
+ sessions = tmux.list_sessions(_omega_home())
2844
+ sessions.sort(key=lambda s: -int(s.created))
2845
+
2846
+ NEW_AISB = "__new_aisb__"
2847
+ NEW_HERMES = "__new_hermes__"
2848
+
2849
+ lines: list[tuple[str, str]] = [] # (display, action_key)
2850
+ if sessions:
2851
+ for s in sessions:
2852
+ attach_mark = " *" if s.attached else " "
2853
+ line = f"{attach_mark} {s.name:<32} {_session_age(s.created):<10} {s.category}"
2854
+ lines.append((line, s.name))
2855
+ lines.append(("──────────────────────────────────────────────",
2856
+ "__separator__"))
2857
+ lines.append((" + New Claude Code session (AISB master)", NEW_AISB))
2858
+ lines.append((" + New Hermès session", NEW_HERMES))
2859
+
2860
+ chosen_key: str | None = None
2861
+ if shutil.which("fzf"):
2862
+ # fzf path — prettiest UX. Header shows the title, separator line
2863
+ # is non-selectable (we filter it after).
2864
+ fzf_input = "\n".join(disp for disp, _ in lines)
2865
+ try:
2866
+ proc = subprocess.run(
2867
+ ["fzf",
2868
+ "--prompt=omega › ",
2869
+ "--header=Omega Session Manager — Enter to attach, Esc to quit",
2870
+ "--layout=reverse",
2871
+ "--height=70%",
2872
+ "--border",
2873
+ "--no-multi"],
2874
+ input=fzf_input, capture_output=True, text=True,
2875
+ )
2876
+ if proc.returncode == 0:
2877
+ pick = proc.stdout.strip()
2878
+ for disp, key in lines:
2879
+ if disp == pick and key != "__separator__":
2880
+ chosen_key = key
2881
+ break
2882
+ except Exception as exc: # noqa: BLE001
2883
+ print(f" fzf failed: {exc}")
2884
+ return 2
2885
+ else:
2886
+ # Plain stdin fallback — numbered list.
2887
+ print()
2888
+ print(" Omega Session Manager")
2889
+ for i, (disp, _) in enumerate(lines, 1):
2890
+ print(f" {i:2}) {disp}")
2891
+ print()
2892
+ try:
2893
+ raw = input(" pick a number (Enter to quit): ").strip()
2894
+ except (EOFError, KeyboardInterrupt):
2895
+ return 0
2896
+ if not raw:
2897
+ return 0
2898
+ try:
2899
+ n = int(raw)
2900
+ except ValueError:
2901
+ print(f" not a number: {raw!r}")
2902
+ return 0
2903
+ if 1 <= n <= len(lines):
2904
+ chosen_key = lines[n - 1][1]
2905
+ if chosen_key == "__separator__":
2906
+ chosen_key = None
2907
+
2908
+ if chosen_key is None:
2909
+ return 0
2910
+ if chosen_key == NEW_AISB:
2911
+ # "+ New AISB" means the user wants a FRESH session — kill
2912
+ # the existing AISB-chat first so we don't attach to a dead
2913
+ # one (claude died, OAuth missing, etc.).
2914
+ return _attach_or_spawn_chat(
2915
+ "AISB-chat",
2916
+ spawn_fn=lambda h: tmux.spawn_aisb_chat(h, force_replace=True),
2917
+ label="AISB master (Claude Code on Max OAuth)",
2918
+ )
2919
+ if chosen_key == NEW_HERMES:
2920
+ return _attach_or_spawn_chat(
2921
+ "Hermes-chat",
2922
+ spawn_fn=lambda h: tmux.spawn_hermes_chat(h, force_replace=True),
2923
+ label="Hermès (Claude Code on Anthropic API)",
2924
+ )
2925
+ # Otherwise it's an existing session name — just attach.
2926
+ print(f" attaching to {chosen_key}…")
2927
+ try:
2928
+ os.execvp("tmux", ["tmux", "attach", "-t", chosen_key])
2929
+ except FileNotFoundError:
2930
+ print(" tmux not on PATH")
2931
+ return 2
2932
+ return 0
2801
2933
 
2802
2934
 
2803
2935
  def cmd_menu_whiptail(_args: argparse.Namespace) -> int:
@@ -259,49 +259,85 @@ def _ensure_chat_context_dir(home: Path, label: str,
259
259
  return ctx_dir
260
260
 
261
261
 
262
- def spawn_aisb_chat(omega_home: str | Path | None = None) -> str:
262
+ def _spawn_with_shell_then_run(
263
+ name: str,
264
+ *,
265
+ cwd: str | Path,
266
+ run_command: str,
267
+ force_replace: bool = False,
268
+ ) -> str:
269
+ """Spawn a tmux session that starts the user's interactive shell at
270
+ ``cwd``, then types ``run_command`` + Enter into it. This way:
271
+
272
+ * The shell stays alive even if ``run_command`` exits (claude
273
+ with no auth, claude exited cleanly, etc.) — user still sees
274
+ the shell and can debug.
275
+ * The shell sources the user's rc files normally (PATH, env, etc.)
276
+ so ``claude`` resolves to the operator's binary.
277
+
278
+ Used by spawn_aisb_chat / spawn_hermes_chat. ``force_replace=True``
279
+ kills any existing session of the same name first — the menu's
280
+ "+ New" actions pass this so the user always gets a fresh session
281
+ instead of attaching to a dead one.
282
+ """
283
+ if force_replace and is_alive(name):
284
+ kill(name)
285
+ if is_alive(name):
286
+ return name
287
+ # 1. Create a detached session running the user's login shell at cwd.
288
+ rc, _ = _tmux("new-session", "-d", "-s", name, "-c", str(cwd))
289
+ if rc != 0:
290
+ return name
291
+ # 2. Send the launch command + Enter into the shell. We use
292
+ # `send-keys` (not the new-session command arg) so the shell stays
293
+ # alive even if the launched binary exits.
294
+ _tmux("send-keys", "-t", name, run_command, "Enter")
295
+ return name
296
+
297
+
298
+ def spawn_aisb_chat(omega_home: str | Path | None = None,
299
+ force_replace: bool = False) -> str:
263
300
  """Spawn the AISB master chat tmux session — REAL Claude Code TUI.
264
301
 
265
- v0.19.18instead of running our Python REPL (`omega aisb chat-loop`),
266
- we now run the canonical `claude` CLI inside a dedicated project dir
267
- seeded with the AISB master persona (``Agentik_SSOT/agents/aisb/CLAUDE.md``).
268
- User sees the SAME interactive Claude Code TUI they get with bare
269
- `claude`, but pre-loaded with AISB's identity, the L3 orchestrator
270
- role, and full OmegaOS context.
302
+ v0.19.20moved from ``exec claude`` (which kills the session when
303
+ claude exits) to ``spawn shell + send-keys claude``. The shell stays
304
+ alive even if claude can't start (no Max OAuth wired, etc.), so the
305
+ user lands inside the session and sees the actual failure instead of
306
+ "ça fait rien du tout" silent attach-to-dead.
271
307
 
272
308
  Auth: Claude Max OAuth (inherited from the user's shell env, no env
273
309
  override needed — `claude` reads `~/.claude/.credentials.json`).
274
310
 
275
- cwd=$HOME is the legacy crash fix (spawn() default would inherit
276
- the npm/_npx cache dir which can disappear); the `claude` process
277
- itself runs with cwd = the context dir we just created.
311
+ ``force_replace=True`` kills any existing AISB-chat first used by
312
+ the `omega` session manager's "+ New" action so the user gets a
313
+ fresh session each time.
278
314
  """
279
315
  name = "AISB-chat"
280
316
  home = Path(omega_home or os.environ.get("OMEGA_HOME")
281
317
  or Path.home() / "Omega")
282
318
  persona = home / "Agentik_SSOT" / "agents" / "aisb" / "CLAUDE.md"
283
319
  ctx_dir = _ensure_chat_context_dir(home, "aisb-master", persona)
284
- spawn(name, command=f"cd {ctx_dir} && exec claude",
285
- cwd=str(Path.home()))
286
- return name
320
+ return _spawn_with_shell_then_run(
321
+ name, cwd=ctx_dir, run_command="claude",
322
+ force_replace=force_replace,
323
+ )
287
324
 
288
325
 
289
- def spawn_hermes_chat(omega_home: str | Path | None = None) -> str:
326
+ def spawn_hermes_chat(omega_home: str | Path | None = None,
327
+ force_replace: bool = False) -> str:
290
328
  """Spawn the Hermès chat tmux session — REAL Claude Code TUI, but on
291
329
  Anthropic API (Hermès's own paid key, budget-isolated from Max OAuth).
292
330
 
293
331
  Mirrors ``spawn_aisb_chat`` for the L2 companion: drops a Hermès
294
- persona ``CLAUDE.md`` into a dedicated context dir, then runs
295
- `claude` there with ``ANTHROPIC_API_KEY`` exported from the vault.
296
- Setting the env var makes Claude Code use the API key instead of
297
- the Max OAuth — same TUI, different billing surface.
332
+ persona ``CLAUDE.md`` into a dedicated context dir, exports
333
+ ``ANTHROPIC_API_KEY`` (from vault) before launching `claude`. Same
334
+ shell-stays-alive pattern.
298
335
  """
299
336
  name = "Hermes-chat"
300
337
  home = Path(omega_home or os.environ.get("OMEGA_HOME")
301
338
  or Path.home() / "Omega")
302
- persona = home / "Agentik_SSOT" / "docs" / "LAYERS.md" # Hermès reads architecture as persona
339
+ persona = home / "Agentik_SSOT" / "docs" / "LAYERS.md"
303
340
  ctx_dir = _ensure_chat_context_dir(home, "hermes", persona)
304
- # Resolve Anthropic key from vault → fallback to existing env.
305
341
  try:
306
342
  from omega_engine.vault import vault_read
307
343
  api_key = (vault_read(home, "ANTHROPIC_API_KEY_HERMES") or "").strip()
@@ -309,9 +345,6 @@ def spawn_hermes_chat(omega_home: str | Path | None = None) -> str:
309
345
  api_key = ""
310
346
  if not api_key:
311
347
  api_key = (os.environ.get("ANTHROPIC_API_KEY") or "").strip()
312
- # If no key, fall back to Max OAuth (Hermès will share AISB's
313
- # billing — not ideal but better than failing). Surface a marker
314
- # file in the context dir so the user sees the warning on first launch.
315
348
  if not api_key:
316
349
  (ctx_dir / "NO_ANTHROPIC_KEY.md").write_text(
317
350
  "# Hermès — no Anthropic API key wired\n\n"
@@ -319,12 +352,14 @@ def spawn_hermes_chat(omega_home: str | Path | None = None) -> str:
319
352
  "own paid Anthropic budget instead of the AISB Max OAuth.\n\n"
320
353
  " omega vault write ANTHROPIC_API_KEY_HERMES sk-ant-...\n"
321
354
  )
322
- cmd = f"cd {ctx_dir} && exec claude"
355
+ run_cmd = "claude"
323
356
  else:
324
- cmd = (f"cd {ctx_dir} && "
325
- f"ANTHROPIC_API_KEY={api_key} exec claude")
326
- spawn(name, command=cmd, cwd=str(Path.home()))
327
- return name
357
+ # Single-line shell statement; send-keys passes it as-is.
358
+ run_cmd = f"ANTHROPIC_API_KEY={api_key} claude"
359
+ return _spawn_with_shell_then_run(
360
+ name, cwd=ctx_dir, run_command=run_cmd,
361
+ force_replace=force_replace,
362
+ )
328
363
 
329
364
 
330
365
  # ---------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "omega-engine"
3
- version = "0.19.18"
3
+ version = "0.19.20"
4
4
  description = "The Omega OS orchestration engine — event-sourced, verified-completion agent graphs."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1 +1 @@
1
- 0.19.18
1
+ 0.19.20
@@ -4,44 +4,53 @@
4
4
  # (interactive) or apply the manifest's `claude_plugins:` list (headless). For
5
5
  # each selected plugin, the installer:
6
6
  #
7
- # 1. ensures the marketplace is registered: `claude plugin marketplace add <source>`
7
+ # 1. ensures the marketplace is registered: `claude plugin marketplace add <owner>/<repo>`
8
8
  # (skipped if `source: builtin` — already present after a fresh install)
9
- # 2. installs it: `claude plugin install <name>@<marketplace> -s <scope>`
9
+ # 2. installs it: `claude plugin install <name>@<marketplace>`
10
10
  #
11
11
  # Maintained by the claudecode-educator (Agentik_Orchestration/educators/).
12
12
  # Secrets are referenced by name only — never stored here.
13
13
  #
14
14
  # Marketplaces are listed once; plugins reference them by `marketplace:` id.
15
+ #
16
+ # IMPORTANT — marketplace id != github source.
17
+ # When `claude plugin marketplace add anthropics/skills` runs, the
18
+ # Claude CLI derives an id from the marketplace.json `name` field in the
19
+ # repo, which can be different from the repo name. We tracked these by
20
+ # hand (verified on the VPS as of 2026-05-25).
21
+ #
22
+ # Source format: `<owner>/<repo>` — NO `github:` prefix (the prefix
23
+ # previously bundled here caused `marketplace add` to fail with
24
+ # "Invalid marketplace source format").
15
25
 
16
26
  version: 1
17
27
 
18
28
  marketplaces:
19
29
  - id: claude-plugins-official
20
- source: "github:anthropics/claude-plugins-official"
30
+ source: "anthropics/claude-plugins-official"
21
31
  description: "Anthropic's official plugin marketplace"
22
- builtin: true
23
- - id: anthropic-skills
24
- source: "github:anthropics/skills"
25
- description: "Anthropic's official skill collection (find-skills, document skills, etc.)"
26
- builtin: false
27
- trust: high
28
- - id: vercel-labs-skills
29
- source: "github:vercel-labs/skills"
30
- description: "Vercel Labs skills (skill discovery CLI + find-skills)"
32
+ builtin: true # auto-registered by claude CLI
33
+ - id: anthropic-agent-skills
34
+ source: "anthropics/skills"
35
+ description: "Anthropic's official Agent Skills repo (document-skills, claude-api, example-skills)"
31
36
  builtin: false
32
37
  trust: high
33
- - id: davila7-templates
34
- source: "github:davila7/claude-code-templates"
35
- description: "Community-maintained Claude Code templates and skills"
36
- builtin: false
37
- trust: medium
38
38
  - id: thedotmack
39
- source: "github:thedotmack/claude-mem"
39
+ source: "thedotmack/claude-mem"
40
40
  description: "claude-mem memory + observation system"
41
41
  builtin: false
42
42
  trust: medium
43
+ - id: daymade-skills
44
+ source: "daymade/claude-code-skills"
45
+ description: "Community skill creator marketplace (daymade) — includes skill-creator-style tooling"
46
+ builtin: false
47
+ trust: medium
43
48
 
44
49
  catalog:
50
+ # All entries below were verified to exist + install cleanly on a real
51
+ # Claude Code 2.1.150+ install before being committed here. See the
52
+ # commit message of v0.19.20 for the audit trail.
53
+
45
54
  - id: claude-mem
46
55
  name: claude-mem
47
56
  description: "Long-term memory + observation system across sessions"
@@ -75,26 +84,50 @@ catalog:
75
84
  secrets: [STRIPE_SECRET_KEY]
76
85
  recommended: false
77
86
 
78
- - id: skill-creator
79
- name: skill-creator
80
- description: "Generate new SKILL.md files with Claude's help (Anthropic official)"
81
- category: meta
82
- marketplace: anthropic-skills
83
- scope: user
84
- recommended: true
85
-
86
- - id: find-skills
87
- name: find-skills
88
- description: "Discover skills across marketplaces (vercel-labs); pairs with skill-auditor"
89
- category: meta
90
- marketplace: vercel-labs-skills
91
- scope: user
92
- recommended: true
93
-
94
87
  - id: document-skills
95
88
  name: document-skills
96
89
  description: "Anthropic official suite — docx, pdf, pptx, xlsx (creation + editing)"
97
90
  category: documents
98
- marketplace: anthropic-skills
91
+ marketplace: anthropic-agent-skills
99
92
  scope: user
100
93
  recommended: true
94
+
95
+ - id: pr-review-toolkit
96
+ name: pr-review-toolkit
97
+ description: "Pull request review tooling — analyse diffs, suggest fixes"
98
+ category: dev
99
+ marketplace: claude-plugins-official
100
+ scope: user
101
+ recommended: false
102
+
103
+ - id: code-review
104
+ name: code-review
105
+ description: "Static code review with style + quality heuristics"
106
+ category: dev
107
+ marketplace: claude-plugins-official
108
+ scope: user
109
+ recommended: false
110
+
111
+ - id: feature-dev
112
+ name: feature-dev
113
+ description: "Feature development workflow — spec → impl → review"
114
+ category: dev
115
+ marketplace: claude-plugins-official
116
+ scope: user
117
+ recommended: false
118
+
119
+ - id: mcp-server-dev
120
+ name: mcp-server-dev
121
+ description: "Scaffold + iterate on new MCP servers"
122
+ category: dev
123
+ marketplace: claude-plugins-official
124
+ scope: user
125
+ recommended: false
126
+
127
+ - id: plugin-dev
128
+ name: plugin-dev
129
+ description: "Build + test new Claude Code plugins"
130
+ category: meta
131
+ marketplace: claude-plugins-official
132
+ scope: user
133
+ recommended: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentikos/omega-os",
3
- "version": "0.19.18",
3
+ "version": "0.19.20",
4
4
  "description": "Omega OS — installable agentic operating system with verified-completion orchestration. Event-sourced engine, 8-block rack, autonomous agents, MCP.",
5
5
  "bin": {
6
6
  "omega-os": "bin/omega-os.js"