@trac3er/oh-my-god 2.0.2 → 2.0.3
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +6 -0
- package/README.md +5 -7
- package/commands/OMG:setup.md +1 -2
- package/hooks/prompt-enhancer.py +1 -1
- package/hooks/setup_wizard.py +1 -12
- package/package.json +1 -1
- package/plugins/README.md +1 -1
- package/plugins/core/plugin.json +1 -1
- package/runtime/adoption.py +1 -1
- package/runtime/mcp_config_writers.py +0 -11
- package/runtime/team_router.py +0 -2
- package/scripts/omg.py +1 -1
- package/settings.json +2 -2
- package/runtime/providers/opencode_provider.py +0 -144
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "OMG - Oh-My-God for Claude Code",
|
|
9
|
-
"version": "2.0.
|
|
9
|
+
"version": "2.0.3",
|
|
10
10
|
"homepage": "https://github.com/trac3er00/OMG",
|
|
11
11
|
"repository": "https://github.com/trac3er00/OMG"
|
|
12
12
|
},
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{
|
|
15
15
|
"name": "omg",
|
|
16
16
|
"description": "OMG plugin layer for Claude Code with native setup, orchestration, and interop.",
|
|
17
|
-
"version": "2.0.
|
|
17
|
+
"version": "2.0.3",
|
|
18
18
|
"source": "./",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "trac3er00"
|
|
@@ -32,5 +32,5 @@
|
|
|
32
32
|
]
|
|
33
33
|
}
|
|
34
34
|
],
|
|
35
|
-
"version": "2.0.
|
|
35
|
+
"version": "2.0.3"
|
|
36
36
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.3 - 2026-03-06
|
|
4
|
+
|
|
5
|
+
- removed OpenCode runtime, setup wiring, docs, and tests from the supported OMG host surface
|
|
6
|
+
- merged the remaining security and trust-review hardening work into `main` and cleaned up the finished `codex/*` branches
|
|
7
|
+
- published the post-merge patch release after the `v2.0.2` release target became immutable
|
|
8
|
+
|
|
3
9
|
## 2.0.2 - 2026-03-06
|
|
4
10
|
|
|
5
11
|
- cleaned the repo for public launch by removing internal planning docs and stale private references
|
package/README.md
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
# OMG 2.0.
|
|
1
|
+
# OMG 2.0.3
|
|
2
2
|
|
|
3
3
|
[](https://github.com/trac3er00/OMG/actions/workflows/omg-compat-gate.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/@trac3er/oh-my-god)
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
|
|
7
|
-
OMG upgrades your agent host instead of replacing it. It gives Claude Code, Codex,
|
|
7
|
+
OMG upgrades your agent host instead of replacing it. It gives Claude Code, Codex, and other supported CLIs a tighter setup flow, stronger orchestration, native adoption from older plugin stacks, and proof-backed verification.
|
|
8
8
|
|
|
9
9
|
- Brand: `OMG`
|
|
10
10
|
- Repo: `https://github.com/trac3er00/OMG`
|
|
11
11
|
- npm: `@trac3er/oh-my-god`
|
|
12
12
|
- Plugin id: `omg`
|
|
13
13
|
- Marketplace id: `omg`
|
|
14
|
-
- Version: `2.0.
|
|
14
|
+
- Version: `2.0.3`
|
|
15
15
|
|
|
16
16
|
## Why OMG
|
|
17
17
|
|
|
18
18
|
- Small front door: install, run `/OMG:setup`, then `/OMG:crazy <goal>`.
|
|
19
|
-
- Multi-host support: Claude Code, Codex,
|
|
19
|
+
- Multi-host support: Claude Code, Codex, Gemini CLI, and Kimi CLI.
|
|
20
20
|
- Native adoption: setup detects OMC, OMX, and Superpowers-style environments without exposing copycat public migration commands.
|
|
21
21
|
- Proof-first delivery: verification, provider coverage, HUD artifacts, and transcripts are published instead of implied.
|
|
22
22
|
|
|
@@ -57,8 +57,6 @@ Success looks like:
|
|
|
57
57
|
|
|
58
58
|
- Claude Code: [docs/install/claude-code.md](docs/install/claude-code.md)
|
|
59
59
|
- Codex: [docs/install/codex.md](docs/install/codex.md)
|
|
60
|
-
- OpenCode: [docs/install/opencode.md](docs/install/opencode.md)
|
|
61
|
-
|
|
62
60
|
## Native Adoption
|
|
63
61
|
|
|
64
62
|
OMG uses native setup language instead of public migration commands.
|
|
@@ -71,7 +69,7 @@ Compatibility references to OMC, OMX, and Superpowers are documented here: [docs
|
|
|
71
69
|
|
|
72
70
|
## Proof
|
|
73
71
|
|
|
74
|
-
Current local verification for this release: `
|
|
72
|
+
Current local verification for this release: `2425 passed, 2 skipped` on March 6, 2026.
|
|
75
73
|
|
|
76
74
|
- Verification and provider matrix: [docs/proof.md](docs/proof.md)
|
|
77
75
|
- Sample setup transcript: [docs/transcripts/setup.md](docs/transcripts/setup.md)
|
package/commands/OMG:setup.md
CHANGED
|
@@ -10,7 +10,7 @@ Feature-gated: requires `OMG_SETUP_ENABLED=1` or `settings.json._omg.features.SE
|
|
|
10
10
|
|
|
11
11
|
## Overview
|
|
12
12
|
|
|
13
|
-
Native OMG setup for Claude Code, Codex,
|
|
13
|
+
Native OMG setup for Claude Code, Codex, and other supported CLIs.
|
|
14
14
|
The command keeps migration logic internal and focuses the user on a small adoption flow:
|
|
15
15
|
|
|
16
16
|
1. Detect supported CLIs.
|
|
@@ -25,7 +25,6 @@ The command keeps migration logic internal and focuses the user on a small adopt
|
|
|
25
25
|
Step 1: Detect CLIs
|
|
26
26
|
- codex
|
|
27
27
|
- gemini
|
|
28
|
-
- opencode
|
|
29
28
|
- kimi
|
|
30
29
|
|
|
31
30
|
Step 2: Detect adoption context
|
package/hooks/prompt-enhancer.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""
|
|
3
3
|
UserPromptSubmit Hook — OMG v1
|
|
4
4
|
|
|
5
|
-
Inspired by
|
|
5
|
+
Inspired by earlier OMG routing experiments. Key upgrades:
|
|
6
6
|
1. Intent classification BEFORE acting (IntentGate)
|
|
7
7
|
2. Discipline enforcement — never stop halfway
|
|
8
8
|
3. Agent-aware routing — Codex/Gemini/Claude orchestration
|
package/hooks/setup_wizard.py
CHANGED
|
@@ -24,14 +24,12 @@ from runtime.mcp_config_writers import ( # noqa: E402
|
|
|
24
24
|
write_claude_mcp_config,
|
|
25
25
|
write_codex_mcp_config,
|
|
26
26
|
write_gemini_mcp_config,
|
|
27
|
-
write_opencode_mcp_config,
|
|
28
27
|
write_kimi_mcp_config,
|
|
29
28
|
)
|
|
30
29
|
|
|
31
30
|
# Trigger provider auto-registration on import
|
|
32
31
|
import runtime.providers.codex_provider # noqa: E402, F401
|
|
33
32
|
import runtime.providers.gemini_provider # noqa: E402, F401
|
|
34
|
-
import runtime.providers.opencode_provider # noqa: E402, F401
|
|
35
33
|
import runtime.providers.kimi_provider # noqa: E402, F401
|
|
36
34
|
from runtime.adoption import ( # noqa: E402
|
|
37
35
|
CANONICAL_VERSION,
|
|
@@ -46,7 +44,6 @@ _logger = logging.getLogger(__name__)
|
|
|
46
44
|
_INSTALL_HINTS: dict[str, str] = {
|
|
47
45
|
"codex": "npm install -g @openai/codex",
|
|
48
46
|
"gemini": "npm install -g @google/gemini-cli",
|
|
49
|
-
"opencode": "npm install -g opencode-ai (or: curl -fsSL https://opencode.ai/install | bash)",
|
|
50
47
|
"kimi": "uv tool install --python 3.13 kimi-cli",
|
|
51
48
|
}
|
|
52
49
|
|
|
@@ -325,7 +322,7 @@ def get_cli_auth_instructions(provider: str) -> dict[str, str]:
|
|
|
325
322
|
or store credentials.
|
|
326
323
|
|
|
327
324
|
Args:
|
|
328
|
-
provider: CLI provider name (e.g. "codex", "gemini", "kimi"
|
|
325
|
+
provider: CLI provider name (e.g. "codex", "gemini", or "kimi").
|
|
329
326
|
|
|
330
327
|
Returns:
|
|
331
328
|
Dict with keys: install, auth, verify, subscription.
|
|
@@ -350,12 +347,6 @@ def get_cli_auth_instructions(provider: str) -> dict[str, str]:
|
|
|
350
347
|
"verify": "kimi --version",
|
|
351
348
|
"subscription": "Requires Kimi API key from platform.moonshot.cn",
|
|
352
349
|
},
|
|
353
|
-
"opencode": {
|
|
354
|
-
"install": "npm install -g opencode-ai",
|
|
355
|
-
"auth": "opencode auth login",
|
|
356
|
-
"verify": "opencode --version",
|
|
357
|
-
"subscription": "Requires Anthropic API key or Claude subscription",
|
|
358
|
-
},
|
|
359
350
|
}
|
|
360
351
|
|
|
361
352
|
return instructions.get(provider, {
|
|
@@ -412,7 +403,6 @@ def configure_mcp(
|
|
|
412
403
|
cli_writers = {
|
|
413
404
|
"codex": write_codex_mcp_config,
|
|
414
405
|
"gemini": write_gemini_mcp_config,
|
|
415
|
-
"opencode": write_opencode_mcp_config,
|
|
416
406
|
"kimi": write_kimi_mcp_config,
|
|
417
407
|
}
|
|
418
408
|
|
|
@@ -460,7 +450,6 @@ def set_preferences(project_dir: str, preferences: dict[str, Any]) -> dict[str,
|
|
|
460
450
|
default_cli_configs: dict[str, Any] = {
|
|
461
451
|
"codex": {"subscription": "free", "max_parallel_agents": 1},
|
|
462
452
|
"gemini": {"subscription": "free", "max_parallel_agents": 1},
|
|
463
|
-
"opencode": {"subscription": "free", "max_parallel_agents": 1},
|
|
464
453
|
"kimi": {"subscription": "free", "max_parallel_agents": 1},
|
|
465
454
|
}
|
|
466
455
|
preset = resolve_preset(cast(str | None, preferences.get("preset")))
|
package/package.json
CHANGED
package/plugins/README.md
CHANGED
|
@@ -50,5 +50,5 @@ Public migration commands are intentionally avoided. OMG uses `/OMG:setup` and `
|
|
|
50
50
|
|
|
51
51
|
## Public Docs
|
|
52
52
|
|
|
53
|
-
- Install guides live in [docs/install/claude-code.md](../docs/install/claude-code.md)
|
|
53
|
+
- Install guides live in [docs/install/claude-code.md](../docs/install/claude-code.md) and [docs/install/codex.md](../docs/install/codex.md).
|
|
54
54
|
- Proof surface lives in [docs/proof.md](../docs/proof.md).
|
package/plugins/core/plugin.json
CHANGED
package/runtime/adoption.py
CHANGED
|
@@ -11,7 +11,7 @@ CANONICAL_REPO_URL = "https://github.com/trac3er00/OMG"
|
|
|
11
11
|
CANONICAL_PACKAGE_NAME = "@trac3er/oh-my-god"
|
|
12
12
|
CANONICAL_PLUGIN_ID = "omg"
|
|
13
13
|
CANONICAL_MARKETPLACE_ID = "omg"
|
|
14
|
-
CANONICAL_VERSION = "2.0.
|
|
14
|
+
CANONICAL_VERSION = "2.0.3"
|
|
15
15
|
|
|
16
16
|
VALID_ADOPTION_MODES = ("omg-only", "coexist")
|
|
17
17
|
VALID_PRESETS = ("safe", "balanced", "interop", "labs")
|
|
@@ -93,17 +93,6 @@ def write_gemini_mcp_config(server_url: str, server_name: str = "memory-server")
|
|
|
93
93
|
_write_json(config_path, config)
|
|
94
94
|
|
|
95
95
|
|
|
96
|
-
def write_opencode_mcp_config(server_url: str, server_name: str = "memory-server") -> None:
|
|
97
|
-
config_path = Path.home() / ".config" / "opencode" / "opencode.json"
|
|
98
|
-
config = _load_json(config_path)
|
|
99
|
-
mcp = config.get("mcp")
|
|
100
|
-
if not isinstance(mcp, dict):
|
|
101
|
-
mcp = {}
|
|
102
|
-
config["mcp"] = mcp
|
|
103
|
-
mcp[server_name] = {"type": "remote", "url": server_url}
|
|
104
|
-
_write_json(config_path, config)
|
|
105
|
-
|
|
106
|
-
|
|
107
96
|
def write_kimi_mcp_config(server_url: str, server_name: str = "memory-server") -> None:
|
|
108
97
|
config_path = Path.home() / ".kimi" / "mcp.json"
|
|
109
98
|
config = _load_json(config_path)
|
package/runtime/team_router.py
CHANGED
|
@@ -26,7 +26,6 @@ _logger = logging.getLogger(__name__)
|
|
|
26
26
|
try:
|
|
27
27
|
import runtime.providers.codex_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
|
|
28
28
|
import runtime.providers.gemini_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
|
|
29
|
-
import runtime.providers.opencode_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
|
|
30
29
|
import runtime.providers.kimi_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
|
|
31
30
|
except ImportError:
|
|
32
31
|
pass
|
|
@@ -550,7 +549,6 @@ def dispatch_to_model(agent_name: str, user_prompt: str, project_dir: str) -> di
|
|
|
550
549
|
provider_name_map = {
|
|
551
550
|
"codex-cli": "codex",
|
|
552
551
|
"gemini-cli": "gemini",
|
|
553
|
-
"opencode-cli": "opencode",
|
|
554
552
|
"kimi-cli": "kimi",
|
|
555
553
|
}
|
|
556
554
|
provider_name = provider_name_map.get(preferred)
|
package/scripts/omg.py
CHANGED
package/settings.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
3
|
-
"_comment": "OMG 2.0.
|
|
3
|
+
"_comment": "OMG 2.0.3 - project-level config with hook registrations, presets, and feature flags.",
|
|
4
4
|
"permissions": {
|
|
5
5
|
"allow": [
|
|
6
6
|
"Agent",
|
|
@@ -262,7 +262,7 @@
|
|
|
262
262
|
]
|
|
263
263
|
},
|
|
264
264
|
"_omg": {
|
|
265
|
-
"_version": "2.0.
|
|
265
|
+
"_version": "2.0.3",
|
|
266
266
|
"preset": "safe",
|
|
267
267
|
"default_mode": "ulw+ralph",
|
|
268
268
|
"vision_auto": true,
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
"""OpenCode CLI provider -- implements CLIProvider for the ``opencode`` binary."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import json
|
|
6
|
-
import logging
|
|
7
|
-
import os
|
|
8
|
-
import shlex
|
|
9
|
-
import shutil
|
|
10
|
-
import subprocess
|
|
11
|
-
import uuid
|
|
12
|
-
from typing import Any
|
|
13
|
-
|
|
14
|
-
from runtime.cli_provider import CLIProvider, register_provider
|
|
15
|
-
from runtime.tmux_session_manager import TmuxSessionManager
|
|
16
|
-
|
|
17
|
-
_logger = logging.getLogger(__name__)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class OpenCodeProvider(CLIProvider):
|
|
21
|
-
"""CLIProvider implementation for the OpenCode CLI (``opencode``)."""
|
|
22
|
-
|
|
23
|
-
# -- identity -----------------------------------------------------------
|
|
24
|
-
|
|
25
|
-
def get_name(self) -> str: # noqa: D401
|
|
26
|
-
"""Return the canonical provider name."""
|
|
27
|
-
return "opencode"
|
|
28
|
-
|
|
29
|
-
# -- detection ----------------------------------------------------------
|
|
30
|
-
|
|
31
|
-
def detect(self) -> bool:
|
|
32
|
-
"""Return ``True`` when the ``opencode`` binary is available on PATH."""
|
|
33
|
-
return shutil.which("opencode") is not None
|
|
34
|
-
|
|
35
|
-
# -- authentication -----------------------------------------------------
|
|
36
|
-
|
|
37
|
-
def check_auth(self) -> tuple[bool | None, str]:
|
|
38
|
-
"""Check OpenCode authentication status via ``opencode auth list``."""
|
|
39
|
-
try:
|
|
40
|
-
result = self.run_tool(["opencode", "auth", "list"], timeout=30)
|
|
41
|
-
if result.returncode == 0:
|
|
42
|
-
return True, result.stdout.strip()
|
|
43
|
-
return False, result.stderr.strip() or result.stdout.strip()
|
|
44
|
-
except Exception as exc:
|
|
45
|
-
return None, f"opencode auth check failed: {exc}"
|
|
46
|
-
|
|
47
|
-
# -- invocation ---------------------------------------------------------
|
|
48
|
-
|
|
49
|
-
def invoke(self, prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
|
|
50
|
-
"""Invoke ``opencode run`` via subprocess."""
|
|
51
|
-
try:
|
|
52
|
-
result = self.run_tool(
|
|
53
|
-
["opencode", "run", prompt],
|
|
54
|
-
timeout=timeout,
|
|
55
|
-
)
|
|
56
|
-
return {
|
|
57
|
-
"model": "opencode-cli",
|
|
58
|
-
"output": result.stdout,
|
|
59
|
-
"exit_code": result.returncode,
|
|
60
|
-
}
|
|
61
|
-
except subprocess.TimeoutExpired:
|
|
62
|
-
return {"error": "opencode-cli timeout", "fallback": "claude"}
|
|
63
|
-
except FileNotFoundError:
|
|
64
|
-
return {"error": "opencode-cli not found", "fallback": "claude"}
|
|
65
|
-
except Exception as exc:
|
|
66
|
-
return {"error": str(exc), "fallback": "claude"}
|
|
67
|
-
|
|
68
|
-
def invoke_json(self, prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
|
|
69
|
-
"""Invoke ``opencode run --format json`` for raw JSON event stream output."""
|
|
70
|
-
try:
|
|
71
|
-
result = self.run_tool(
|
|
72
|
-
["opencode", "run", "--format", "json", prompt],
|
|
73
|
-
timeout=timeout,
|
|
74
|
-
)
|
|
75
|
-
return {
|
|
76
|
-
"model": "opencode-cli",
|
|
77
|
-
"output": result.stdout,
|
|
78
|
-
"exit_code": result.returncode,
|
|
79
|
-
}
|
|
80
|
-
except subprocess.TimeoutExpired:
|
|
81
|
-
return {"error": "opencode-cli timeout", "fallback": "claude"}
|
|
82
|
-
except FileNotFoundError:
|
|
83
|
-
return {"error": "opencode-cli not found", "fallback": "claude"}
|
|
84
|
-
except Exception as exc:
|
|
85
|
-
return {"error": str(exc), "fallback": "claude"}
|
|
86
|
-
|
|
87
|
-
def invoke_tmux(self, prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
|
|
88
|
-
"""Invoke ``opencode run`` via a persistent tmux session.
|
|
89
|
-
|
|
90
|
-
Falls back to :meth:`invoke` on failure.
|
|
91
|
-
"""
|
|
92
|
-
try:
|
|
93
|
-
mgr = TmuxSessionManager()
|
|
94
|
-
session_name = mgr.make_session_name("opencode", unique_id=str(uuid.uuid4())[:8])
|
|
95
|
-
session = mgr.get_or_create_session(session_name)
|
|
96
|
-
output = mgr.send_command(session, f"opencode run {shlex.quote(prompt)}", timeout=timeout)
|
|
97
|
-
mgr.kill_session(session)
|
|
98
|
-
return {"model": "opencode-cli", "output": output, "exit_code": 0}
|
|
99
|
-
except Exception as exc:
|
|
100
|
-
_logger.warning("tmux opencode invocation failed, falling back to subprocess: %s", exc)
|
|
101
|
-
return self.invoke(prompt, project_dir, timeout=timeout)
|
|
102
|
-
|
|
103
|
-
# -- command helpers ----------------------------------------------------
|
|
104
|
-
|
|
105
|
-
def get_non_interactive_cmd(self, prompt: str) -> list[str]:
|
|
106
|
-
"""Return the non-interactive command for opencode."""
|
|
107
|
-
return ["opencode", "run", prompt]
|
|
108
|
-
|
|
109
|
-
# -- configuration ------------------------------------------------------
|
|
110
|
-
|
|
111
|
-
def get_config_path(self) -> str:
|
|
112
|
-
"""Return the OpenCode configuration file path."""
|
|
113
|
-
return os.path.expanduser("~/.config/opencode/opencode.json")
|
|
114
|
-
|
|
115
|
-
def write_mcp_config(self, server_url: str, server_name: str = "memory-server") -> None:
|
|
116
|
-
"""Write an MCP server entry to ``~/.config/opencode/opencode.json``.
|
|
117
|
-
|
|
118
|
-
Uses JSON format with ``mcp`` key, ``type: "remote"``, and ``url`` field,
|
|
119
|
-
merging into any existing configuration.
|
|
120
|
-
"""
|
|
121
|
-
config_path = self.get_config_path()
|
|
122
|
-
os.makedirs(os.path.dirname(config_path), exist_ok=True)
|
|
123
|
-
|
|
124
|
-
# Load existing config or start fresh
|
|
125
|
-
existing: dict[str, Any] = {} # pyright: ignore[reportExplicitAny]
|
|
126
|
-
if os.path.exists(config_path):
|
|
127
|
-
with open(config_path) as fh:
|
|
128
|
-
try:
|
|
129
|
-
existing = json.load(fh)
|
|
130
|
-
except (json.JSONDecodeError, ValueError):
|
|
131
|
-
existing = {}
|
|
132
|
-
|
|
133
|
-
# Ensure mcp dict exists
|
|
134
|
-
if "mcp" not in existing:
|
|
135
|
-
existing["mcp"] = {}
|
|
136
|
-
|
|
137
|
-
existing["mcp"][server_name] = {"type": "remote", "url": server_url}
|
|
138
|
-
|
|
139
|
-
with open(config_path, "w") as fh:
|
|
140
|
-
json.dump(existing, fh, indent=2)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
# -- auto-register on import -----------------------------------------------
|
|
144
|
-
register_provider(OpenCodeProvider())
|