@agentikos/omega-os 0.19.14 → 0.19.16

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.
@@ -550,13 +550,19 @@ except Exception: print("unknown")' 2>/dev/null)" || readiness="unknown"
550
550
  printf ' %s elapsed %s\n' "$bar" "$(printf '%02d:%02d' "$mm" "$ss")"
551
551
  printf ' %s\n' "$bar"
552
552
  printf ' %s %snext steps%s\n' "$bar" "$C_BOLD" "$C_RST"
553
- printf " %s 1. %stmux attach -t AISB-chat%s %salways-on Hermès conversation%s\n" \
553
+ printf " %s 1. ${C_BOLD}source ~/.zshrc${C_RST} ${C_DIM}or open a new shell${C_RST}\n" "$bar"
554
+ printf ' %s 2. %somega%s %stalk to AISB (master agent, Max OAuth)%s\n' \
555
+ "$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
556
+ printf ' %s 3. %somega hermes%s %stalk to Hermès (meta-companion, Anthropic API)%s\n' \
557
+ "$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
558
+ printf ' %s 4. %somega account login%s %swire your Claude Max OAuth%s\n' \
559
+ "$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
560
+ printf ' %s 5. %somega run "hello"%s %sfirst verified mission%s\n' \
561
+ "$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
562
+ printf ' %s 6. %somega menu%s %sinteractive whiptail picker%s\n' \
563
+ "$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
564
+ printf ' %s 7. %somega doctor%s %sfull health check%s\n' \
554
565
  "$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
555
- printf " %s 2. open a new shell ${C_DIM}(or \`source ~/.zshrc\`)${C_RST}\n" "$bar"
556
- printf ' %s 3. %somega status%s every task + derived state\n' "$bar" "$C_BOLD" "$C_RST"
557
- printf ' %s 4. %somega account list%s wire your Claude Max OAuth\n' "$bar" "$C_BOLD" "$C_RST"
558
- printf ' %s 5. %somega run "hello"%s first verified mission\n' "$bar" "$C_BOLD" "$C_RST"
559
- printf ' %s 6. %somega%s interactive menu (whiptail)\n' "$bar" "$C_BOLD" "$C_RST"
560
566
  printf ' %s\n' "$bar"
561
567
  printf ' %s %ssessions%s all Omega/Claude/LLM sessions run inside tmux\n' \
562
568
  "$bar" "$C_BOLD" "$C_RST"
