@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.
- package/bootstrap/lib/steps.sh +24 -13
- package/install.sh +21 -0
- package/omega/Agentik_Engine/omega_engine/__init__.py +1 -1
- package/omega/Agentik_Engine/omega_engine/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/cli.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/tmux.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/cli.py +159 -27
- package/omega/Agentik_Engine/omega_engine/tmux.py +63 -28
- package/omega/Agentik_Engine/pyproject.toml +1 -1
- package/omega/Agentik_SSOT/VERSION +1 -1
- package/omega/Agentik_SSOT/claude-plugins/claude-plugins.yaml +68 -35
- package/package.json +1 -1
package/bootstrap/lib/steps.sh
CHANGED
|
@@ -21,16 +21,18 @@ step_preflight() {
|
|
|
21
21
|
|
|
22
22
|
# --- 10 -----------------------------------------------------------------------
|
|
23
23
|
step_system_deps() {
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
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
|
-
#
|
|
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
|
|
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
|
|
755
|
-
if claude plugin install "$spec"
|
|
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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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` —
|
|
2719
|
+
"""`omega aisb` — straight to the AISB master Claude Code session.
|
|
2720
2720
|
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
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
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
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
|
|
2787
|
-
"""
|
|
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
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
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
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
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
|
|
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.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
role, and full OmegaOS context.
|
|
302
|
+
v0.19.20 — moved 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
|
-
|
|
276
|
-
the
|
|
277
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
|
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,
|
|
295
|
-
|
|
296
|
-
|
|
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"
|
|
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
|
-
|
|
355
|
+
run_cmd = "claude"
|
|
323
356
|
else:
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
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 +1 @@
|
|
|
1
|
-
0.19.
|
|
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 <
|
|
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
|
|
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: "
|
|
30
|
+
source: "anthropics/claude-plugins-official"
|
|
21
31
|
description: "Anthropic's official plugin marketplace"
|
|
22
|
-
builtin: true
|
|
23
|
-
- id: anthropic-skills
|
|
24
|
-
source: "
|
|
25
|
-
description: "Anthropic's official
|
|
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: "
|
|
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.
|
|
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"
|