oh-my-githubcopilot 1.8.0-alpha.f50f59a → 1.8.1-alpha.11991fb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "1.0",
3
3
  "name": "oh-my-githubcopilot",
4
- "version": "1.8.0",
4
+ "version": "1.8.1",
5
5
  "description": "Multi-agent orchestration for GitHub Copilot CLI. 23 agents, 39 skills, parallel execution, HUD, PSM, SWE-bench.",
6
6
  "author": {
7
7
  "name": "r3dlex"
package/AGENTS.md CHANGED
@@ -174,3 +174,8 @@ Before starting work on an issue:
174
174
  3. Do not make a fourth attempt without human acknowledgement.
175
175
 
176
176
  <!-- ai-sdlc-init:end -->
177
+
178
+ <!-- v3-ai-sdlc-init:start -->
179
+ ## AI SDLC v3
180
+ This repo follows the v3 AI-SDLC layout. See `.ai/matrix.json`, `.memory/human-override/`, and `docs/architecture/adr/`. Modules at `r3dlex/skills/ai-sdlc-init/modules/`.
181
+ <!-- v3-ai-sdlc-init:end -->
package/CHANGELOG.md CHANGED
@@ -1,9 +1,40 @@
1
+ ## oh-my-githubcopilot v1.8.1 — 2026-05-25
2
+
3
+ ### Fixes
4
+
5
+ - **Node.js v26 native addon compatibility** — upgraded `better-sqlite3` from `^11.0.0` to `^12.10.0` to resolve
6
+ V8 API removals (`GetPrototype`, `GetIsolate`, `PropertyCallbackInfo::This`) that broke `npm install -g oh-my-githubcopilot`
7
+ on Node.js v26 (all macOS, Linux, and Windows with V8 >= 12.0)
8
+
9
+ ### Changed
10
+
11
+ - **Dependencies**: `better-sqlite3` ^11.0.0 → ^12.10.0, `@types/better-sqlite3` ^7.0.0 → ^7.6.13
12
+
13
+ ---
14
+
1
15
  # Changelog
2
16
 
3
17
  All notable changes to **oh-my-githubcopilot** are documented here, ordered newest first.
4
18
 
5
19
  ---
6
20
 
21
+ ## oh-my-githubcopilot v1.8.0 — 2026-05-25
22
+
23
+ ### Features
24
+
25
+ - **Cross-repo sync**: Aligned README template, Star History chart, sponsor links, and badge shields with OMX/OMC/OMA/OMG
26
+ - **Dual publish**: GitHub Actions release workflow now publishes to both npmjs.com (oh-my-githubcopilot) and GitHub Packages (@r3dlex/oh-my-githubcopilot) with version verification
27
+ - **README updates**: 12 localized README files regenerated from unified template
28
+ - **AI SDLC methodology**: Scaffolded across the repo with Archgate rules, ADR governance, Karpathy guidelines
29
+
30
+ ### Documentation
31
+
32
+ - Updated READMEs across 13 languages (en, de, es, fr, it, ja, ko, pt, ru, tr, vi, zh)
33
+ - Star History chart added for r3dlex/oh-my-githubcopilot
34
+ - Sponsor link updated to github.com/sponsors/r3dlex
35
+
36
+ ---
37
+
7
38
  ## oh-my-githubcopilot v1.7.0 — 2026-04-21
8
39
 
9
40
  ### Features
package/README.de.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **Multi-Agent-Orchestrierung für GitHub Copilot CLI. Keine Lernkurve.**
6
6
 
package/README.es.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **Orquestación multiagente para GitHub Copilot CLI. Sin curva de aprendizaje.**
6
6
 
package/README.fr.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **Orchestration multi-agent pour GitHub Copilot CLI. Aucune courbe d’apprentissage.**
6
6
 
package/README.it.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **Orchestrazione multi-agente per GitHub Copilot CLI. Nessuna curva di apprendimento.**
6
6
 
package/README.ja.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **GitHub Copilot CLI のためのマルチエージェント・オーケストレーション。学習コストはゼロ。**
6
6
 
package/README.ko.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **GitHub Copilot CLI를 위한 멀티 에이전트 오케스트레이션. 학습 곡선은 없습니다.**
6
6
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **Multi-agent orchestration for GitHub Copilot CLI. Zero learning curve.**
6
6
 
@@ -138,3 +138,8 @@ omp is open source under the [Apache-2.0 License](LICENSE).
138
138
  ## Sponsors
139
139
 
140
140
  If omp saves you time, consider [sponsoring the project](https://github.com/sponsors/r3dlex) ❤️
141
+
142
+ <!-- v3-ai-sdlc-init:start -->
143
+ ## AI SDLC v3
144
+ This repo follows the v3 AI-SDLC layout. See `.ai/matrix.json`, `.memory/human-override/`, and `docs/architecture/adr/`. Modules at `r3dlex/skills/ai-sdlc-init/modules/`.
145
+ <!-- v3-ai-sdlc-init:end -->
package/README.pt.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **Orquestração multiagente para GitHub Copilot CLI. Curva de aprendizado zero.**
6
6
 
package/README.ru.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **Мультиагентная оркестрация для GitHub Copilot CLI. Без кривой обучения.**
6
6
 
package/README.tr.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **GitHub Copilot CLI için çok ajanlı orkestrasyon. Öğrenme eğrisi yok.**
6
6
 
package/README.vi.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **Điều phối đa tác nhân cho GitHub Copilot CLI. Không cần đường cong học tập.**
6
6
 
package/README.zh.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oh-my-githubcopilot (omp)
2
2
 
3
- > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-gemini (OMG)](https://github.com/r3dlex/oh-my-gemini) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
3
+ > **Sister projects:** [oh-my-claudecode (OMC)](https://github.com/Yeachan-Heo/oh-my-claudecode) | [oh-my-codex (OMX)](https://github.com/Yeachan-Heo/oh-my-codex) | [oh-my-githubcopilot (OMP)](https://github.com/r3dlex/oh-my-githubcopilot) | [oh-my-antigravity (OMG)](https://github.com/r3dlex/oh-my-antigravity) | [oh-my-auggie (OMA)](https://github.com/r3dlex/oh-my-auggie)
4
4
 
5
5
  **面向 GitHub Copilot CLI 的多智能体编排。零学习成本。**
6
6
 
@@ -149,17 +149,17 @@ function writeHudArtifacts(snapshot, paths = getStatuslinePaths()) {
149
149
  return { line, state, paths };
150
150
  }
151
151
  function readStatusline(paths = getStatuslinePaths()) {
152
- try {
153
- const line = readFileSync(paths.displayPath, "utf-8").trim();
154
- if (line) return line;
155
- } catch {
156
- }
157
152
  try {
158
153
  const parsed = JSON.parse(readFileSync(paths.statusJsonPath, "utf-8"));
159
154
  const state = deserializeHudState(parsed);
160
155
  if (state) return renderPlain(state);
161
156
  } catch {
162
157
  }
158
+ try {
159
+ const line = readFileSync(paths.displayPath, "utf-8").trim();
160
+ if (line) return line;
161
+ } catch {
162
+ }
163
163
  try {
164
164
  const line = readFileSync(paths.legacyLinePath, "utf-8").trim();
165
165
  if (line) return line;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/hud/statusline.mts", "../src/hud/renderer.mts"],
4
- "sourcesContent": ["/**\n * HUD statusline helpers and standalone entrypoint.\n *\n * Keeps HUD artifact generation in one place so hooks and shell wrappers\n * can share the same rendering and fallback behavior.\n */\n\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { renderPlain, type HudState, type HudStatus } from \"./renderer.mts\";\n\nconst DEFAULT_VERSION = \"0.0.0\";\nconst DEFAULT_STATUSLINE = \"OMP | hud: no active session\";\nconst DEFAULT_TOKEN_BUDGET = 200_000;\nconst DEFAULT_PREMIUM_REQUESTS_TOTAL = 1500;\n\nexport interface StatuslinePaths {\n legacyLinePath: string;\n hudDir: string;\n statusJsonPath: string;\n displayPath: string;\n tmuxSegmentPath: string;\n}\n\nexport interface HudSnapshot {\n version?: string;\n session_id?: string;\n started_at?: number;\n updated_at?: number;\n model?: string;\n tokens_estimated?: number;\n token_budget?: number;\n context_pct?: number;\n tools_used?: string[];\n skills_used?: string[];\n agents_used?: string[];\n active_mode?: string | null;\n last_output?: string;\n task_progress?: number;\n status?: HudStatus;\n premium_requests?: number;\n premium_requests_total?: number;\n warning_active?: boolean;\n}\n\ninterface SerializedHudState extends Omit<HudState, \"toolsUsed\" | \"skillsUsed\"> {\n toolsUsed: string[];\n skillsUsed: string[];\n}\n\nexport function getStatuslinePaths(home = process.env[\"HOME\"] || homedir()): StatuslinePaths {\n const ompDir = join(home, \".omp\");\n const hudDir = join(ompDir, \"hud\");\n return {\n legacyLinePath: join(ompDir, \"hud.line\"),\n hudDir,\n statusJsonPath: join(hudDir, \"status.json\"),\n displayPath: join(hudDir, \"display.txt\"),\n tmuxSegmentPath: join(hudDir, \"tmux-segment.sh\"),\n };\n}\n\nfunction ensureParent(filePath: string): void {\n mkdirSync(dirname(filePath), { recursive: true });\n}\n\nfunction writeAtomic(filePath: string, content: string, mode?: number): void {\n ensureParent(filePath);\n const tempPath = `${filePath}.tmp`;\n writeFileSync(tempPath, content, mode === undefined ? \"utf-8\" : { encoding: \"utf-8\", mode });\n renameSync(tempPath, filePath);\n}\n\nfunction normalizeStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === \"string\");\n}\n\nfunction serializeHudState(state: HudState): SerializedHudState {\n return {\n ...state,\n toolsUsed: Array.from(state.toolsUsed),\n skillsUsed: Array.from(state.skillsUsed),\n };\n}\n\nfunction deserializeHudState(raw: unknown): HudState | null {\n if (!raw || typeof raw !== \"object\") return null;\n const value = raw as Record<string, unknown>;\n const toolsUsed = new Set(normalizeStringArray(value.toolsUsed));\n const skillsUsed = new Set(normalizeStringArray(value.skillsUsed));\n const agentsActive = normalizeStringArray(value.agentsActive);\n const status = typeof value.status === \"string\" ? (value.status as HudStatus) : \"idle\";\n\n return {\n sessionId: typeof value.sessionId === \"string\" ? value.sessionId : \"default\",\n activeMode: typeof value.activeMode === \"string\" ? value.activeMode : null,\n activeModel: typeof value.activeModel === \"string\" ? value.activeModel : \"sonnet\",\n contextPct: typeof value.contextPct === \"number\" ? value.contextPct : 0,\n tokensUsed: typeof value.tokensUsed === \"number\" ? value.tokensUsed : 0,\n tokensTotal: typeof value.tokensTotal === \"number\" ? value.tokensTotal : DEFAULT_TOKEN_BUDGET,\n agentsActive,\n lastAgent: typeof value.lastAgent === \"string\" ? value.lastAgent : agentsActive.at(-1) ?? \"-\",\n lastOutput: typeof value.lastOutput === \"string\" ? value.lastOutput : \"\",\n taskProgress: typeof value.taskProgress === \"number\" ? value.taskProgress : 0,\n startedAt: typeof value.startedAt === \"number\" ? value.startedAt : Date.now(),\n updatedAt: typeof value.updatedAt === \"number\" ? value.updatedAt : Date.now(),\n version: typeof value.version === \"string\" ? value.version : DEFAULT_VERSION,\n status,\n sessionDurationMs: typeof value.sessionDurationMs === \"number\" ? value.sessionDurationMs : 0,\n cumulativeAgentsUsed: typeof value.cumulativeAgentsUsed === \"number\" ? value.cumulativeAgentsUsed : agentsActive.length,\n toolsUsed,\n skillsUsed,\n toolsTotal: typeof value.toolsTotal === \"number\" ? value.toolsTotal : 13,\n skillsTotal: typeof value.skillsTotal === \"number\" ? value.skillsTotal : 25,\n agentsTotal: typeof value.agentsTotal === \"number\" ? value.agentsTotal : 23,\n premiumRequests: typeof value.premiumRequests === \"number\" ? value.premiumRequests : 0,\n premiumRequestsTotal: typeof value.premiumRequestsTotal === \"number\" ? value.premiumRequestsTotal : DEFAULT_PREMIUM_REQUESTS_TOTAL,\n warningActive: typeof value.warningActive === \"boolean\" ? value.warningActive : false,\n };\n}\n\nexport function buildHudState(snapshot: HudSnapshot, now = Date.now()): HudState {\n const startedAt = snapshot.started_at ?? now;\n const updatedAt = snapshot.updated_at ?? now;\n const toolsUsed = new Set(normalizeStringArray(snapshot.tools_used));\n const skillsUsed = new Set(normalizeStringArray(snapshot.skills_used));\n const agentsActive = normalizeStringArray(snapshot.agents_used);\n\n return {\n sessionId: snapshot.session_id ?? \"default\",\n activeMode: snapshot.active_mode ?? null,\n activeModel: snapshot.model ?? \"sonnet\",\n contextPct: snapshot.context_pct ?? 0,\n tokensUsed: snapshot.tokens_estimated ?? 0,\n tokensTotal: snapshot.token_budget ?? DEFAULT_TOKEN_BUDGET,\n agentsActive,\n lastAgent: agentsActive.at(-1) ?? \"-\",\n lastOutput: snapshot.last_output ?? \"\",\n taskProgress: snapshot.task_progress ?? 0,\n startedAt,\n updatedAt,\n version: snapshot.version ?? DEFAULT_VERSION,\n status: snapshot.status ?? \"idle\",\n sessionDurationMs: Math.max(0, updatedAt - startedAt),\n cumulativeAgentsUsed: agentsActive.length,\n toolsUsed,\n skillsUsed,\n toolsTotal: 13,\n skillsTotal: 25,\n agentsTotal: 23,\n premiumRequests: snapshot.premium_requests ?? 0,\n premiumRequestsTotal: snapshot.premium_requests_total ?? DEFAULT_PREMIUM_REQUESTS_TOTAL,\n warningActive: snapshot.warning_active ?? false,\n };\n}\n\nexport function writeHudArtifacts(snapshot: HudSnapshot, paths = getStatuslinePaths()): { line: string; state: HudState; paths: StatuslinePaths } {\n const state = buildHudState(snapshot);\n const line = renderPlain(state);\n const serializedState = `${JSON.stringify(serializeHudState(state), null, 2)}\\n`;\n\n writeAtomic(paths.statusJsonPath, serializedState);\n writeAtomic(paths.displayPath, `${line}\\n`);\n writeAtomic(paths.tmuxSegmentPath, `${line}\\n`, 0o755);\n writeAtomic(paths.legacyLinePath, `${line}\\n`);\n\n return { line, state, paths };\n}\n\nexport function readStatusline(paths = getStatuslinePaths()): string {\n try {\n const line = readFileSync(paths.displayPath, \"utf-8\").trim();\n if (line) return line;\n } catch {\n // Fall through to other sources.\n }\n\n try {\n const parsed = JSON.parse(readFileSync(paths.statusJsonPath, \"utf-8\"));\n const state = deserializeHudState(parsed);\n if (state) return renderPlain(state);\n } catch {\n // Fall through to legacy file.\n }\n\n try {\n const line = readFileSync(paths.legacyLinePath, \"utf-8\").trim();\n if (line) return line;\n } catch {\n // No HUD artifacts yet.\n }\n\n return DEFAULT_STATUSLINE;\n}\n\nif (process.argv[1] === fileURLToPath(import.meta.url)) {\n console.log(readStatusline());\n}\n", "/**\n * HUD Renderer\n * Formats HudState into ANSI or plain text status lines.\n */\n\n\nexport interface HudState {\n sessionId: string;\n activeMode: string | null;\n activeModel: string;\n contextPct: number;\n tokensUsed: number;\n tokensTotal: number;\n agentsActive: string[];\n lastAgent: string;\n lastOutput: string;\n taskProgress: number;\n startedAt: number;\n updatedAt: number;\n version: string;\n status: HudStatus;\n sessionDurationMs: number;\n cumulativeAgentsUsed: number;\n toolsUsed: Set<string>;\n skillsUsed: Set<string>;\n toolsTotal: number;\n skillsTotal: number;\n agentsTotal: number;\n premiumRequests: number;\n premiumRequestsTotal: number;\n warningActive: boolean;\n}\n\nexport type HudStatus = \"idle\" | \"running\" | \"waiting\" | \"complete\" | \"error\" | \"eco\";\n\nconst STATUS_ICONS: Record<HudStatus, string> = {\n idle: \"\u25CB\",\n running: \"\u25CF\",\n waiting: \"\u25F7\",\n complete: \"\u2713\",\n error: \"\u2717\",\n eco: \"\u26A1\",\n};\n\nfunction formatAge(startedAt: number): string {\n const elapsed = Date.now() - startedAt;\n const mins = Math.floor(elapsed / 60000);\n if (mins < 60) return `${mins}m`;\n const hours = Math.floor(mins / 60);\n const remainingMins = mins % 60;\n return `${hours}h${remainingMins}m`;\n}\n\nfunction formatTokens(tokens: number): string {\n if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M`;\n if (tokens >= 1_000) return `${(tokens / 1_000).toFixed(1)}k`;\n return `${tokens}`;\n}\n\nfunction ctxColor(pct: number): string {\n if (pct < 60) return \"\\x1b[32m\"; // green\n if (pct < 85) return \"\\x1b[33m\"; // yellow\n return \"\\x1b[31m\"; // red\n}\n\nfunction reset(): string {\n return \"\\x1b[0m\";\n}\n\n/**\n * Render HUD line with ANSI color codes.\n * Format: [OMP v1.0.0] mode | model | ctx:N% | tok:~Nk/Nk | Nm | tools:N/N | skills:N/N | agents:N/N | N% status\n */\nexport function renderAnsi(state: HudState): string {\n const age = formatAge(state.startedAt);\n const tokens = formatTokens(state.tokensUsed);\n const ctx = state.contextPct;\n const mode = state.activeMode || \"-\";\n const model = state.activeModel || \"sonnet\";\n const icon = STATUS_ICONS[state.status] || \"\u25CF\";\n\n const ctxClr = ctxColor(ctx);\n const ctxStr = `${ctxClr}ctx:${ctx}%${reset()}`;\n const tokenStr = `tok:~${tokens}/${state.tokensTotal}`;\n const modeStr = mode === \"-\" ? \"-\" : `\\x1b[36m${mode}${reset()}`; // cyan for active modes\n\n const reqWarning = state.warningActive ? \" !!\" : \"\";\n const reqStr = `req:${state.premiumRequests ?? 0}/${state.premiumRequestsTotal ?? 1500}${reqWarning}`;\n\n return `[OMP v${state.version}] ${modeStr} | ${model} | ${ctxStr} | ${tokenStr} | ${reqStr} | ${age} | tools:${state.toolsUsed?.size || 0}/${state.toolsTotal ?? 13} | skills:${state.skillsUsed?.size || 0}/${state.skillsTotal ?? 25} | agents:${state.cumulativeAgentsUsed}/${state.agentsTotal ?? 23} | ${icon} ${state.status}`;\n}\n\n/**\n * Render HUD line as plain text (no ANSI codes).\n * Format: [OMP v1.0.0] mode | model | ctx:N% | tok:~Nk/Nk | Nm | tools:N/N | skills:N/N | agents:N/N | N% status\n */\nexport function renderPlain(state: HudState): string {\n const age = formatAge(state.startedAt);\n const tokens = formatTokens(state.tokensUsed);\n const ctx = state.contextPct;\n const mode = state.activeMode || \"-\";\n const model = state.activeModel || \"sonnet\";\n\n const reqWarningPlain = state.warningActive ? \" !!\" : \"\";\n const reqStrPlain = `req:${state.premiumRequests ?? 0}/${state.premiumRequestsTotal ?? 1500}${reqWarningPlain}`;\n\n return `[OMP v${state.version}] ${mode} | ${model} | ctx:${ctx}% | tok:~${tokens}/${state.tokensTotal} | ${reqStrPlain} | ${age} | tools:${state.toolsUsed?.size || 0}/${state.toolsTotal ?? 13} | skills:${state.skillsUsed?.size || 0}/${state.skillsTotal ?? 25} | agents:${state.cumulativeAgentsUsed}/${state.agentsTotal ?? 23} | ${state.status}`;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * HUD statusline helpers and standalone entrypoint.\n *\n * Keeps HUD artifact generation in one place so hooks and shell wrappers\n * can share the same rendering and fallback behavior.\n */\n\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { renderPlain, type HudState, type HudStatus } from \"./renderer.mts\";\n\nconst DEFAULT_VERSION = \"0.0.0\";\nconst DEFAULT_STATUSLINE = \"OMP | hud: no active session\";\nconst DEFAULT_TOKEN_BUDGET = 200_000;\nconst DEFAULT_PREMIUM_REQUESTS_TOTAL = 1500;\n\nexport interface StatuslinePaths {\n legacyLinePath: string;\n hudDir: string;\n statusJsonPath: string;\n displayPath: string;\n tmuxSegmentPath: string;\n}\n\nexport interface HudSnapshot {\n version?: string;\n session_id?: string;\n started_at?: number;\n updated_at?: number;\n model?: string;\n tokens_estimated?: number;\n token_budget?: number;\n context_pct?: number;\n tools_used?: string[];\n skills_used?: string[];\n agents_used?: string[];\n active_mode?: string | null;\n last_output?: string;\n task_progress?: number;\n status?: HudStatus;\n premium_requests?: number;\n premium_requests_total?: number;\n warning_active?: boolean;\n}\n\ninterface SerializedHudState extends Omit<HudState, \"toolsUsed\" | \"skillsUsed\"> {\n toolsUsed: string[];\n skillsUsed: string[];\n}\n\nexport function getStatuslinePaths(home = process.env[\"HOME\"] || homedir()): StatuslinePaths {\n const ompDir = join(home, \".omp\");\n const hudDir = join(ompDir, \"hud\");\n return {\n legacyLinePath: join(ompDir, \"hud.line\"),\n hudDir,\n statusJsonPath: join(hudDir, \"status.json\"),\n displayPath: join(hudDir, \"display.txt\"),\n tmuxSegmentPath: join(hudDir, \"tmux-segment.sh\"),\n };\n}\n\nfunction ensureParent(filePath: string): void {\n mkdirSync(dirname(filePath), { recursive: true });\n}\n\nfunction writeAtomic(filePath: string, content: string, mode?: number): void {\n ensureParent(filePath);\n const tempPath = `${filePath}.tmp`;\n writeFileSync(tempPath, content, mode === undefined ? \"utf-8\" : { encoding: \"utf-8\", mode });\n renameSync(tempPath, filePath);\n}\n\nfunction normalizeStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === \"string\");\n}\n\nfunction serializeHudState(state: HudState): SerializedHudState {\n return {\n ...state,\n toolsUsed: Array.from(state.toolsUsed),\n skillsUsed: Array.from(state.skillsUsed),\n };\n}\n\nfunction deserializeHudState(raw: unknown): HudState | null {\n if (!raw || typeof raw !== \"object\") return null;\n const value = raw as Record<string, unknown>;\n const toolsUsed = new Set(normalizeStringArray(value.toolsUsed));\n const skillsUsed = new Set(normalizeStringArray(value.skillsUsed));\n const agentsActive = normalizeStringArray(value.agentsActive);\n const status = typeof value.status === \"string\" ? (value.status as HudStatus) : \"idle\";\n\n return {\n sessionId: typeof value.sessionId === \"string\" ? value.sessionId : \"default\",\n activeMode: typeof value.activeMode === \"string\" ? value.activeMode : null,\n activeModel: typeof value.activeModel === \"string\" ? value.activeModel : \"sonnet\",\n contextPct: typeof value.contextPct === \"number\" ? value.contextPct : 0,\n tokensUsed: typeof value.tokensUsed === \"number\" ? value.tokensUsed : 0,\n tokensTotal: typeof value.tokensTotal === \"number\" ? value.tokensTotal : DEFAULT_TOKEN_BUDGET,\n agentsActive,\n lastAgent: typeof value.lastAgent === \"string\" ? value.lastAgent : agentsActive.at(-1) ?? \"-\",\n lastOutput: typeof value.lastOutput === \"string\" ? value.lastOutput : \"\",\n taskProgress: typeof value.taskProgress === \"number\" ? value.taskProgress : 0,\n startedAt: typeof value.startedAt === \"number\" ? value.startedAt : Date.now(),\n updatedAt: typeof value.updatedAt === \"number\" ? value.updatedAt : Date.now(),\n version: typeof value.version === \"string\" ? value.version : DEFAULT_VERSION,\n status,\n sessionDurationMs: typeof value.sessionDurationMs === \"number\" ? value.sessionDurationMs : 0,\n cumulativeAgentsUsed: typeof value.cumulativeAgentsUsed === \"number\" ? value.cumulativeAgentsUsed : agentsActive.length,\n toolsUsed,\n skillsUsed,\n toolsTotal: typeof value.toolsTotal === \"number\" ? value.toolsTotal : 13,\n skillsTotal: typeof value.skillsTotal === \"number\" ? value.skillsTotal : 25,\n agentsTotal: typeof value.agentsTotal === \"number\" ? value.agentsTotal : 23,\n premiumRequests: typeof value.premiumRequests === \"number\" ? value.premiumRequests : 0,\n premiumRequestsTotal: typeof value.premiumRequestsTotal === \"number\" ? value.premiumRequestsTotal : DEFAULT_PREMIUM_REQUESTS_TOTAL,\n warningActive: typeof value.warningActive === \"boolean\" ? value.warningActive : false,\n };\n}\n\nexport function buildHudState(snapshot: HudSnapshot, now = Date.now()): HudState {\n const startedAt = snapshot.started_at ?? now;\n const updatedAt = snapshot.updated_at ?? now;\n const toolsUsed = new Set(normalizeStringArray(snapshot.tools_used));\n const skillsUsed = new Set(normalizeStringArray(snapshot.skills_used));\n const agentsActive = normalizeStringArray(snapshot.agents_used);\n\n return {\n sessionId: snapshot.session_id ?? \"default\",\n activeMode: snapshot.active_mode ?? null,\n activeModel: snapshot.model ?? \"sonnet\",\n contextPct: snapshot.context_pct ?? 0,\n tokensUsed: snapshot.tokens_estimated ?? 0,\n tokensTotal: snapshot.token_budget ?? DEFAULT_TOKEN_BUDGET,\n agentsActive,\n lastAgent: agentsActive.at(-1) ?? \"-\",\n lastOutput: snapshot.last_output ?? \"\",\n taskProgress: snapshot.task_progress ?? 0,\n startedAt,\n updatedAt,\n version: snapshot.version ?? DEFAULT_VERSION,\n status: snapshot.status ?? \"idle\",\n sessionDurationMs: Math.max(0, updatedAt - startedAt),\n cumulativeAgentsUsed: agentsActive.length,\n toolsUsed,\n skillsUsed,\n toolsTotal: 13,\n skillsTotal: 25,\n agentsTotal: 23,\n premiumRequests: snapshot.premium_requests ?? 0,\n premiumRequestsTotal: snapshot.premium_requests_total ?? DEFAULT_PREMIUM_REQUESTS_TOTAL,\n warningActive: snapshot.warning_active ?? false,\n };\n}\n\nexport function writeHudArtifacts(snapshot: HudSnapshot, paths = getStatuslinePaths()): { line: string; state: HudState; paths: StatuslinePaths } {\n const state = buildHudState(snapshot);\n const line = renderPlain(state);\n const serializedState = `${JSON.stringify(serializeHudState(state), null, 2)}\\n`;\n\n writeAtomic(paths.statusJsonPath, serializedState);\n writeAtomic(paths.displayPath, `${line}\\n`);\n writeAtomic(paths.tmuxSegmentPath, `${line}\\n`, 0o755);\n writeAtomic(paths.legacyLinePath, `${line}\\n`);\n\n return { line, state, paths };\n}\n\nexport function readStatusline(paths = getStatuslinePaths()): string {\n // Try live render from status.json \u2014 formatAge runs at call time, not hook-fire time\n try {\n const parsed = JSON.parse(readFileSync(paths.statusJsonPath, \"utf-8\"));\n const state = deserializeHudState(parsed);\n if (state) return renderPlain(state);\n } catch {\n // Fall through to cached display string.\n }\n\n // Fallback: pre-rendered cached string (written by hud-emitter; used by tmux consumers)\n try {\n const line = readFileSync(paths.displayPath, \"utf-8\").trim();\n if (line) return line;\n } catch {\n // Fall through to legacy file.\n }\n\n try {\n const line = readFileSync(paths.legacyLinePath, \"utf-8\").trim();\n if (line) return line;\n } catch {\n // Fall through to default statusline.\n }\n\n return DEFAULT_STATUSLINE;\n}\n\nif (process.argv[1] === fileURLToPath(import.meta.url)) {\n console.log(readStatusline());\n}\n", "/**\n * HUD Renderer\n * Formats HudState into ANSI or plain text status lines.\n */\n\n\nexport interface HudState {\n sessionId: string;\n activeMode: string | null;\n activeModel: string;\n contextPct: number;\n tokensUsed: number;\n tokensTotal: number;\n agentsActive: string[];\n lastAgent: string;\n lastOutput: string;\n taskProgress: number;\n startedAt: number;\n updatedAt: number;\n version: string;\n status: HudStatus;\n sessionDurationMs: number;\n cumulativeAgentsUsed: number;\n toolsUsed: Set<string>;\n skillsUsed: Set<string>;\n toolsTotal: number;\n skillsTotal: number;\n agentsTotal: number;\n premiumRequests: number;\n premiumRequestsTotal: number;\n warningActive: boolean;\n}\n\nexport type HudStatus = \"idle\" | \"running\" | \"waiting\" | \"complete\" | \"error\" | \"eco\";\n\nconst STATUS_ICONS: Record<HudStatus, string> = {\n idle: \"\u25CB\",\n running: \"\u25CF\",\n waiting: \"\u25F7\",\n complete: \"\u2713\",\n error: \"\u2717\",\n eco: \"\u26A1\",\n};\n\nfunction formatAge(startedAt: number): string {\n const elapsed = Date.now() - startedAt;\n const mins = Math.floor(elapsed / 60000);\n if (mins < 60) return `${mins}m`;\n const hours = Math.floor(mins / 60);\n const remainingMins = mins % 60;\n return `${hours}h${remainingMins}m`;\n}\n\nfunction formatTokens(tokens: number): string {\n if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M`;\n if (tokens >= 1_000) return `${(tokens / 1_000).toFixed(1)}k`;\n return `${tokens}`;\n}\n\nfunction ctxColor(pct: number): string {\n if (pct < 60) return \"\\x1b[32m\"; // green\n if (pct < 85) return \"\\x1b[33m\"; // yellow\n return \"\\x1b[31m\"; // red\n}\n\nfunction reset(): string {\n return \"\\x1b[0m\";\n}\n\n/**\n * Render HUD line with ANSI color codes.\n * Format: [OMP v1.0.0] mode | model | ctx:N% | tok:~Nk/Nk | Nm | tools:N/N | skills:N/N | agents:N/N | N% status\n */\nexport function renderAnsi(state: HudState): string {\n const age = formatAge(state.startedAt);\n const tokens = formatTokens(state.tokensUsed);\n const ctx = state.contextPct;\n const mode = state.activeMode || \"-\";\n const model = state.activeModel || \"sonnet\";\n const icon = STATUS_ICONS[state.status] || \"\u25CF\";\n\n const ctxClr = ctxColor(ctx);\n const ctxStr = `${ctxClr}ctx:${ctx}%${reset()}`;\n const tokenStr = `tok:~${tokens}/${state.tokensTotal}`;\n const modeStr = mode === \"-\" ? \"-\" : `\\x1b[36m${mode}${reset()}`; // cyan for active modes\n\n const reqWarning = state.warningActive ? \" !!\" : \"\";\n const reqStr = `req:${state.premiumRequests ?? 0}/${state.premiumRequestsTotal ?? 1500}${reqWarning}`;\n\n return `[OMP v${state.version}] ${modeStr} | ${model} | ${ctxStr} | ${tokenStr} | ${reqStr} | ${age} | tools:${state.toolsUsed?.size || 0}/${state.toolsTotal ?? 13} | skills:${state.skillsUsed?.size || 0}/${state.skillsTotal ?? 25} | agents:${state.cumulativeAgentsUsed}/${state.agentsTotal ?? 23} | ${icon} ${state.status}`;\n}\n\n/**\n * Render HUD line as plain text (no ANSI codes).\n * Format: [OMP v1.0.0] mode | model | ctx:N% | tok:~Nk/Nk | Nm | tools:N/N | skills:N/N | agents:N/N | N% status\n */\nexport function renderPlain(state: HudState): string {\n const age = formatAge(state.startedAt);\n const tokens = formatTokens(state.tokensUsed);\n const ctx = state.contextPct;\n const mode = state.activeMode || \"-\";\n const model = state.activeModel || \"sonnet\";\n\n const reqWarningPlain = state.warningActive ? \" !!\" : \"\";\n const reqStrPlain = `req:${state.premiumRequests ?? 0}/${state.premiumRequestsTotal ?? 1500}${reqWarningPlain}`;\n\n return `[OMP v${state.version}] ${mode} | ${model} | ctx:${ctx}% | tok:~${tokens}/${state.tokensTotal} | ${reqStrPlain} | ${age} | tools:${state.toolsUsed?.size || 0}/${state.toolsTotal ?? 13} | skills:${state.skillsUsed?.size || 0}/${state.skillsTotal ?? 25} | agents:${state.cumulativeAgentsUsed}/${state.agentsTotal ?? 23} | ${state.status}`;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/bin/omp.mjs CHANGED
@@ -189,17 +189,17 @@ function writeHudArtifacts(snapshot, paths = getStatuslinePaths()) {
189
189
  return { line, state, paths };
190
190
  }
191
191
  function readStatusline(paths = getStatuslinePaths()) {
192
- try {
193
- const line = readFileSync(paths.displayPath, "utf-8").trim();
194
- if (line) return line;
195
- } catch {
196
- }
197
192
  try {
198
193
  const parsed = JSON.parse(readFileSync(paths.statusJsonPath, "utf-8"));
199
194
  const state = deserializeHudState(parsed);
200
195
  if (state) return renderPlain(state);
201
196
  } catch {
202
197
  }
198
+ try {
199
+ const line = readFileSync(paths.displayPath, "utf-8").trim();
200
+ if (line) return line;
201
+ } catch {
202
+ }
203
203
  try {
204
204
  const line = readFileSync(paths.legacyLinePath, "utf-8").trim();
205
205
  if (line) return line;
@@ -283,6 +283,62 @@ var init_watch = __esm({
283
283
  }
284
284
  });
285
285
 
286
+ // src/cli/install.mts
287
+ var install_exports = {};
288
+ __export(install_exports, {
289
+ runInstall: () => runInstall
290
+ });
291
+ import { mkdir as mkdir2, readFile as readFile2, rename, writeFile as writeFile2 } from "fs/promises";
292
+ import { homedir as homedir4 } from "os";
293
+ import { dirname as dirname3, join as join4 } from "path";
294
+ import { fileURLToPath as fileURLToPath2 } from "url";
295
+ async function runInstall(settingsPath = join4(homedir4(), ".copilot", "settings.json")) {
296
+ const pkgRoot = join4(dirname3(fileURLToPath2(import.meta.url)), "..");
297
+ const statusLineCommand = join4(pkgRoot, "bin", "omp-statusline.sh");
298
+ const marketplacePath = pkgRoot;
299
+ let existing = {};
300
+ try {
301
+ const raw = await readFile2(settingsPath, "utf-8");
302
+ const parsed = JSON.parse(raw);
303
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
304
+ existing = parsed;
305
+ }
306
+ } catch {
307
+ }
308
+ const existingPlugins = typeof existing.enabledPlugins === "object" && existing.enabledPlugins !== null && !Array.isArray(existing.enabledPlugins) ? existing.enabledPlugins : {};
309
+ const existingMarketplaces = typeof existing.extraKnownMarketplaces === "object" && existing.extraKnownMarketplaces !== null && !Array.isArray(existing.extraKnownMarketplaces) ? existing.extraKnownMarketplaces : {};
310
+ const merged = {
311
+ ...existing,
312
+ enabledPlugins: {
313
+ ...existingPlugins,
314
+ "oh-my-githubcopilot@oh-my-githubcopilot": true
315
+ },
316
+ experimental: true,
317
+ statusLine: { type: "command", command: statusLineCommand },
318
+ extraKnownMarketplaces: {
319
+ ...existingMarketplaces,
320
+ "oh-my-githubcopilot": {
321
+ source: { source: "directory", path: marketplacePath }
322
+ }
323
+ }
324
+ };
325
+ const tmp = `${settingsPath}.tmp`;
326
+ await mkdir2(dirname3(settingsPath), { recursive: true });
327
+ await writeFile2(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
328
+ await rename(tmp, settingsPath);
329
+ console.log(`omp install: wrote ${settingsPath}`);
330
+ console.log(` statusLine.command: ${statusLineCommand}`);
331
+ console.log(` marketplace path: ${marketplacePath}`);
332
+ console.log(` plugin: oh-my-githubcopilot@oh-my-githubcopilot`);
333
+ console.log(`
334
+ Restart Copilot CLI to activate OMP.`);
335
+ }
336
+ var init_install = __esm({
337
+ "src/cli/install.mts"() {
338
+ "use strict";
339
+ }
340
+ });
341
+
286
342
  // src/hooks/keyword-detector.mts
287
343
  var keyword_detector_exports = {};
288
344
  __export(keyword_detector_exports, {
@@ -698,6 +754,11 @@ async function main() {
698
754
  case "hook":
699
755
  await runHook(positionals.slice(1));
700
756
  break;
757
+ case "install": {
758
+ const { runInstall: runInstall2 } = await Promise.resolve().then(() => (init_install(), install_exports));
759
+ await runInstall2();
760
+ break;
761
+ }
701
762
  default:
702
763
  console.error(`Unknown subcommand: ${resolvedSubcommand}`);
703
764
  printUsage(true);
@@ -706,14 +767,14 @@ async function main() {
706
767
  }
707
768
  function printUsage(stderr = false) {
708
769
  const output = stderr ? console.error : console.log;
709
- output("Usage: omp [hud|version|psm|bench|hook] [--watch]");
770
+ output("Usage: omp [hud|install|version|psm|bench|hook] [--watch]");
710
771
  }
711
772
  async function printHud() {
712
773
  try {
713
774
  const { readFileSync: readFileSync3 } = await import("fs");
714
- const { join: join4 } = await import("path");
715
- const { homedir: homedir4 } = await import("os");
716
- const hudPath = join4(homedir4(), ".omp", "hud.line");
775
+ const { join: join5 } = await import("path");
776
+ const { homedir: homedir5 } = await import("os");
777
+ const hudPath = join5(homedir5(), ".omp", "hud.line");
717
778
  const line = readFileSync3(hudPath, "utf-8").trim();
718
779
  console.log(line);
719
780
  } catch {