@@ -448,10 +448,11 @@ PY
448
448
  step_mcp() {
449
449
  local catalog="$OMEGA_HOME/Agentik_SSOT/mcp/mcp-catalog.yaml"
450
450
  [ -f "$catalog" ] || { err "MCP catalog missing: $catalog"; return 1; }
451
- # grep -c exits 1 when count is 0, which made the old `|| echo '?'`
452
- # fire AND grep's "0" stayed printed "0\n? entries" splatter.
451
+ # The catalog YAML uses ``catalog:`` then `` - id: <name>`` (2-space
452
+ # indent). The old pattern ``^- id:`` matched at column 0 and counted
453
+ # zero. Allow leading whitespace.
453
454
  local _mcp_count
454
- _mcp_count="$(grep -c '^- id:' "$catalog" 2>/dev/null || true)"
455
+ _mcp_count="$(grep -cE '^[[:space:]]*- id:' "$catalog" 2>/dev/null || true)"
455
456
  _mcp_count="$(printf '%s' "$_mcp_count" | tr -d '\n ' )"
456
457
  info "MCP catalog present (${_mcp_count:-?} entries)"
457
458
 
@@ -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.14"
191
+ __version__ = "0.19.16"
192
192
 
193
193
  __all__ = [
194
194
  "__version__",
@@ -2741,8 +2741,70 @@ def cmd_aisb(args: argparse.Namespace) -> int:
2741
2741
  return 2
2742
2742
 
2743
2743
 
2744
+ def _attach_or_spawn_chat(session_name: str, *,
2745
+ spawn_fn,
2746
+ label: str) -> int:
2747
+ """Attach to ``session_name`` tmux session, spawning it first if absent.
2748
+
2749
+ - Outside tmux : `os.execvp("tmux", ["tmux", "attach", "-t", session])`
2750
+ - Inside tmux : prints the switch command (we can't switch from a
2751
+ subprocess; the user needs to do it in their shell).
2752
+ Returns the exit code of execvp or 0 when we printed instructions.
2753
+
2754
+ This is the v0.19.15 UX: bare `omega` puts you in the master chat,
2755
+ bare `omega hermes` puts you in the Hermès chat. No whiptail menu
2756
+ by default — that's `omega menu` now.
2757
+ """
2758
+ import os
2759
+ from omega_engine import tmux
2760
+ home = _omega_home()
2761
+ if not tmux.is_alive(session_name):
2762
+ try:
2763
+ spawn_fn(home)
2764
+ except Exception as exc: # noqa: BLE001
2765
+ print(f" could not spawn {label}: {exc}")
2766
+ print(f" try manually: tmux new -d -s {session_name}")
2767
+ return 2
2768
+ # Inside tmux already? Tell the user to switch (we can't from here).
2769
+ if os.environ.get("TMUX"):
2770
+ print(f" already inside tmux — switch with:")
2771
+ print(f" tmux switch-client -t {session_name}")
2772
+ print(f" or detach (Ctrl-b d) then `omega` again.")
2773
+ return 0
2774
+ # Outside tmux — replace this process with `tmux attach`.
2775
+ print(f" attaching to {label} ({session_name})…")
2776
+ print(f" detach: Ctrl-b d (session keeps running)")
2777
+ try:
2778
+ os.execvp("tmux", ["tmux", "attach", "-t", session_name])
2779
+ except FileNotFoundError:
2780
+ print(" tmux not on PATH — install with `brew install tmux` "
2781
+ "or `apt-get install tmux`")
2782
+ return 2
2783
+ return 0 # unreachable (execvp replaced the process)
2784
+
2785
+
2744
2786
  def cmd_menu(_args: argparse.Namespace) -> int:
2745
- """`omega` with no args interactive whiptail menu (the on-ramp)."""
2787
+ """`omega` (no args) open the AISB master chat session in tmux.
2788
+
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`.
2794
+ """
2795
+ 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
+ )
2801
+
2802
+
2803
+ def cmd_menu_whiptail(_args: argparse.Namespace) -> int:
2804
+ """`omega menu` — the explicit whiptail picker.
2805
+
2806
+ The old bare-omega behaviour, moved behind an explicit subcommand
2807
+ because the default is now the AISB chat (v0.19.15)."""
2746
2808
  from omega_engine.menu import run_menu
2747
2809
  return run_menu()
2748
2810
 
@@ -2825,6 +2887,53 @@ def cmd_hermes(args: argparse.Namespace) -> int:
2825
2887
  import json as _json
2826
2888
  sub = getattr(args, "hermes_cmd", None)
2827
2889
 
2890
+ # v0.19.15 — `omega hermes` with no subcommand opens the Hermès chat
2891
+ # tmux session. Same UX as bare `omega` → AISB chat, but for L2.
2892
+ if sub is None or sub == "chat":
2893
+ from omega_engine import tmux as _tx
2894
+ return _attach_or_spawn_chat(
2895
+ "Hermes-chat",
2896
+ spawn_fn=_tx.spawn_hermes_chat,
2897
+ label="Hermès meta-companion chat",
2898
+ )
2899
+ if sub == "chat-loop":
2900
+ # REPL that runs inside the Hermes-chat tmux session.
2901
+ # Uses Anthropic API directly (separate from AISB's Max OAuth).
2902
+ from omega_engine.aisb_chat import chat_once
2903
+ from omega_engine.vault import vault_read
2904
+ import os, sys
2905
+ home = _omega_home()
2906
+ api_key = (vault_read(home, "ANTHROPIC_API_KEY_HERMES") or "").strip()
2907
+ if not api_key:
2908
+ api_key = (os.environ.get("ANTHROPIC_API_KEY") or "").strip()
2909
+ if not api_key:
2910
+ print(" Hermès has no Anthropic API key — set one with:")
2911
+ print(" omega vault write ANTHROPIC_API_KEY_HERMES sk-ant-...")
2912
+ print(" (Hermès uses its OWN paid Anthropic budget, separate")
2913
+ print(" from OmegaOS's Claude Max OAuth — see LAYERS.md)")
2914
+ return 2
2915
+ os.environ["ANTHROPIC_API_KEY"] = api_key
2916
+ print(f" Hermès chat (Anthropic API) — /quit to exit")
2917
+ # We re-use chat_once but namespace history to a Hermès topic so
2918
+ # AISB's chat history doesn't bleed into Hermès's.
2919
+ HERMES_TOPIC = -999999
2920
+ while True:
2921
+ try:
2922
+ line = input("\nyou > ").strip()
2923
+ except (EOFError, KeyboardInterrupt):
2924
+ print("\n(exit)")
2925
+ return 0
2926
+ if not line:
2927
+ continue
2928
+ if line in ("/quit", "/exit"):
2929
+ return 0
2930
+ try:
2931
+ reply = chat_once(home, line, topic_id=HERMES_TOPIC)
2932
+ except Exception as exc: # noqa: BLE001
2933
+ print(f"hermes (error): {exc}")
2934
+ continue
2935
+ print(f"\nhermes > {reply}")
2936
+
2828
2937
  if sub == "status":
2829
2938
  st = H.status()
2830
2939
  if getattr(args, "json", False):
@@ -3774,10 +3883,14 @@ def cmd_cleanup(args: argparse.Namespace) -> int:
3774
3883
 
3775
3884
  def _build_parser() -> argparse.ArgumentParser:
3776
3885
  parser = argparse.ArgumentParser(prog="omega", description="Omega OS control CLI")
3777
- # When no subcommand is given, drop into the interactive menu instead of
3778
- # erroring. The cmd_menu function reads the whiptail menus and dispatches.
3886
+ # v0.19.15 bare `omega` now drops into the AISB master chat tmux
3887
+ # session (attach or spawn). `omega menu` keeps the legacy whiptail
3888
+ # picker for power users.
3779
3889
  parser.set_defaults(fn=cmd_menu)
3780
3890
  sub = parser.add_subparsers(dest="cmd")
3891
+ sub.add_parser("menu",
3892
+ help="open the interactive whiptail menu (the old `omega` behaviour)"
3893
+ ).set_defaults(fn=cmd_menu_whiptail)
3781
3894
  sub.add_parser("version", help="print the engine version").set_defaults(fn=cmd_version)
3782
3895
  p_doc = sub.add_parser("doctor", help="validate the deployment")
3783
3896
  p_doc.add_argument("--json", action="store_true",
@@ -4018,6 +4131,14 @@ def _build_parser() -> argparse.ArgumentParser:
4018
4131
  help="(observe) project slug")
4019
4132
  p_hebr.add_argument("task_id", nargs="?", default=None,
4020
4133
  help="(observe) task id whose .done.json to ingest")
4134
+ # v0.19.15 — `omega hermes chat` and `omega hermes chat-loop`: the
4135
+ # Hermès counterpart to `omega aisb chat`. `chat` spawns/attaches
4136
+ # the persistent Hermes-chat tmux session; `chat-loop` is the REPL
4137
+ # itself that runs inside that session (Anthropic API).
4138
+ he_sub.add_parser("chat",
4139
+ help="spawn (or attach to) the Hermes-chat tmux session")
4140
+ he_sub.add_parser("chat-loop",
4141
+ help="the Hermès REPL itself (called by the tmux session)")
4021
4142
 
4022
4143
  # `omega hermes-desktop` — Hermes Desktop remote backend
4023
4144
  p_hd = sub.add_parser(
@@ -194,13 +194,32 @@ class ClaudeCodeAdapter:
194
194
  cat = catalog_by_id.get(sid, {})
195
195
  install = cat.get("install") or {}
196
196
 
197
- # Prefer the locally installed binary; fall back to `npx <package>`.
198
- if tool and tool.invoke:
197
+ # Resolve the launch command. Three shapes:
198
+ # 1. uvx:<package> — Python MCP via Astral uvx (no
199
+ # local binary; Claude calls `uvx <package>` at runtime)
200
+ # 2. tool.invoke = relative path → resolved binary on disk
201
+ # 3. catalog install method → `npx -y <package>` or
202
+ # `uvx <package>` synthesized from the catalog alone
203
+ catalog_args = list(install.get("args") or [])
204
+ server_args = list(server.get("args") or [])
205
+ if tool and tool.invoke and tool.invoke.startswith("uvx:"):
206
+ # uvx-managed Python MCP server.
207
+ pkg = tool.invoke[len("uvx:"):]
208
+ entry["command"] = "uvx"
209
+ entry["args"] = [pkg, *catalog_args, *server_args]
210
+ elif tool and tool.invoke:
199
211
  entry["command"] = str(omega_home / tool.invoke)
200
- entry["args"] = list(server.get("args") or [])
212
+ entry["args"] = [*catalog_args, *server_args]
201
213
  elif install.get("method") == "npx" and install.get("package"):
202
214
  entry["command"] = "npx"
203
- entry["args"] = ["-y", str(install["package"]), *(server.get("args") or [])]
215
+ entry["args"] = ["-y", str(install["package"]),
216
+ *catalog_args, *server_args]
217
+ elif install.get("method") == "uvx" and install.get("package"):
218
+ # No local install (cold uvx call at runtime — slow first time
219
+ # but works without ever running `omega tool install`).
220
+ entry["command"] = "uvx"
221
+ entry["args"] = [str(install["package"]),
222
+ *catalog_args, *server_args]
204
223
  else:
205
224
  # nothing to invoke — skip rather than write a half-broken entry
206
225
  continue
@@ -232,11 +232,11 @@ def spawn_worker(project: str, task: str, *,
232
232
 
233
233
 
234
234
  def spawn_aisb_chat(omega_home: str | Path | None = None) -> str:
235
- """Spawn an AISB chat session — the Telegram-conversation fallback.
235
+ """Spawn the AISB master chat tmux session.
236
236
 
237
- Runs ``omega aisb chat-loop`` inside the session so the user can
238
- attach and have a conversation with the AISB master agent without
239
- needing Telegram connectivity.
237
+ Runs ``omega aisb chat-loop`` inside REPL conversation with the
238
+ AISB master agent on Claude Max OAuth. This is what bare `omega`
239
+ attaches to (v0.19.15+).
240
240
  """
241
241
  name = "AISB-chat"
242
242
  home = Path(omega_home or os.environ.get("OMEGA_HOME")
@@ -246,6 +246,21 @@ def spawn_aisb_chat(omega_home: str | Path | None = None) -> str:
246
246
  return name
247
247
 
248
248
 
249
+ def spawn_hermes_chat(omega_home: str | Path | None = None) -> str:
250
+ """Spawn the Hermès meta-companion chat tmux session.
251
+
252
+ Runs ``omega hermes chat-loop`` — REPL conversation with Hermès on
253
+ Anthropic API (separate budget from AISB's Max OAuth). This is what
254
+ `omega hermes` attaches to (v0.19.15+).
255
+ """
256
+ name = "Hermes-chat"
257
+ home = Path(omega_home or os.environ.get("OMEGA_HOME")
258
+ or Path.home() / "Omega")
259
+ omega_bin = home / "Agentik_Tools" / "bin" / "omega"
260
+ spawn(name, command=f"{omega_bin} hermes chat-loop")
261
+ return name
262
+
263
+
249
264
  # ---------------------------------------------------------------------------
250
265
  # Categorised view + health
251
266
  # ---------------------------------------------------------------------------
@@ -215,6 +215,45 @@ def install_from_catalog(
215
215
  except (OSError, json.JSONDecodeError):
216
216
  version = ""
217
217
 
218
+ elif method == "uvx" and package:
219
+ # Python MCP servers (mcp-server-git, mcp-server-fetch, etc.) run
220
+ # via `uvx <package>` — Astral fetches + caches the package on
221
+ # first call. We don't install it locally; we just verify `uv`
222
+ # is on PATH and pre-warm the cache so the first `claude` call
223
+ # doesn't pay the cold-fetch latency.
224
+ uv = shutil.which("uv") or str(Path.home() / ".local" / "bin" / "uv")
225
+ if not Path(uv).exists():
226
+ raise RuntimeError(
227
+ "uv not found on PATH — install with "
228
+ "`curl -LsSf https://astral.sh/uv/install.sh | sh` to use uvx MCP servers"
229
+ )
230
+ # Pre-warm: `uv tool install` makes the package globally available
231
+ # as a uv tool (resolves once, ~5s) so subsequent `uvx <package>`
232
+ # invocations are instant. Failure here is non-fatal — `uvx` will
233
+ # still resolve at call time, just slower.
234
+ try:
235
+ res = subprocess.run(
236
+ [uv, "tool", "install", "--quiet", package],
237
+ check=False, capture_output=True, text=True, timeout=300,
238
+ )
239
+ # Best-effort version detect via `uv tool list`.
240
+ ls = subprocess.run(
241
+ [uv, "tool", "list"], capture_output=True, text=True, timeout=15,
242
+ )
243
+ for line in (ls.stdout or "").splitlines():
244
+ line = line.strip()
245
+ if line.startswith(package + " "):
246
+ # Format: "<package> v<version>"
247
+ parts = line.split()
248
+ if len(parts) >= 2:
249
+ version = parts[1].lstrip("v")
250
+ break
251
+ except subprocess.SubprocessError:
252
+ pass
253
+ # invoke is `uvx <package>` — sync.py renders it directly to the
254
+ # Claude .mcp.json (no local binary needed).
255
+ invoke = f"uvx:{package}"
256
+
218
257
  tool = Tool(
219
258
  name=mcp_id,
220
259
  version=version,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "omega-engine"
3
- version = "0.19.14"
3
+ version = "0.19.16"
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"
@@ -140,7 +140,12 @@ class TestPostInstallCard(unittest.TestCase):
140
140
  self.assertIn("install complete", out)
141
141
  self.assertIn("status", out)
142
142
  self.assertIn("next steps", out)
143
- self.assertIn("omega status", out)
143
+ # v0.19.15 — bare `omega` is the AISB master chat, `omega hermes`
144
+ # is the L2 companion. Old card pointed at `omega status` as the
145
+ # entry; new card points at `omega` itself.
146
+ self.assertIn("omega", out)
147
+ self.assertIn("AISB", out)
148
+ self.assertIn("Hermès", out)
144
149
  self.assertIn("omega run", out)
145
150
  # No literal $C_DIM / $C_RST tokens
146
151
  self.assertNotIn("${C_DIM}", out)
@@ -475,20 +475,25 @@ class TestBrandColourIsOrange(unittest.TestCase):
475
475
  f"banner should use C_ORANGE on each of 8 rows (got {n})")
476
476
 
477
477
 
478
- class TestPostInstallCardMentionsAISBChat(unittest.TestCase):
479
- """The 'AISB-chat' tmux session is the conversational entry point when
480
- Telegram isn't wired. The post-install card MUST tell the operator how
481
- to attach to it; otherwise they finish the install with no UI."""
482
-
483
- def test_card_shows_attach_command(self):
478
+ class TestPostInstallCardSurfacesEntryPoints(unittest.TestCase):
479
+ """v0.19.15 bare `omega` is now the AISB chat attach (no longer needs
480
+ the explicit `tmux attach -t AISB-chat` in the card). The card must
481
+ still surface BOTH master entry points: `omega` for AISB and
482
+ `omega hermes` for the L2 companion. Plus the "every session in tmux"
483
+ discipline."""
484
+
485
+ def test_card_surfaces_aisb_and_hermes_entries(self):
484
486
  if not COMMON_SH.is_file():
485
487
  self.skipTest("common.sh not in repo")
486
488
  text = COMMON_SH.read_text()
487
- self.assertIn("tmux attach -t AISB-chat", text,
488
- "post_install_card must include the AISB-chat attach line — "
489
- "otherwise the operator has no way to discover their always-on "
490
- "Hermès session")
491
- # Also surface the "every session in tmux" expectation.
489
+ # Bare omega = AISB master.
490
+ self.assertIn("AISB", text,
491
+ "post_install_card must mention AISB as the master agent entry")
492
+ # `omega hermes` = L2.
493
+ self.assertIn("omega hermes", text,
494
+ "post_install_card must mention `omega hermes` as the L2 "
495
+ "companion entry — without it the user can't discover it")
496
+ # The "every session in tmux" expectation.
492
497
  self.assertIn("tmux", text)
493
498
 
494
499
 
@@ -1 +1 @@
1
- 0.19.14
1
+ 0.19.16
@@ -18,7 +18,10 @@ catalog:
18
18
  name: Git
19
19
  description: Read/inspect git repositories
20
20
  category: core
21
- install: { method: npx, package: "@modelcontextprotocol/server-git" }
21
+ # Official MCP git server is Python — runs via uvx (Astral). The old
22
+ # npm package `@modelcontextprotocol/server-git` returns 404 — it was
23
+ # never published; only the Python `mcp-server-git` on PyPI exists.
24
+ install: { method: uvx, package: "mcp-server-git" }
22
25
  recommended: true
23
26
 
24
27
  - id: github
@@ -41,8 +44,10 @@ catalog:
41
44
  name: Higgsfield
42
45
  description: Image and video generation
43
46
  category: media
44
- install: { method: npx, package: "@higgsfield/mcp" }
45
- secrets: [HIGGSFIELD_API_KEY]
47
+ # Correct npm package name is `higgsfield-mcp` (no @ scope). The
48
+ # scoped `@higgsfield/mcp` returns 404 — was never published.
49
+ install: { method: npx, package: "higgsfield-mcp" }
50
+ secrets: [HF_API_KEY, HF_SECRET]
46
51
  recommended: false
47
52
 
48
53
  - id: playwright
@@ -63,7 +68,10 @@ catalog:
63
68
  name: Fetch
64
69
  description: Fetch and convert web content
65
70
  category: core
66
- install: { method: npx, package: "@modelcontextprotocol/server-fetch" }
71
+ # Official MCP fetch server is Python — runs via uvx. The npm
72
+ # package `@modelcontextprotocol/server-fetch` returns 404 — was
73
+ # never published. PyPI ships `mcp-server-fetch`.
74
+ install: { method: uvx, package: "mcp-server-fetch" }
67
75
  recommended: true
68
76
 
69
77
  - id: memory
@@ -98,10 +106,12 @@ catalog:
98
106
 
99
107
  - id: linear
100
108
  name: Linear
101
- description: Issues and project management
109
+ description: Issues and project management (Linear-hosted remote MCP)
102
110
  category: project
103
- install: { method: npx, package: "@linear/mcp" }
104
- secrets: [LINEAR_API_KEY]
111
+ # Linear ships an OFFICIAL remote MCP at https://mcp.linear.app/mcp,
112
+ # accessed via the `mcp-remote` npm proxy. No API key in env —
113
+ # OAuth happens in-browser the first time Claude connects.
114
+ install: { method: npx, package: "mcp-remote", args: ["https://mcp.linear.app/mcp"] }
105
115
  recommended: false
106
116
 
107
117
  - id: sentry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentikos/omega-os",
3
- "version": "0.19.14",
3
+ "version": "0.19.16",
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"