oh-my-agent 7.22.0 β†’ 7.23.1

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.
Files changed (3) hide show
  1. package/README.md +10 -6
  2. package/bin/cli.js +3 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -53,12 +53,16 @@ Pick a preset and you're ready:
53
53
 
54
54
  | Preset | What You Get |
55
55
  |--------|-------------|
56
- | ✨ All | Every agent and skill |
57
- | 🌐 Fullstack | architecture + frontend + backend + db + pm + qa + debug + brainstorm + scm |
58
- | 🎨 Frontend | architecture + frontend + pm + qa + debug + brainstorm + scm |
59
- | βš™οΈ Backend | architecture + backend + db + pm + qa + debug + brainstorm + scm |
60
- | πŸ“± Mobile | architecture + mobile + pm + qa + debug + brainstorm + scm |
61
- | πŸš€ DevOps | architecture + tf-infra + dev-workflow + pm + qa + debug + brainstorm + scm |
56
+ | **All** | **Every agent and skill** |
57
+ | Backend | architecture + backend + brainstorm + db + debug + dev-workflow + pm + qa + scm |
58
+ | Content | academic-writer + design + image + scm + translator + voice |
59
+ | DevOps | architecture + brainstorm + debug + dev-workflow + observability + pm + qa + scm + tf-infra |
60
+ | Frontend | architecture + brainstorm + debug + design + frontend + pm + qa + scm |
61
+ | Fullstack | architecture + backend + brainstorm + db + debug + design + dev-workflow + frontend + mobile + pm + qa + scm + tf-infra |
62
+ | Fullstack Mobile | architecture + backend + brainstorm + db + debug + design + dev-workflow + mobile + pm + qa + scm |
63
+ | Fullstack Web | architecture + backend + brainstorm + db + debug + design + dev-workflow + frontend + pm + qa + scm |
64
+ | Mobile | architecture + brainstorm + debug + mobile + pm + qa + scm |
65
+ | Research | academic-writer + hwp + market + pdf + scholar + scm + search + translator |
62
66
 
63
67
  ## Works With Every Agent
64
68
 
package/bin/cli.js CHANGED
@@ -1006,7 +1006,7 @@ merge: git -C ${JSON.stringify($.path)} log --oneline; git merge ${$.branch}
1006
1006
  discard: git worktree remove ${JSON.stringify($.path)} --force && git branch -D ${$.branch}`}var kl2=["refactor","architecture","cross-cutting","migration","redesign","overhaul","restructure","rewrite"];function G22($,z,G){let J=$.toLowerCase(),U=kl2.some((Q)=>J.includes(Q));if(z>=5||G>=3||U)return"Complex";if($.length<200&&z<=2&&G<=1&&!U)return"Simple";return"Medium"}function Hl2($,z){let G=z?.acCount??3,J=z?.filesInScope??2;return G22($,G,J)}var Bl2=".serena/memories";function Al2($=process.cwd()){let z=XK.join($,Bl2);try{if(!S3.existsSync(z))S3.mkdirSync(z,{recursive:!0})}catch(G){console.warn(`[spawn] Could not pre-create memories dir ${z}: ${String(G)}`)}}async function J22($,z,G,J,U,K,X){let Q=null;if(X==="worktree")Q=$22(G,$),console.log(V3.default.blue(`[${$}] Isolated worktree: ${Q.path} (branch ${Q.branch})`));else if(X&&X!=="none")throw Error(`Unknown --isolation mode: ${JSON.stringify(X)}. Supported: worktree`);let Z=Q?Q.path:J==="."?XV($):J,j=XK.resolve(Z);if(!S3.existsSync(j))S3.mkdirSync(j,{recursive:!0}),console.log(V3.default.dim(`[${$}] Created workspace: ${j}`));else if(!Q&&Z!==J)console.log(V3.default.blue(`[${$}] Auto-detected workspace: ${Z}`));let Y=XK.join(tw(),`subagent-${G}-${$}.log`),W=XK.join(tw(),`subagent-${G}-${$}.pid`);Al2(process.cwd());let L=GV(z),k=Hl2(L,K);console.log(V3.default.dim(` Difficulty: ${k}`));try{let c=de(process.cwd());if(c!==null){let n=re(G,c);if(n.exceeded){let t=se(n);throw console.error(V3.default.red(`[${$}] ${t}`)),Error(`[session-cost] Quota cap exceeded for session ${G}: ${n.reason} (current: ${n.current}, limit: ${n.limit})`)}}}catch(c){if(c instanceof Error&&c.message.startsWith("[session-cost]"))throw c;console.warn(`[${$}] session-cost checkCap error (non-fatal): ${String(c)}`)}let{vendor:H,config:B}=zK($,U),A=JV(H,process.cwd()),V=A?`${L}
1007
1007
 
1008
1008
  ${A}`:L,F=B?.vendors?.[H]||{},N=S3.openSync(Y,"w");console.log(V3.default.blue(`[${$}] Spawning subagent...`)),console.log(V3.default.dim(` Vendor: ${H}`)),console.log(V3.default.dim(` Workspace: ${j}`)),console.log(V3.default.dim(` Log: ${Y}`));let O=zV(H,F.prompt_flag),q=KV($,H,F,O,V),{command:I,args:D,env:M}=q.invocation;console.log(V3.default.dim(` Dispatch: ${q.mode} (${q.runtimeVendor} -> ${q.targetVendor}, ${q.reason})`));let T=Ll2(I,D,{cwd:j,stdio:["ignore",N,N],detached:!1,env:M});if(!T.pid)console.error(V3.default.red(`[${$}] Failed to spawn process`)),process.exit(1);S3.writeFileSync(W,T.pid.toString()),console.log(V3.default.green(`[${$}] Started with PID ${T.pid}`));let i=()=>{try{if(S3.existsSync(W))S3.unlinkSync(W);if(S3.existsSync(Y))S3.unlinkSync(Y)}catch{}},h=()=>{if(T.pid&&NG(T.pid))process.kill(T.pid);y(),i(),process.exit()},y=JK(h,h);T.on("exit",(c)=>{if(y(),console.log(V3.default.blue(`[${$}] Exited with code ${c}`)),c!==0&&S3.existsSync(Y)){let n=S3.readFileSync(Y,"utf-8").trim();if(n)console.log(V3.default.red(`[${$}] Log output:`)),console.log(n)}try{pe(G,{vendor:H,agentId:$,tokens:Math.ceil(V.length/4),estimatedCostNote:`difficulty:${k}`})}catch(n){console.warn(`[${$}] session-cost recordUsage error (non-fatal): ${String(n)}`)}if(Q){console.log(V3.default.blue(`[${$}] Worktree retained for review:`));for(let n of z22(Q).split(`
1009
- `))console.log(V3.default.dim(` ${n}`))}i(),process.exit(c??0)})}async function U22($,z,G=process.cwd()){let J={};for(let U of z){let K=XK.join(G,".serena","memories",`result-${U}.md`),X=XK.join(tw(),`subagent-${$}-${U}.pid`);if(S3.existsSync(K)){let Z=S3.readFileSync(K,"utf-8").match(/^## Status:\s*(\S+)/m);J[U]=Z?.[1]?Z[1]:"completed"}else if(S3.existsSync(X)){let Q=S3.readFileSync(X,"utf-8").trim(),Z=Number.parseInt(Q,10);J[U]=!Number.isNaN(Z)&&NG(Z)?"running":"crashed"}else J[U]="crashed"}for(let[U,K]of Object.entries(J))console.log(`${U}:${K}`)}function K22($){$.command("agent:spawn <agent-id> <prompt> <session-id>").description("Spawn a subagent (prompt can be inline text or a file path)").option("-m, --model <vendor>","CLI vendor override (gemini/claude/codex/cursor/qwen)").option("-w, --workspace <path>","Working directory for the agent (auto-detected if omitted)").option("--isolation <mode>","Isolation mode: 'worktree' creates a git worktree per spawn (default: none)").action(Y5(async(z,G,J,U)=>{await J22(z,G,J,U.workspace||".",U.model,void 0,U.isolation)})),$.command("agent:status <session-id> [agent-ids...]").description("Check status of subagents").option("-r, --root <path>","Root path for memory checks",process.cwd()).action(Y5(async(z,G,J)=>{await U22(z,G,J.root)})),$.command("agent:parallel [tasks...]").description("Run multiple sub-agents in parallel").option("-m, --model <vendor>","CLI vendor override (gemini/claude/codex/cursor/qwen)").option("-i, --inline","Inline mode: specify tasks as agent:task arguments").option("--no-wait","Don't wait for completion (background mode)").action(Y5(async(z,G)=>{await Se(z,{vendor:G.model,inline:G.inline,noWait:!G.wait})})),$.command("agent:review").description("Run code review using external CLI (codex/claude/gemini)").option("-m, --model <vendor>","CLI vendor (codex/claude/gemini)").option("-p, --prompt <prompt>","Custom review prompt").option("-w, --workspace <path>","Working directory (default: current)").option("--no-uncommitted","Review committed changes only").action(Y5(async(z)=>{await he({prompt:z.prompt,model:z.model,workspace:z.workspace,uncommitted:z.uncommitted})}))}K7();var IG=p2(I4(),1);import{execSync as TC}from"node:child_process";import*as m2 from"node:fs";import{homedir as tc2}from"node:os";import{dirname as ec2,join as I5,relative as $n2,resolve as EC,sep as zn2}from"node:path";var a7={domain:[{name:"oma-architecture",desc:"Architecture specialist for software/system design, module and service boundaries, tradeoff analysis, and stakeholder synthesis. Uses context-aware methods such as diagnostic routing, design-twice comparison, ATAM-style risk analysis, CBAM-style prioritization, and ADR-style decision records."},{name:"oma-backend",desc:"Backend specialist for APIs, databases, authentication with clean architecture (Repository/Service/Router pattern). Use for API, endpoint, REST, database, server, migration, and auth work."},{name:"oma-db",desc:"Database specialist for SQL, NoSQL, and vector database modeling, schema design, normalization, indexing, transactions, integrity, concurrency control, backup, capacity planning, data standards, anti-pattern review, and compliance-aware database design. Use for database, schema, ERD, table design, document model, vector index design, RAG retrieval architecture, migration, query tuning, glossary, capacity estimation, backup strategy, database anti-pattern remediation work, and ISO 27001, ISO 27002, or ISO 22301-aware database recommendations."},{name:"oma-frontend",desc:"Frontend specialist for React, Next.js, TypeScript with FSD-lite architecture, shadcn/ui, and design system alignment. Use for UI, component, page, layout, CSS, Tailwind, and shadcn work."},{name:"oma-mobile",desc:"Mobile specialist for Flutter, React Native, and cross-platform mobile development. Use for mobile app, Flutter, Dart, iOS, Android, Riverpod, and widget work."}],design:[{name:"oma-design",desc:"AI design specialist skill with DESIGN.md management, anti-pattern enforcement, optional Stitch MCP integration, and component library guidance. Covers typography, color systems, motion design (motion/react, GSAP, Three.js), responsive-first layouts, and accessibility (WCAG 2.2)."}],coordination:[{name:"oma-brainstorm",desc:"Design-first ideation that explores user intent, constraints, and approaches before any planning or implementation. Use for brainstorming, ideation, exploring concepts, and evaluating approaches."},{name:"oma-coordination",desc:"Guide for coordinating PM, Frontend, Backend, Mobile, and QA agents on complex projects via CLI. Use for manual step-by-step coordination and workflow guidance."},{name:"oma-orchestrator",desc:"Automated multi-agent orchestrator that spawns CLI subagents in parallel, coordinates via MCP Memory, and monitors progress. Use for orchestration, parallel execution, and automated multi-agent workflows."},{name:"oma-pm",desc:"Product manager that decomposes requirements into actionable tasks with priorities and dependencies. Use for planning, requirements, specification, scope, prioritization, task breakdown, and ISO 21500, ISO 31000, or ISO 38500-aligned planning recommendations."},{name:"oma-qa",desc:"Quality assurance specialist for security, performance, accessibility, comprehensive testing, and quality standard alignment. Use for test, review, security audit, OWASP, coverage, lint work, and ISO/IEC 25010 or ISO/IEC 29119-aligned QA recommendations."}],utility:[{name:"oma-academic-writer",desc:"Academic writing specialist for publication-grade English prose. Drafts, revises, and audits essays, reports, analysis sections, executive summaries, conclusions, and literature reviews while enforcing sentence-structure variation, high-frequency academic verbs, calibrated hedging, and anti-AI stylistic compliance. USE for academic writing, essay polish, paragraph rewrite, prose revision against any rubric tier (HD/D/C, A/B/C, top-band/mid-band, etc.), anti-AI audit, reverse outlining, claim-evidence mapping, and rubric enforcement on assignments."},{name:"oma-debug",desc:"Bug diagnosis and fixing specialist - analyzes errors, identifies root causes, provides fixes, and writes regression tests. Use for bug, debug, error, crash, traceback, exception, and regression work."},{name:"oma-deepsec",desc:"Drive Vercel's `deepsec` agent-powered vulnerability scanner end-to-end: installing the `.deepsec/` workspace, bootstrapping `INFO.md`, running cost-aware `scan` / `process` / `triage` / `revalidate` / `export` passes, gating PRs with `process --diff`, writing custom matchers, and triaging findings. Use whenever the user mentions deepsec, asks an agent to scan a repo for vulnerabilities, runs into `pnpm deepsec` / `bunx deepsec` commands, wants a CI-based PR security review, sees a `.deepsec/` directory, or asks about `INFO.md` / matchers / `process --diff` / `revalidate`, even when the tool name is not spoken. Deepsec scans are expensive (a single full scan can cost hundreds to tens of thousands of dollars) so the skill exists in part to keep the user from getting surprised."},{name:"oma-docs",desc:"Verify documentation references against the current codebase and propose updates for diff-affected docs. Use to check if docs still match reality (broken file paths, CLI commands, config keys, env vars, scripts) and to surface docs that may need updating after code changes."},{name:"oma-hwp",desc:"Convert HWP / HWPX / HWPML files to Markdown using kordoc. Extracts text, headings, tables, lists, images, footnotes, and hyperlinks. Use for Korean word processor files (Hangul), government documents, and AI-ready data preparation."},{name:"oma-image",desc:"Multi-vendor AI image generation with authentication-aware parallel dispatch. Routes to Codex (gpt-image-2 via ChatGPT OAuth) and Pollinations (flux/zimage, free with signup). Gemini provider is present but disabled by default (requires billing). Use for image generation, image creation, visual asset generation, and AI art."},{name:"oma-market",desc:"Market research skill for pain-point extraction, trend detection, competitor positioning, and discovery across community sources (Reddit, HN, Bluesky, Mastodon, GitHub Issues, web). Routes via oma-search transport, deterministic CLI compute, intent-auto SWOT/Porter's 5F/PESTEL frameworks. Use for market research, pain point analysis, trend detection, competitor research, user complaints, voice-of-customer, μ‹œμž₯쑰사, μ‚¬μš©μž 페인, νŠΈλ Œλ“œ, κ²½μŸκ΅¬λ„."},{name:"oma-pdf",desc:"Convert PDF files to Markdown using opendataloader-pdf. Extracts text, tables, headings, lists, and images with correct reading order. Use for PDF parsing, PDF to Markdown conversion, document extraction, and AI-ready data preparation."},{name:"oma-recap",desc:"Analyze conversation histories from multiple AI tools (Claude, Codex, Gemini, Qwen, Cursor) and generate themed daily/period work summaries. Filter by date or time window."},{name:"oma-scholar",desc:"Scholarly research companion using Knows sidecar spec (.knows.yaml). Generates, validates, reviews, queries, and compares structured research-paper sidecars, and fetches them from knows.academy. Use for academic literature search, survey synthesis, paper authoring assistance, and peer review with token-efficient claim/evidence/relation access."},{name:"oma-scm",desc:"SCM (software configuration management) and Git: branching, merges, conflicts, worktrees, baselines, audit readiness, plus Conventional Commits and safe staging."},{name:"oma-search",desc:"Intent-based search router with trust scoring. Routes queries to optimal channels (Context7 docs, native web search, gh/glab code search, Serena local) and attaches domain trust labels. Use for search, find, lookup, reference, docs, code search, and web research."},{name:"oma-skill-creator",desc:"Create or update OMA skills in the SSL-lite human-readable format. Use when adding a new `.agents/skills/{skill-name}/SKILL.md`, converting an existing skill to the standardized Scheduling / Structural Flow / Logical Operations / References structure, or validating whether a skill has enough routing, execution, resource, and safety detail."},{name:"oma-translator",desc:"Context-aware translation that preserves tone, style, and natural word order. Use when translating UI strings, documentation, marketing copy, or any multilingual content. Infers register, domain, and style from the source text and surrounding codebase context."},{name:"oma-voice",desc:"Local-first text-to-speech and speech-to-text via the Voicebox MCP server. Generates speech from cloned or preset voice profiles for agent notifications, content voiceovers, and audio asset creation, and transcribes audio files for meeting notes or memos. Runs entirely on-device with no cloud, no API keys, no per-call cost. Use for voice generation, TTS, STT, transcription, voiceover, narration, dictation, audio asset work."}],infrastructure:[{name:"oma-dev-workflow",desc:"Use when setting up or optimizing developer workflows in a monorepo, managing mise tasks, git hooks, CI/CD pipelines, database migrations, or release automation. Invoke for development environment setup, build automation, testing workflows, and release coordination."},{name:"oma-observability",desc:"Intent-based observability + traceability router across layers, boundaries, and signals. Routes to vendor-specific skills via category taxonomy; owns transport tuning, meta-observability, incident forensics. Use for observability, traceability, telemetry, APM, RUM, metrics, logs, traces, profiles, SLO, incident forensics, tracing architecture work."},{name:"oma-tf-infra",desc:"Infrastructure-as-code specialist for multi-cloud provisioning using Terraform across any provider (AWS, GCP, Azure, Oracle Cloud). Use for terraform plan/apply, state management, compute, databases, storage, networking, IAM, OIDC, cost optimization, policy-as-code, ISO/IEC 42001 AI controls, ISO 22301 continuity, and ISO/IEC/IEEE 42010 architecture documentation."}]},m22={fullstack:["oma-architecture","oma-brainstorm","oma-design","oma-frontend","oma-backend","oma-db","oma-pm","oma-qa","oma-debug","oma-scm","oma-tf-infra","oma-dev-workflow"],frontend:["oma-architecture","oma-brainstorm","oma-design","oma-frontend","oma-pm","oma-qa","oma-debug","oma-scm"],backend:["oma-architecture","oma-brainstorm","oma-backend","oma-db","oma-pm","oma-qa","oma-debug","oma-scm","oma-dev-workflow"],mobile:["oma-architecture","oma-brainstorm","oma-mobile","oma-pm","oma-qa","oma-debug","oma-scm"],devops:["oma-architecture","oma-brainstorm","oma-tf-infra","oma-dev-workflow","oma-pm","oma-qa","oma-debug","oma-scm"],all:[...a7.domain,...a7.design,...a7.coordination,...a7.utility,...a7.infrastructure].map(($)=>$.name)};import*as ZK from"node:fs";import{join as kf5,sep as f22}from"node:path";function Y9($){return f22==="/"?$:$.split(f22).join("/")}function G8($){try{if(!ZK.lstatSync($).isDirectory())ZK.unlinkSync($)}catch{}}var Qc2={serena:{command:"serena",args:["start-mcp-server","--context","ide","--project","."],env:{SERENA_LOG_LEVEL:"info"}}};function l22($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function c22($){let z=l22($)?$:{},G=l22(z.mcpServers)?z.mcpServers:{};return z.mcpServers={...G,serena:{...Qc2.serena}},z}import*as u$ from"node:fs";import{dirname as Zc2,isAbsolute as jc2,resolve as Yc2}from"node:path";var n22=new Set;function d22($,z,G){if(process.platform!=="win32")return u$.symlinkSync($,z,G),"symlink";try{return u$.symlinkSync($,z,G),"symlink"}catch(U){if(!Wc2(U))throw U}let J=jc2($)?$:Yc2(Zc2(z),$);if(G==="dir")return u$.symlinkSync(J,z,"junction"),OC("junction"),"junction";try{return u$.linkSync(J,z),OC("hardlink"),"hardlink"}catch{return u$.copyFileSync(J,z),OC("copy"),"copy"}}function Wc2($){if(!$||typeof $!=="object")return!1;let z=$.code;return z==="EPERM"||z==="EACCES"}var kc2={symlink:"",junction:"note: using directory junctions because symlinks need admin or Developer Mode",hardlink:"note: using hardlinks because symlinks need admin or Developer Mode (content stays in sync via shared inode)",copy:"note: copying files because symlinks and hardlinks both failed (likely cross-volume) β€” re-run install after editing .agents/* to refresh"};function OC($){if(n22.has($))return;n22.add($);let z=kc2[$];if(z)console.warn(z)}import{existsSync as qC,mkdirSync as Hc2,readdirSync as Bc2,readFileSync as a22,writeFileSync as Ac2}from"node:fs";import{join as YK}from"node:path";var FV=p2(e3(),1);function Lc2($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function uC($){if($===void 0||$===null)return;if(Array.isArray($))return $.map((z)=>uC(z)).filter((z)=>z!==void 0);if(Lc2($))return Object.fromEntries(Object.entries($).map(([z,G])=>[z,uC(G)]).filter(([,z])=>z!==void 0));return $}function q$($){let z=$.trimStart();if(!z.startsWith("---"))return{frontmatter:{},body:$};let G=z.indexOf(`
1009
+ `))console.log(V3.default.dim(` ${n}`))}i(),process.exit(c??0)})}async function U22($,z,G=process.cwd()){let J={};for(let U of z){let K=XK.join(G,".serena","memories",`result-${U}.md`),X=XK.join(tw(),`subagent-${$}-${U}.pid`);if(S3.existsSync(K)){let Z=S3.readFileSync(K,"utf-8").match(/^## Status:\s*(\S+)/m);J[U]=Z?.[1]?Z[1]:"completed"}else if(S3.existsSync(X)){let Q=S3.readFileSync(X,"utf-8").trim(),Z=Number.parseInt(Q,10);J[U]=!Number.isNaN(Z)&&NG(Z)?"running":"crashed"}else J[U]="crashed"}for(let[U,K]of Object.entries(J))console.log(`${U}:${K}`)}function K22($){$.command("agent:spawn <agent-id> <prompt> <session-id>").description("Spawn a subagent (prompt can be inline text or a file path)").option("-m, --model <vendor>","CLI vendor override (gemini/claude/codex/cursor/qwen)").option("-w, --workspace <path>","Working directory for the agent (auto-detected if omitted)").option("--isolation <mode>","Isolation mode: 'worktree' creates a git worktree per spawn (default: none)").action(Y5(async(z,G,J,U)=>{await J22(z,G,J,U.workspace||".",U.model,void 0,U.isolation)})),$.command("agent:status <session-id> [agent-ids...]").description("Check status of subagents").option("-r, --root <path>","Root path for memory checks",process.cwd()).action(Y5(async(z,G,J)=>{await U22(z,G,J.root)})),$.command("agent:parallel [tasks...]").description("Run multiple sub-agents in parallel").option("-m, --model <vendor>","CLI vendor override (gemini/claude/codex/cursor/qwen)").option("-i, --inline","Inline mode: specify tasks as agent:task arguments").option("--no-wait","Don't wait for completion (background mode)").action(Y5(async(z,G)=>{await Se(z,{vendor:G.model,inline:G.inline,noWait:!G.wait})})),$.command("agent:review").description("Run code review using external CLI (codex/claude/gemini)").option("-m, --model <vendor>","CLI vendor (codex/claude/gemini)").option("-p, --prompt <prompt>","Custom review prompt").option("-w, --workspace <path>","Working directory (default: current)").option("--no-uncommitted","Review committed changes only").action(Y5(async(z)=>{await he({prompt:z.prompt,model:z.model,workspace:z.workspace,uncommitted:z.uncommitted})}))}K7();var IG=p2(I4(),1);import{execSync as TC}from"node:child_process";import*as m2 from"node:fs";import{homedir as tc2}from"node:os";import{dirname as ec2,join as I5,relative as $n2,resolve as EC,sep as zn2}from"node:path";var a7={domain:[{name:"oma-architecture",desc:"Architecture specialist for software/system design, module and service boundaries, tradeoff analysis, and stakeholder synthesis. Uses context-aware methods such as diagnostic routing, design-twice comparison, ATAM-style risk analysis, CBAM-style prioritization, and ADR-style decision records."},{name:"oma-backend",desc:"Backend specialist for APIs, databases, authentication with clean architecture (Repository/Service/Router pattern). Use for API, endpoint, REST, database, server, migration, and auth work."},{name:"oma-db",desc:"Database specialist for SQL, NoSQL, and vector database modeling, schema design, normalization, indexing, transactions, integrity, concurrency control, backup, capacity planning, data standards, anti-pattern review, and compliance-aware database design. Use for database, schema, ERD, table design, document model, vector index design, RAG retrieval architecture, migration, query tuning, glossary, capacity estimation, backup strategy, database anti-pattern remediation work, and ISO 27001, ISO 27002, or ISO 22301-aware database recommendations."},{name:"oma-frontend",desc:"Frontend specialist for React, Next.js, TypeScript with FSD-lite architecture, shadcn/ui, and design system alignment. Use for UI, component, page, layout, CSS, Tailwind, and shadcn work."},{name:"oma-mobile",desc:"Mobile specialist for Flutter, React Native, and cross-platform mobile development. Use for mobile app, Flutter, Dart, iOS, Android, Riverpod, and widget work."}],design:[{name:"oma-design",desc:"AI design specialist skill with DESIGN.md management, anti-pattern enforcement, optional Stitch MCP integration, and component library guidance. Covers typography, color systems, motion design (motion/react, GSAP, Three.js), responsive-first layouts, and accessibility (WCAG 2.2)."}],coordination:[{name:"oma-brainstorm",desc:"Design-first ideation that explores user intent, constraints, and approaches before any planning or implementation. Use for brainstorming, ideation, exploring concepts, and evaluating approaches."},{name:"oma-coordination",desc:"Guide for coordinating PM, Frontend, Backend, Mobile, and QA agents on complex projects via CLI. Use for manual step-by-step coordination and workflow guidance."},{name:"oma-orchestrator",desc:"Automated multi-agent orchestrator that spawns CLI subagents in parallel, coordinates via MCP Memory, and monitors progress. Use for orchestration, parallel execution, and automated multi-agent workflows."},{name:"oma-pm",desc:"Product manager that decomposes requirements into actionable tasks with priorities and dependencies. Use for planning, requirements, specification, scope, prioritization, task breakdown, and ISO 21500, ISO 31000, or ISO 38500-aligned planning recommendations."},{name:"oma-qa",desc:"Quality assurance specialist for security, performance, accessibility, comprehensive testing, and quality standard alignment. Use for test, review, security audit, OWASP, coverage, lint work, and ISO/IEC 25010 or ISO/IEC 29119-aligned QA recommendations."}],utility:[{name:"oma-academic-writer",desc:"Academic writing specialist for publication-grade English prose. Drafts, revises, and audits essays, reports, analysis sections, executive summaries, conclusions, and literature reviews while enforcing sentence-structure variation, high-frequency academic verbs, calibrated hedging, and anti-AI stylistic compliance. USE for academic writing, essay polish, paragraph rewrite, prose revision against any rubric tier (HD/D/C, A/B/C, top-band/mid-band, etc.), anti-AI audit, reverse outlining, claim-evidence mapping, and rubric enforcement on assignments."},{name:"oma-debug",desc:"Bug diagnosis and fixing specialist - analyzes errors, identifies root causes, provides fixes, and writes regression tests. Use for bug, debug, error, crash, traceback, exception, and regression work."},{name:"oma-deepsec",desc:"Drive Vercel's `deepsec` agent-powered vulnerability scanner end-to-end: installing the `.deepsec/` workspace, bootstrapping `INFO.md`, running cost-aware `scan` / `process` / `triage` / `revalidate` / `export` passes, gating PRs with `process --diff`, writing custom matchers, and triaging findings. Use whenever the user mentions deepsec, asks an agent to scan a repo for vulnerabilities, runs into `pnpm deepsec` / `bunx deepsec` commands, wants a CI-based PR security review, sees a `.deepsec/` directory, or asks about `INFO.md` / matchers / `process --diff` / `revalidate`, even when the tool name is not spoken. Deepsec scans are expensive (a single full scan can cost hundreds to tens of thousands of dollars) so the skill exists in part to keep the user from getting surprised."},{name:"oma-docs",desc:"Verify documentation references against the current codebase and propose updates for diff-affected docs. Use to check if docs still match reality (broken file paths, CLI commands, config keys, env vars, scripts) and to surface docs that may need updating after code changes."},{name:"oma-hwp",desc:"Convert HWP / HWPX / HWPML files to Markdown using kordoc. Extracts text, headings, tables, lists, images, footnotes, and hyperlinks. Use for Korean word processor files (Hangul), government documents, and AI-ready data preparation."},{name:"oma-image",desc:"Multi-vendor AI image generation with authentication-aware parallel dispatch. Routes to Codex (gpt-image-2 via ChatGPT OAuth) and Pollinations (flux/zimage, free with signup). Gemini provider is present but disabled by default (requires billing). Use for image generation, image creation, visual asset generation, and AI art."},{name:"oma-market",desc:"Market research skill for pain-point extraction, trend detection, competitor positioning, and discovery across community sources (Reddit, HN, Bluesky, Mastodon, GitHub Issues, web). Routes via oma-search transport, deterministic CLI compute, intent-auto SWOT/Porter's 5F/PESTEL frameworks. Use for market research, pain point analysis, trend detection, competitor research, user complaints, voice-of-customer, μ‹œμž₯쑰사, μ‚¬μš©μž 페인, νŠΈλ Œλ“œ, κ²½μŸκ΅¬λ„."},{name:"oma-pdf",desc:"Convert PDF files to Markdown using opendataloader-pdf. Extracts text, tables, headings, lists, and images with correct reading order. Use for PDF parsing, PDF to Markdown conversion, document extraction, and AI-ready data preparation."},{name:"oma-recap",desc:"Analyze conversation histories from multiple AI tools (Claude, Codex, Gemini, Qwen, Cursor) and generate themed daily/period work summaries. Filter by date or time window."},{name:"oma-scholar",desc:"Scholarly research companion using Knows sidecar spec (.knows.yaml). Generates, validates, reviews, queries, and compares structured research-paper sidecars, and fetches them from knows.academy. Use for academic literature search, survey synthesis, paper authoring assistance, and peer review with token-efficient claim/evidence/relation access."},{name:"oma-scm",desc:"SCM (software configuration management) and Git: branching, merges, conflicts, worktrees, baselines, audit readiness, plus Conventional Commits and safe staging."},{name:"oma-search",desc:"Intent-based search router with trust scoring. Routes queries to optimal channels (Context7 docs, native web search, gh/glab code search, Serena local) and attaches domain trust labels. Use for search, find, lookup, reference, docs, code search, and web research."},{name:"oma-skill-creator",desc:"Create or update OMA skills in the SSL-lite human-readable format. Use when adding a new `.agents/skills/{skill-name}/SKILL.md`, converting an existing skill to the standardized Scheduling / Structural Flow / Logical Operations / References structure, or validating whether a skill has enough routing, execution, resource, and safety detail."},{name:"oma-translator",desc:"Context-aware translation that preserves tone, style, and natural word order. Use when translating UI strings, documentation, marketing copy, or any multilingual content. Infers register, domain, and style from the source text and surrounding codebase context."},{name:"oma-voice",desc:"Local-first text-to-speech and speech-to-text via the Voicebox MCP server. Generates speech from cloned or preset voice profiles for agent notifications, content voiceovers, and audio asset creation, and transcribes audio files for meeting notes or memos. Runs entirely on-device with no cloud, no API keys, no per-call cost. Use for voice generation, TTS, STT, transcription, voiceover, narration, dictation, audio asset work."}],infrastructure:[{name:"oma-dev-workflow",desc:"Use when setting up or optimizing developer workflows in a monorepo, managing mise tasks, git hooks, CI/CD pipelines, database migrations, or release automation. Invoke for development environment setup, build automation, testing workflows, and release coordination."},{name:"oma-observability",desc:"Intent-based observability + traceability router across layers, boundaries, and signals. Routes to vendor-specific skills via category taxonomy; owns transport tuning, meta-observability, incident forensics. Use for observability, traceability, telemetry, APM, RUM, metrics, logs, traces, profiles, SLO, incident forensics, tracing architecture work."},{name:"oma-tf-infra",desc:"Infrastructure-as-code specialist for multi-cloud provisioning using Terraform across any provider (AWS, GCP, Azure, Oracle Cloud). Use for terraform plan/apply, state management, compute, databases, storage, networking, IAM, OIDC, cost optimization, policy-as-code, ISO/IEC 42001 AI controls, ISO 22301 continuity, and ISO/IEC/IEEE 42010 architecture documentation."}]},m22={fullstack:["oma-architecture","oma-brainstorm","oma-design","oma-frontend","oma-backend","oma-mobile","oma-db","oma-pm","oma-qa","oma-debug","oma-scm","oma-tf-infra","oma-dev-workflow"],"fullstack-web":["oma-architecture","oma-brainstorm","oma-design","oma-frontend","oma-backend","oma-db","oma-pm","oma-qa","oma-debug","oma-scm","oma-dev-workflow"],"fullstack-mobile":["oma-architecture","oma-brainstorm","oma-design","oma-mobile","oma-backend","oma-db","oma-pm","oma-qa","oma-debug","oma-scm","oma-dev-workflow"],frontend:["oma-architecture","oma-brainstorm","oma-design","oma-frontend","oma-pm","oma-qa","oma-debug","oma-scm"],backend:["oma-architecture","oma-brainstorm","oma-backend","oma-db","oma-pm","oma-qa","oma-debug","oma-scm","oma-dev-workflow"],mobile:["oma-architecture","oma-brainstorm","oma-mobile","oma-pm","oma-qa","oma-debug","oma-scm"],devops:["oma-architecture","oma-brainstorm","oma-tf-infra","oma-dev-workflow","oma-observability","oma-pm","oma-qa","oma-debug","oma-scm"],research:["oma-scholar","oma-market","oma-pdf","oma-hwp","oma-academic-writer","oma-search","oma-translator","oma-scm"],content:["oma-design","oma-image","oma-voice","oma-academic-writer","oma-translator","oma-scm"],all:[...a7.domain,...a7.design,...a7.coordination,...a7.utility,...a7.infrastructure].map(($)=>$.name)};import*as ZK from"node:fs";import{join as kf5,sep as f22}from"node:path";function Y9($){return f22==="/"?$:$.split(f22).join("/")}function G8($){try{if(!ZK.lstatSync($).isDirectory())ZK.unlinkSync($)}catch{}}var Qc2={serena:{command:"serena",args:["start-mcp-server","--context","ide","--project","."],env:{SERENA_LOG_LEVEL:"info"}}};function l22($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function c22($){let z=l22($)?$:{},G=l22(z.mcpServers)?z.mcpServers:{};return z.mcpServers={...G,serena:{...Qc2.serena}},z}import*as u$ from"node:fs";import{dirname as Zc2,isAbsolute as jc2,resolve as Yc2}from"node:path";var n22=new Set;function d22($,z,G){if(process.platform!=="win32")return u$.symlinkSync($,z,G),"symlink";try{return u$.symlinkSync($,z,G),"symlink"}catch(U){if(!Wc2(U))throw U}let J=jc2($)?$:Yc2(Zc2(z),$);if(G==="dir")return u$.symlinkSync(J,z,"junction"),OC("junction"),"junction";try{return u$.linkSync(J,z),OC("hardlink"),"hardlink"}catch{return u$.copyFileSync(J,z),OC("copy"),"copy"}}function Wc2($){if(!$||typeof $!=="object")return!1;let z=$.code;return z==="EPERM"||z==="EACCES"}var kc2={symlink:"",junction:"note: using directory junctions because symlinks need admin or Developer Mode",hardlink:"note: using hardlinks because symlinks need admin or Developer Mode (content stays in sync via shared inode)",copy:"note: copying files because symlinks and hardlinks both failed (likely cross-volume) β€” re-run install after editing .agents/* to refresh"};function OC($){if(n22.has($))return;n22.add($);let z=kc2[$];if(z)console.warn(z)}import{existsSync as qC,mkdirSync as Hc2,readdirSync as Bc2,readFileSync as a22,writeFileSync as Ac2}from"node:fs";import{join as YK}from"node:path";var FV=p2(e3(),1);function Lc2($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function uC($){if($===void 0||$===null)return;if(Array.isArray($))return $.map((z)=>uC(z)).filter((z)=>z!==void 0);if(Lc2($))return Object.fromEntries(Object.entries($).map(([z,G])=>[z,uC(G)]).filter(([,z])=>z!==void 0));return $}function q$($){let z=$.trimStart();if(!z.startsWith("---"))return{frontmatter:{},body:$};let G=z.indexOf(`
1010
1010
  ---`,3);if(G===-1)return{frontmatter:{},body:$};let J=z.slice(3,G).trim(),U=z.slice(G+4);try{let K=FV.parse(J);return{frontmatter:K&&typeof K==="object"?K:{},body:U}}catch{return{frontmatter:{},body:U}}}function jK($,z){let G=Object.fromEntries(Object.entries($).map(([U,K])=>[U,uC(K)]).filter(([,U])=>U!==void 0));if(Object.keys(G).length===0)return`---
1011
1011
  ---
1012
1012
 
@@ -1260,7 +1260,7 @@ ${UX.stringify(A)}`;if(V02(G,V),z.push(`.agents/oma-config.yaml updated (model_p
1260
1260
  `),!0}function V35($){let z=$0($,".cursor","mcp.json"),G=!1;try{G=Y35(z).isSymbolicLink()}catch{return!1}if(!G)return!1;let J=$0($,".agents","mcp.json");if(!kW(J))return!1;let U;try{U=JSON.parse(LW(J,"utf-8"))}catch{return!1}if(!z0(U))return!1;let X={mcpServers:{...z0(U.mcpServers)?U.mcpServers:{},serena:{command:"serena",args:["start-mcp-server","--context","ide","--project","."],env:{SERENA_LOG_LEVEL:"info"}}}};return W35(z),HW(z,`${JSON.stringify(X,null,2)}
1261
1261
  `),!0}var q02={name:"009-serena-uv-tool",up($){let z=[];if(B35($0($,".codex","config.toml")))z.push(".codex/config.toml (Serena uvx β†’ uv tool install)");if($N($0($,".qwen","settings.json"),"mcpServers","ide"))z.push(".qwen/settings.json (Serena uvx β†’ uv tool install)");if($N($0($,".gemini","settings.json"),"mcpServers","ide"))z.push(".gemini/settings.json (Serena uvx β†’ uv tool install)");if(A35($))z.push(".gemini/settings.json (bridge URL β†’ direct stdio)");if($N($0($,".agents","mcp.json"),"mcpServers","claude-code"))z.push(".agents/mcp.json (Serena uvx β†’ uv tool install)");if(V35($))z.push(".cursor/mcp.json (symlink β†’ regular file, --context=ide)");let G=$0($,".mcp.json");if(kW(G)){let J={};try{J=JSON.parse(LW(G,"utf-8"))}catch{J={}}if(tF(J))HW(G,`${JSON.stringify(eF(J),null,2)}
1262
1262
  `),z.push(".mcp.json (Claude Code project MCP refreshed)")}if($N($0(k35(),".claude.json"),"mcpServers","claude-code"))z.push("~/.claude.json (Serena uvx β†’ uv tool install)");return z}};import{copyFileSync as F35,existsSync as N35,readFileSync as O35,writeFileSync as u35}from"node:fs";import{join as q35}from"node:path";var M02={"claude-only":"claude","codex-only":"codex","gemini-only":"gemini","qwen-only":"qwen","cursor-only":"cursor",antigravity:"mixed"},M35=new Set(Object.keys(M02)),D02={name:"010-rename-preset-keys",up($){let z=[],G=q35($,".agents","oma-config.yaml");if(!N35(G))return z;let J;try{J=O35(G,"utf-8")}catch{return z}let U=J.match(/^(model_preset:\s*)([A-Za-z0-9_-]+)([ \t]*(?:#[^\n]*)?)$/m);if(!U)return z;let K=U[2];if(!K)return z;if(!M35.has(K))return z;let X=M02[K];if(!X)return z;let Q=`${G}.bak`;try{F35(G,Q),z.push("Backed up .agents/oma-config.yaml β†’ .agents/oma-config.yaml.bak")}catch{}let Z=J.replace(/^(model_preset:\s*)([A-Za-z0-9_-]+)([ \t]*(?:#[^\n]*)?)$/m,(j,Y,W,L)=>`${Y}${X}${L}`);return u35(G,Z,"utf-8"),z.push(`.agents/oma-config.yaml: model_preset "${K}" β†’ "${X}"`),z}};var D35=[r82,z02,U02,X02,Z02,j02,H02,F02,q02,D02];function nG($){let z=[];for(let G of D35)z.push(...G.up($));return z}var P35={en:"English",ko:"ν•œκ΅­μ–΄",ja:"ζ—₯本θͺž",zh:"δΈ­ζ–‡",vi:"TiαΊΏng Việt",de:"Deutsch",es:"EspaΓ±ol",fr:"FranΓ§ais",nl:"Nederlands",pl:"Polski",pt:"PortuguΓͺs",ru:"Русский"};function b35($){let z=F9($,"docs"),G=["en"];if(G0(z))for(let J of T02(z)){let U=J.match(/^README\.(.+)\.md$/);if(U?.[1])G.push(U[1])}return G.map((J)=>({value:J,label:P35[J]??J}))}function w35($){let z=F9($,".agents","oma-config.yaml");if(!G0(z))return null;try{return dG(z,"utf-8").match(/^language:\s*([A-Za-z-]+)/m)?.[1]??null}catch{return null}}function C35($){if(!G0($))return;let z;try{z=T02($,{withFileTypes:!0,encoding:"utf-8"})}catch{return}for(let G of z){if(!G.isSymbolicLink())continue;let J=F9($,G.name),U;try{U=T35(J)}catch{continue}let K=v35($,U),X;try{E35(K),X=!0}catch{X=!1}if(!X)try{R35(J),console.log(`cleaned broken symlink: ${J}`)}catch{}}}function R02($={}){if($.yes)return!0;if(process.env.OMA_YES==="1"||process.env.OMA_YES==="true")return!0;return!1}function _35($={}){if(R02($))return!0;if(process.env.CI==="true"||process.env.CI==="1")return!0;return!1}function S35($){let z=F9($,".agents","oma-config.yaml");if(!G0(z))return null;try{return dG(z,"utf-8").match(/^model_preset:\s*([A-Za-z0-9_-]+)/m)?.[1]??null}catch{return null}}async function zN($={}){let z=_35($),G=R02($);if(console.clear(),d4(l4.default.bgMagenta(l4.default.white(" \uD83D\uDEF8 oh-my-agent "))),z)$4.info(l4.default.dim("Non-interactive mode β€” using defaults."));let J=nG(process.cwd());if(J.length>0)G5(J.map((y)=>`${l4.default.green("βœ“")} ${y}`).join(`
1263
- `),"Migration");if(!z)await gF(process.cwd());let U=E6();U.start("Downloading...");let K,X;try{let y=await pK();K=y.dir,X=y.cleanup}catch(y){U.stop("Download failed"),$4.error(y instanceof Error?y.message:String(y)),process.exit(1)}U.stop("Downloaded!");let Q=b35(K),Z=w35(process.cwd()),j=Q.some((y)=>y.value===Z)?Z:"en",Y=z?j:await n8({message:"Response language?",options:Q,initialValue:j});if(Y4(Y))X(),n1("Cancelled."),process.exit(0);let W=[{value:"claude",label:"Claude Code only",hint:"Claude Max subscription holders"},{value:"codex",label:"Codex CLI only",hint:"ChatGPT Plus/Pro subscription holders"},{value:"gemini",label:"Gemini CLI only",hint:"Google AI Pro subscription holders"},{value:"qwen",label:"Qwen Code only",hint:"Qwen Code subscription holders"},{value:"mixed",label:"Mixed (Antigravity IDE)",hint:"Claude orchestrator + cross-vendor subagents"}],L=S35(process.cwd()),k=W.some((y)=>y.value===L)?L:"claude",H=z?k:await n8({message:"Model preset?",options:W,initialValue:k});if(Y4(H))X(),n1("Cancelled."),process.exit(0);let B=z?"all":await n8({message:"What type of project?",options:[{value:"all",label:"All",hint:"Install everything"},{value:"fullstack",label:"Fullstack",hint:"Frontend + Backend + PM + QA"},{value:"frontend",label:"Frontend",hint:"React/Next.js"},{value:"backend",label:"Backend",hint:"Python, Node.js, Rust, ..."},{value:"mobile",label:"Mobile",hint:"Flutter/Dart"},{value:"devops",label:"DevOps",hint:"Terraform + CI/CD + Workflows"},{value:"custom",label:"Custom",hint:"Choose skills"}]});if(Y4(B))n1("Cancelled."),process.exit(0);let A;if(B==="custom"){let y=qG(),c=await LY({message:"Select skills:",options:y.map((n)=>({value:n.name,label:n.name,hint:n.desc})),required:!0});if(Y4(c))n1("Cancelled."),process.exit(0);A=c}else A=m22[B]??[];let V=process.cwd(),F={};if(A.includes("oma-backend")){let y=z?"python":await n8({message:"Backend language?",options:[{value:"python",label:"\uD83D\uDC0D Python",hint:"FastAPI/SQLAlchemy (default)"},{value:"node",label:"\uD83D\uDFE2 Node.js",hint:"NestJS/Hono + Prisma/Drizzle"},{value:"rust",label:"\uD83E\uDD80 Rust",hint:"Axum/Actix-web"},{value:"other",label:"\uD83D\uDD27 Other / Auto-detect",hint:"Configure later with /stack-set"}],initialValue:"python"});if(Y4(y))n1("Cancelled."),process.exit(0);if(y!=="other")F["oma-backend"]=y}let N=process.platform!=="win32"&&!process.env.CI,O=[{value:"claude",label:"Claude Code",hint:"hooks + settings + CLAUDE.md"},{value:"codex",label:"Codex CLI",hint:"hooks + plugin"},{value:"copilot",label:"GitHub Copilot",hint:"skill symlinks + .github/prompts/ wrappers"},{value:"cursor",label:"Cursor",hint:".cursor/rules/ export + prompt hooks"},{value:"gemini",label:"Gemini CLI",hint:"hooks + Serena MCP"},...N?[{value:"hermes",label:"Hermes Agent",hint:"skills only β€” workflows N/A, HOME-shared (no per-project isolation)"}]:[],{value:"qwen",label:"Qwen Code",hint:"hooks + settings"}],q=O.filter((y)=>{let c=h8[y.value];return!c||c.base!=="home"}).map((y)=>y.value),I=z?q:await LY({message:"CLI tools to configure:",options:O,initialValues:q,required:!0});if(Y4(I))n1("Cancelled."),process.exit(0);let D=I,M=D.filter(NK),T=Object.keys(h8),i=D.filter((y)=>T.includes(y)),h=[];for(let y of i){if(OK(y)){if(z){$4.info(l4.default.dim(`Skipped ${y} export (HOME write requires -y opt-in).`));continue}let c=await F3({message:`${y} export writes to HOME (${l4.default.cyan(B52(y))}). Proceed?`,initialValue:!1});if(Y4(c))X(),n1("Cancelled."),process.exit(0);if(!c){$4.info(l4.default.dim(`Skipped ${y} export.`));continue}}h.push(y)}U.start("Installing skills...");try{try{let n=[".claude/skills",".codex/skills",".gemini/skills",".github/skills"];for(let a of n)C35(F9(V,a));if(MV(K,V),Z52(K,V),D.includes("codex"))FK(K,V);if(D.includes("copilot"))DV(K,V);W52(K,V),k52(K,V,!1);for(let a of A)U.message(`Installing ${l4.default.cyan(a)}...`),qV(K,a,V,F[a]);U.stop("Skills installed!"),U.start("Installing vendor adaptations..."),AK(K,V,M);let t={telemetry:$X(V)};if(D.includes("claude")){let a=F9(V,".claude","settings.json"),E={};if(G0(a))try{E=JSON.parse(dG(a,"utf-8"))}catch{E={}}if(fF(E,t))lF(E,t),BW(a,`${JSON.stringify(E,null,2)}
1263
+ `),"Migration");if(!z)await gF(process.cwd());let U=E6();U.start("Downloading...");let K,X;try{let y=await pK();K=y.dir,X=y.cleanup}catch(y){U.stop("Download failed"),$4.error(y instanceof Error?y.message:String(y)),process.exit(1)}U.stop("Downloaded!");let Q=b35(K),Z=w35(process.cwd()),j=Q.some((y)=>y.value===Z)?Z:"en",Y=z?j:await n8({message:"Response language?",options:Q,initialValue:j});if(Y4(Y))X(),n1("Cancelled."),process.exit(0);let W=[{value:"claude",label:"Claude Code only",hint:"Claude Max subscription holders"},{value:"codex",label:"Codex CLI only",hint:"ChatGPT Plus/Pro subscription holders"},{value:"gemini",label:"Gemini CLI only",hint:"Google AI Pro subscription holders"},{value:"qwen",label:"Qwen Code only",hint:"Qwen Code subscription holders"},{value:"mixed",label:"Mixed (Antigravity IDE)",hint:"Claude orchestrator + cross-vendor subagents"}],L=S35(process.cwd()),k=W.some((y)=>y.value===L)?L:"claude",H=z?k:await n8({message:"Model preset?",options:W,initialValue:k});if(Y4(H))X(),n1("Cancelled."),process.exit(0);let B=z?"all":await n8({message:"What type of project?",options:[{value:"all",label:"All",hint:"Install everything"},{value:"fullstack",label:"Fullstack",hint:"Web + Mobile + Infra (kitchen sink)"},{value:"fullstack-web",label:"Fullstack Web",hint:"Frontend + Backend + DB (no mobile/infra)"},{value:"fullstack-mobile",label:"Fullstack Mobile",hint:"Mobile + Backend + DB"},{value:"frontend",label:"Frontend",hint:"React/Next.js"},{value:"backend",label:"Backend",hint:"Python, Node.js, Rust, ..."},{value:"mobile",label:"Mobile",hint:"Flutter/Dart"},{value:"devops",label:"DevOps",hint:"Terraform + CI/CD + Observability"},{value:"research",label:"Research",hint:"Scholar + Market + PDF/HWP + Writer"},{value:"content",label:"Content",hint:"Image + Voice + Design + Writer"},{value:"custom",label:"Custom",hint:"Choose skills"}]});if(Y4(B))n1("Cancelled."),process.exit(0);let A;if(B==="custom"){let y=qG(),c=await LY({message:"Select skills:",options:y.map((n)=>({value:n.name,label:n.name,hint:n.desc})),required:!0});if(Y4(c))n1("Cancelled."),process.exit(0);A=c}else A=m22[B]??[];let V=process.cwd(),F={};if(A.includes("oma-backend")){let y=z?"python":await n8({message:"Backend language?",options:[{value:"python",label:"\uD83D\uDC0D Python",hint:"FastAPI/SQLAlchemy (default)"},{value:"node",label:"\uD83D\uDFE2 Node.js",hint:"NestJS/Hono + Prisma/Drizzle"},{value:"rust",label:"\uD83E\uDD80 Rust",hint:"Axum/Actix-web"},{value:"other",label:"\uD83D\uDD27 Other / Auto-detect",hint:"Configure later with /stack-set"}],initialValue:"python"});if(Y4(y))n1("Cancelled."),process.exit(0);if(y!=="other")F["oma-backend"]=y}let N=process.platform!=="win32"&&!process.env.CI,O=[{value:"claude",label:"Claude Code",hint:"hooks + settings + CLAUDE.md"},{value:"codex",label:"Codex CLI",hint:"hooks + plugin"},{value:"copilot",label:"GitHub Copilot",hint:"skill symlinks + .github/prompts/ wrappers"},{value:"cursor",label:"Cursor",hint:".cursor/rules/ export + prompt hooks"},{value:"gemini",label:"Gemini CLI",hint:"hooks + Serena MCP"},...N?[{value:"hermes",label:"Hermes Agent",hint:"skills only β€” workflows N/A, HOME-shared (no per-project isolation)"}]:[],{value:"qwen",label:"Qwen Code",hint:"hooks + settings"}],q=O.filter((y)=>{let c=h8[y.value];return!c||c.base!=="home"}).map((y)=>y.value),I=z?q:await LY({message:"CLI tools to configure:",options:O,initialValues:q,required:!0});if(Y4(I))n1("Cancelled."),process.exit(0);let D=I,M=D.filter(NK),T=Object.keys(h8),i=D.filter((y)=>T.includes(y)),h=[];for(let y of i){if(OK(y)){if(z){$4.info(l4.default.dim(`Skipped ${y} export (HOME write requires -y opt-in).`));continue}let c=await F3({message:`${y} export writes to HOME (${l4.default.cyan(B52(y))}). Proceed?`,initialValue:!1});if(Y4(c))X(),n1("Cancelled."),process.exit(0);if(!c){$4.info(l4.default.dim(`Skipped ${y} export.`));continue}}h.push(y)}U.start("Installing skills...");try{try{let n=[".claude/skills",".codex/skills",".gemini/skills",".github/skills"];for(let a of n)C35(F9(V,a));if(MV(K,V),Z52(K,V),D.includes("codex"))FK(K,V);if(D.includes("copilot"))DV(K,V);W52(K,V),k52(K,V,!1);for(let a of A)U.message(`Installing ${l4.default.cyan(a)}...`),qV(K,a,V,F[a]);U.stop("Skills installed!"),U.start("Installing vendor adaptations..."),AK(K,V,M);let t={telemetry:$X(V)};if(D.includes("claude")){let a=F9(V,".claude","settings.json"),E={};if(G0(a))try{E=JSON.parse(dG(a,"utf-8"))}catch{E={}}if(fF(E,t))lF(E,t),BW(a,`${JSON.stringify(E,null,2)}
1264
1264
  `)}if(D.includes("gemini")){let a=F9(V,".gemini","settings.json"),E={};if(G0(a))try{E=JSON.parse(dG(a,"utf-8"))}catch{E={}}if(JX(E,t))i$(E,t),BW(a,`${JSON.stringify(E,null,2)}
1265
1265
  `)}if(D.includes("qwen")){let a=F9(V,".qwen","settings.json"),E={};if(G0(a))try{E=JSON.parse(dG(a,"utf-8"))}catch{E={}}if(g$(E,t)){let v=m$(E,t);I02(E02(a),{recursive:!0}),BW(a,`${JSON.stringify(v,null,2)}
1266
1266
  `)}}if(D.includes("codex")){let a=F9(V,".codex","config.toml"),E=G0(a)?dG(a,"utf-8"):"",v=N6(E);if(o0(v,t)){let U2=r0(v,t);I02(E02(a),{recursive:!0}),BW(a,`${O6(U2)}
@@ -1637,7 +1637,7 @@ spawn_error:${Q.message}`})})})}async function vK2($,z,G={}){let J=performance.n
1637
1637
  `);let z=new V6("!xml"),G=z,J="";this.matcher.reset(),this.entityDecoder.reset(),this.entityExpansionCount=0,this.currentExpandedLength=0;let U=this.options,K=new pD(U.processEntities),X=$.length;for(let Q=0;Q<X;Q++)if($[Q]==="<"){let j=$.charCodeAt(Q+1);if(j===47){let Y=fZ($,">",Q,"Closing Tag is not closed."),W=$.substring(Q+2,Y).trim();if(U.removeNSPrefix){let k=W.indexOf(":");if(k!==-1)W=W.substr(k+1)}if(W=qd(U.transformTagName,W,"",U).tagName,G)J=this.saveTextToParentTag(J,G,this.readonlyMatcher);let L=this.matcher.getCurrentTag();if(W&&U.unpairedTagsSet.has(W))throw Error(`Unpaired tag can not be used as closing tag: </${W}>`);if(L&&U.unpairedTagsSet.has(L))this.matcher.pop(),this.tagsNodeStack.pop();this.matcher.pop(),this.isCurrentNodeStopNode=!1,G=this.tagsNodeStack.pop(),J="",Q=Y}else if(j===63){let Y=Md($,Q,!1,"?>");if(!Y)throw Error("Pi Tag is not closed.");J=this.saveTextToParentTag(J,G,this.readonlyMatcher);let W=this.buildAttributesMap(Y.tagExp,this.matcher,Y.tagName,!0);if(W){let L=W[this.options.attributeNamePrefix+"version"];this.entityDecoder.setXmlVersion(Number(L)||1),K.setXmlVersion(Number(L)||1)}if(U.ignoreDeclaration&&Y.tagName==="?xml"||U.ignorePiTags);else{let L=new V6(Y.tagName);if(L.add(U.textNodeName,""),Y.tagName!==Y.tagExp&&Y.attrExpPresent&&U.ignoreAttributes!==!0)L[":@"]=W;this.addChild(G,L,this.readonlyMatcher,Q)}Q=Y.closeIndex+1}else if(j===33&&$.charCodeAt(Q+2)===45&&$.charCodeAt(Q+3)===45){let Y=fZ($,"-->",Q+4,"Comment is not closed.");if(U.commentPropName){let W=$.substring(Q+4,Y-2);J=this.saveTextToParentTag(J,G,this.readonlyMatcher),G.add(U.commentPropName,[{[U.textNodeName]:W}])}Q=Y}else if(j===33&&$.charCodeAt(Q+2)===68){let Y=K.readDocType($,Q);this.entityDecoder.addInputEntities(Y.entities),Q=Y.i}else if(j===33&&$.charCodeAt(Q+2)===91){let Y=fZ($,"]]>",Q,"CDATA is not closed.")-2,W=$.substring(Q+9,Y);J=this.saveTextToParentTag(J,G,this.readonlyMatcher);let L=this.parseTextData(W,G.tagname,this.readonlyMatcher,!0,!1,!0,!0);if(L==null)L="";if(U.cdataPropName)G.add(U.cdataPropName,[{[U.textNodeName]:W}]);else G.add(U.textNodeName,L);Q=Y+2}else{let Y=Md($,Q,U.removeNSPrefix);if(!Y){let I=$.substring(Math.max(0,Q-50),Math.min(X,Q+50));throw Error(`readTagExp returned undefined at position ${Q}. Context: "${I}"`)}let{tagName:W,rawTagName:L,tagExp:k,attrExpPresent:H,closeIndex:B}=Y;if({tagName:W,tagExp:k}=qd(U.transformTagName,W,k,U),U.strictReservedNames&&(W===U.commentPropName||W===U.cdataPropName||W===U.textNodeName||W===U.attributesGroupName))throw Error(`Invalid tag name: ${W}`);if(G&&J){if(G.tagname!=="!xml")J=this.saveTextToParentTag(J,G,this.readonlyMatcher,!1)}let A=G;if(A&&U.unpairedTagsSet.has(A.tagname))G=this.tagsNodeStack.pop(),this.matcher.pop();let V=!1;if(k.length>0&&k.lastIndexOf("/")===k.length-1){if(V=!0,W[W.length-1]==="/")W=W.substr(0,W.length-1),k=W;else k=k.substr(0,k.length-1);H=W!==k}let F=null,N={},O=void 0;if(O=Cw5(L),W!==z.tagname)this.matcher.push(W,{},O);if(W!==k&&H){if(F=this.buildAttributesMap(k,this.matcher,W),F)N=ww5(F,U)}if(W!==z.tagname)this.isCurrentNodeStopNode=this.isItStopNode();let q=Q;if(this.isCurrentNodeStopNode){let I="";if(V)Q=Y.closeIndex;else if(U.unpairedTagsSet.has(W))Q=Y.closeIndex;else{let M=this.readStopNodeData($,L,B+1);if(!M)throw Error(`Unexpected end of ${L}`);Q=M.i,I=M.tagContent}let D=new V6(W);if(F)D[":@"]=F;D.add(U.textNodeName,I),this.matcher.pop(),this.isCurrentNodeStopNode=!1,this.addChild(G,D,this.readonlyMatcher,q)}else{if(V){({tagName:W,tagExp:k}=qd(U.transformTagName,W,k,U));let I=new V6(W);if(F)I[":@"]=F;this.addChild(G,I,this.readonlyMatcher,q),this.matcher.pop(),this.isCurrentNodeStopNode=!1}else if(U.unpairedTagsSet.has(W)){let I=new V6(W);if(F)I[":@"]=F;this.addChild(G,I,this.readonlyMatcher,q),this.matcher.pop(),this.isCurrentNodeStopNode=!1,Q=Y.closeIndex;continue}else{let I=new V6(W);if(this.tagsNodeStack.length>U.maxNestedTags)throw Error("Maximum nested tags exceeded");if(this.tagsNodeStack.push(G),F)I[":@"]=F;this.addChild(G,I,this.readonlyMatcher,q),G=I}J="",Q=B}}}else J+=$[Q];return z.child};function iw5($,z,G,J){if(!this.options.captureMetaData)J=void 0;let U=this.options.jPath?G.toString():G,K=this.options.updateTag(z.tagname,U,z[":@"]);if(K===!1);else if(typeof K==="string")z.tagname=K,$.addChild(z,J);else $.addChild(z,J)}function gw5($,z,G){let J=this.options.processEntities;if(!J||!J.enabled)return $;if(J.allowedTags){let U=this.options.jPath?G.toString():G;if(!(Array.isArray(J.allowedTags)?J.allowedTags.includes(z):J.allowedTags(z,U)))return $}if(J.tagFilter){let U=this.options.jPath?G.toString():G;if(!J.tagFilter(z,U))return $}return this.entityDecoder.decode($)}function mw5($,z,G,J){if($){if(J===void 0)J=z.child.length===0;if($=this.parseTextData($,z.tagname,G,!1,z[":@"]?Object.keys(z[":@"]).length!==0:!1,J),$!==void 0&&$!=="")z.add(this.options.textNodeName,$);$=""}return $}function fw5(){if(this.stopNodeExpressionsSet.size===0)return!1;return this.matcher.matchesAny(this.stopNodeExpressionsSet)}function lw5($,z,G=">"){let J=0,U=$.length,K=G.charCodeAt(0),X=G.length>1?G.charCodeAt(1):-1,Q="",Z=z;for(let j=z;j<U;j++){let Y=$.charCodeAt(j);if(J){if(Y===J)J=0}else if(Y===34||Y===39)J=Y;else if(Y===K)if(X!==-1){if($.charCodeAt(j+1)===X)return Q+=$.substring(Z,j),{data:Q,index:j}}else return Q+=$.substring(Z,j),{data:Q,index:j};else if(Y===9&&!J)Q+=$.substring(Z,j)+" ",Z=j+1}}function fZ($,z,G,J){let U=$.indexOf(z,G);if(U===-1)throw Error(J);else return U+z.length-1}function cw5($,z,G,J){let U=$.indexOf(z,G);if(U===-1)throw Error(J);return U}function Md($,z,G,J=">"){let U=lw5($,z+1,J);if(!U)return;let{data:K,index:X}=U,Q=K.search(/\s/),Z=K,j=!0;if(Q!==-1)Z=K.substring(0,Q),K=K.substring(Q+1).trimStart();let Y=Z;if(G){let W=Z.indexOf(":");if(W!==-1)Z=Z.substr(W+1),j=Z!==U.data.substr(W+1)}return{tagName:Z,tagExp:K,closeIndex:X,attrExpPresent:j,rawTagName:Y}}function nw5($,z,G){let J=G,U=1,K=$.length;for(;G<K;G++)if($[G]==="<"){let X=$.charCodeAt(G+1);if(X===47){let Q=cw5($,">",G,`${z} is not closed`);if($.substring(G+2,Q).trim()===z){if(U--,U===0)return{tagContent:$.substring(J,G),i:Q}}G=Q}else if(X===63)G=fZ($,"?>",G+1,"StopNode is not closed.");else if(X===33&&$.charCodeAt(G+2)===45&&$.charCodeAt(G+3)===45)G=fZ($,"-->",G+3,"StopNode is not closed.");else if(X===33&&$.charCodeAt(G+2)===91)G=fZ($,"]]>",G,"StopNode is not closed.")-2;else{let Q=Md($,G,!1);if(Q){if((Q&&Q.tagName)===z&&Q.tagExp[Q.tagExp.length-1]!=="/")U++;G=Q.closeIndex}}}}function Dd($,z,G){if(z&&typeof $==="string"){let J=$.trim();if(J==="true")return!0;else if(J==="false")return!1;else return Od($,G)}else if(oE2($))return $;else return""}function qd($,z,G,J){if($){let U=$(z);if(G===z)G=U;z=U}return z=uT2(z,J),{tagName:z,tagExp:G}}function uT2($,z){if(lD.includes($))throw Error(`[SECURITY] Invalid name: "${$}" is a reserved JavaScript keyword that could cause prototype pollution`);else if(GH.includes($))return z.onDangerousProperty($);return $}var Id=V6.getMetaDataSymbol();function dw5($,z){if(!$||typeof $!=="object")return{};if(!z)return $;let G={};for(let J in $)if(J.startsWith(z)){let U=J.substring(z.length);G[U]=$[J]}else G[J]=$[J];return G}function Ed($,z,G,J){return qT2($,z,G,J)}function qT2($,z,G,J){let U,K={};for(let X=0;X<$.length;X++){let Q=$[X],Z=pw5(Q);if(Z!==void 0&&Z!==z.textNodeName){let j=dw5(Q[":@"]||{},z.attributeNamePrefix);G.push(Z,j)}if(Z===z.textNodeName)if(U===void 0)U=Q[Z];else U+=""+Q[Z];else if(Z===void 0)continue;else if(Q[Z]){let j=qT2(Q[Z],z,G,J),Y=ow5(j,z);if(Object.keys(j).length===0&&z.alwaysCreateTextNode)j[z.textNodeName]="";if(Q[":@"])aw5(j,Q[":@"],J,z);else if(Object.keys(j).length===1&&j[z.textNodeName]!==void 0&&!z.alwaysCreateTextNode)j=j[z.textNodeName];else if(Object.keys(j).length===0)if(z.alwaysCreateTextNode)j[z.textNodeName]="";else j="";if(Q[Id]!==void 0&&typeof j==="object"&&j!==null)j[Id]=Q[Id];if(K[Z]!==void 0&&Object.prototype.hasOwnProperty.call(K,Z)){if(!Array.isArray(K[Z]))K[Z]=[K[Z]];K[Z].push(j)}else{let W=z.jPath?J.toString():J;if(z.isArray(Z,W,Y))K[Z]=[j];else K[Z]=j}if(Z!==void 0&&Z!==z.textNodeName)G.pop()}}if(typeof U==="string"){if(U.length>0)K[z.textNodeName]=U}else if(U!==void 0)K[z.textNodeName]=U;return K}function pw5($){let z=Object.keys($);for(let G=0;G<z.length;G++){let J=z[G];if(J!==":@")return J}}function aw5($,z,G,J){if(z){let U=Object.keys(z),K=U.length;for(let X=0;X<K;X++){let Q=U[X],Z=Q.startsWith(J.attributeNamePrefix)?Q.substring(J.attributeNamePrefix.length):Q,j=J.jPath?G.toString()+"."+Z:G;if(J.isArray(Q,j,!0,!0))$[Q]=[z[Q]];else $[Q]=z[Q]}}}function ow5($,z){let{textNodeName:G}=z,J=Object.keys($).length;if(J===0)return!0;if(J===1&&($[G]||typeof $[G]==="boolean"||$[G]===0))return!0;return!1}class jH{constructor($){this.externalEntities={},this.options=AT2($)}parse($,z){if(typeof $!=="string"&&$.toString)$=$.toString();else if(typeof $!=="string")throw Error("XML data is accepted in String or Bytes[] form.");if(z){if(z===!0)z={};let U=$T2($,z);if(U!==!0)throw Error(`${U.err.msg}:${U.err.line}:${U.err.col}`)}let G=new aD(this.options,this.externalEntities),J=G.parseXml($);if(this.options.preserveOrder||J===void 0)return J;else return Ed(J,this.options,G.matcher,G.readonlyMatcher)}addEntity($,z){if(z.indexOf("&")!==-1)throw Error("Entity value can't have '&'");else if($.indexOf("&")!==-1||$.indexOf(";")!==-1)throw Error("An entity must be set without '&' and ';'. Eg. use '#xD' for '&#xD;'");else if(z==="&")throw Error("An entity with value '&' is not permitted");else this.externalEntities[$]=z}static getMetaDataSymbol(){return V6.getMetaDataSymbol()}}j8();var rw5=["/rss","/feed","/atom.xml","/rss.xml","/index.xml"],sw5=new jH({ignoreAttributes:!1,attributeNamePrefix:"@_",textNodeName:"#text"});function Td($){if($===void 0||$===null)return[];return Array.isArray($)?$:[$]}function P3($){if($==null)return;if(typeof $==="string")return $;if(typeof $==="object"){let z=$;if(typeof z["#text"]==="string")return z["#text"];if(typeof z["#cdata"]==="string")return z["#cdata"]}return}function MT2($){for(let z of Td($)){let G=z?.["@_href"],J=z?.["@_rel"];if(typeof G==="string"&&(J===void 0||J==="alternate"))return G}return}function DT2($){let z;try{z=sw5.parse($)}catch{return null}let G=z.rss;if(G){let U=G.channel;if(!U)return null;let K=Td(U.item);return{kind:"rss",title:P3(U.title),description:P3(U.description),link:P3(U.link),entries:K.map((X)=>({title:P3(X.title),link:P3(X.link),pubDate:P3(X.pubDate),description:P3(X.description),content:P3(X["content:encoded"])??P3(X.content)}))}}let J=z.feed;if(J){let U=Td(J.entry);return{kind:"atom",title:P3(J.title),description:P3(J.subtitle),link:MT2(J.link),entries:U.map((K)=>({title:P3(K.title),link:MT2(K.link),pubDate:P3(K.published)??P3(K.updated),description:P3(K.summary),content:P3(K.content)??P3(K.summary)}))}}return null}async function IT2($,z){let G=performance.now(),J;try{let K=await d1($.toString(),{timeoutMs:z.timeoutMs,locale:z.locale,signal:z.signal});if(K.ok)J=HO(K.text).alternate?.[0]?.href}catch{}let U=new Set;if(J)try{U.add(new URL(J,$).toString())}catch{}for(let K of rw5)U.add(new URL(K,`${$.protocol}//${$.host}`).toString());for(let K of U){if(z.signal?.aborted)break;try{let X=await d1(K,{timeoutMs:z.timeoutMs,locale:z.locale,signal:z.signal});if(!X.ok||X.text.length<50)continue;let Q=DT2(X.text);if(!Q||Q.entries.length===0)continue;return{url:$.toString(),status:"ok",strategy:"probe",platform:"rss",httpStatus:X.status,content:X.text,contentType:X.headers.get("content-type")??void 0,elapsedMs:Math.round(performance.now()-G),signals:[],feedUrl:K,feed:Q}}catch{}}return{url:$.toString(),status:"not-found",strategy:"probe",platform:"rss",content:"",elapsedMs:Math.round(performance.now()-G),signals:[],error:"no RSS/Atom feed discovered"}}function ET2($,z="en-US"){let[G,J]=z.split("-"),U=new URL("https://news.google.com/rss/search");return U.searchParams.set("q",$),U.searchParams.set("hl",G??"en"),U.searchParams.set("gl",J??"US"),U.searchParams.set("ceid",`${J??"US"}:${G??"en"}`),U.toString()}FW();j8();var oD={"github.com":{domain:"github.com",level:"verified",score:0.95,tags:["code-host"],source:"registry"},"docs.github.com":{domain:"docs.github.com",level:"verified",score:0.95,tags:["lang-docs"],source:"registry"},"developer.mozilla.org":{domain:"developer.mozilla.org",level:"verified",score:0.95,tags:["lang-docs"],source:"registry"},"nextjs.org":{domain:"nextjs.org",level:"verified",score:0.9,tags:["vendor","lang-docs"],source:"registry"},"vercel.com":{domain:"vercel.com",level:"verified",score:0.9,tags:["vendor"],source:"registry"},"typescriptlang.org":{domain:"typescriptlang.org",level:"verified",score:0.95,tags:["lang-docs"],source:"registry"},"stackoverflow.com":{domain:"stackoverflow.com",level:"community",score:0.7,tags:["qna"],source:"registry"},"dev.to":{domain:"dev.to",level:"external",score:0.4,tags:["blog"],source:"registry"},"medium.com":{domain:"medium.com",level:"external",score:0.35,tags:["blog"],source:"registry"},"npmjs.com":{domain:"npmjs.com",level:"verified",score:0.9,tags:["registry"],source:"registry"},"pypi.org":{domain:"pypi.org",level:"verified",score:0.9,tags:["registry"],source:"registry"},"news.ycombinator.com":{domain:"news.ycombinator.com",level:"community",score:0.65,tags:["news"],source:"registry"},"reddit.com":{domain:"reddit.com",level:"community",score:0.55,tags:["forum"],source:"registry"},"wikipedia.org":{domain:"wikipedia.org",level:"community",score:0.75,tags:["encyclopedia"],source:"registry"},"arxiv.org":{domain:"arxiv.org",level:"verified",score:0.9,tags:["academic"],source:"registry"},"doi.org":{domain:"doi.org",level:"verified",score:0.95,tags:["academic"],source:"registry"}};function tw5($){return $.replace(/^www\./,"")}function ew5($){if($ in oD){let G=oD[$];return G?{...G}:null}let z=tw5($);if(z in oD){let G=oD[z];return G?{...G}:null}return null}function $C5($){let z=$.split(".").pop();if(z==="gov"||z==="edu"||z==="mil")return{domain:$,level:"verified",score:0.9,tags:["institution"],source:"heuristic"};if(/\.gov\.[a-z]{2}$/.test($)||/\.ac\.[a-z]{2}$/.test($))return{domain:$,level:"verified",score:0.85,tags:["institution"],source:"heuristic"};return null}async function zC5($){try{let z=await d1(`https://tranco-list.eu/api/ranks/domain/${$}`,{timeoutMs:5000});if(!z.ok)return null;let J=JSON.parse(z.text).ranks?.[0]?.rank;if(!J)return null;let U=J<1e4?0.6:J<1e5?0.4:0.2;return{domain:$,level:J<1e4?"community":"external",score:U,tags:["tranco"],source:"tranco",rank:J}}catch{return null}}async function TT2($){let z=ew5($);if(z)return z;let G=$C5($);if(G)return G;let J=await zC5($);if(J)return J;return{domain:$,level:"unknown",score:null,tags:[],source:"heuristic"}}var RT2=["api","probe","impersonate","browser","archive"];function vT2($){if(!$)return;let z=$.split(",").map((J)=>J.trim()).filter(Boolean),G=z.filter((J)=>!RT2.includes(J));if(G.length>0)throw Error(`Unknown strategy: ${G.join(", ")}. Valid: ${RT2.join(", ")}`);return z}function lZ($){try{return new URL($)}catch{throw Error(`Invalid URL: ${$}`)}}function az($){return{timeoutMs:$.timeout?Math.max(1000,Math.floor(Number($.timeout)*1000)):15000,locale:$.locale??"en-US,en;q=0.9"}}function n0($,z){if(z)console.log(JSON.stringify($,null,2));else console.log(JSON.stringify($))}function QU($){if(!$){process.exitCode=1;return}if($.status==="ok")process.exitCode=0;else if($.status==="blocked")process.exitCode=2;else if($.status==="not-found")process.exitCode=3;else if($.status==="invalid-input")process.exitCode=4;else if($.status==="auth-required")process.exitCode=5;else if($.status==="timeout")process.exitCode=6;else process.exitCode=1}function PT2($){let z=$.command("search").description("Mechanical search primitives β€” fetch, meta, rss, media, trust, code").alias("s");z.command("fetch <url>").description("Fetch URL via auto-escalating strategy pipeline").option("--only <strategies>","Comma-separated strategies to run").option("--skip <strategies>","Comma-separated strategies to skip").option("--include-archive","Include archive strategy as last fallback").option("--timeout <seconds>","Per-strategy timeout","15").option("--locale <value>","Accept-Language header","en-US,en;q=0.9").option("--pretty","Pretty-print JSON output").action(async(G,J)=>{try{let U=lZ(G),K=az(J),X=await aE2(U,K,{only:vT2(J.only),skip:vT2(J.skip),includeArchive:J.includeArchive});n0(X,Boolean(J.pretty)),QU(X)}catch(U){console.error(_8.default.red(U.message)),process.exitCode=1}}),z.command("api <url>").description("Fetch via matched platform API (Phase 0)").option("--timeout <seconds>","Timeout","15").option("--locale <value>","Accept-Language","en-US,en;q=0.9").option("--pretty","Pretty-print JSON").action(async(G,J)=>{try{let U=lZ(G);if(!vy(U)){console.error(_8.default.yellow(`No API handler matches host ${U.hostname}`)),process.exitCode=3;return}let X=az(J),Q=await UN(U,X);if(!Q){process.exitCode=3;return}n0(Q,Boolean(J.pretty)),QU(Q)}catch(U){console.error(_8.default.red(U.message)),process.exitCode=1}}),z.command("api:search <query>").description("Fan-out keyword search across platforms that support it").option("--platforms <list>","Comma-separated platform ids").option("--timeout <seconds>","Timeout","15").option("--locale <value>","Accept-Language","en-US,en;q=0.9").option("--pretty","Pretty-print JSON").action(async(G,J)=>{let U=az(J),K=J.platforms?J.platforms.split(",").map((Q)=>Q.trim()).filter(Boolean):void 0,X=await l$(G,U,K);n0(X,Boolean(J.pretty))}),z.command("meta <url>").description("Extract OGP / JSON-LD / Schema.org from URL").option("--timeout <seconds>","Timeout","15").option("--locale <value>","Accept-Language","en-US,en;q=0.9").option("--pretty","Pretty-print JSON").action(async(G,J)=>{try{let U=lZ(G),K=az(J),X=await bK2(U,K),{content:Q,...Z}=X;n0(Z,Boolean(J.pretty)),QU(X)}catch(U){console.error(_8.default.red(U.message)),process.exitCode=1}}),z.command("rss <url>").description("Discover and parse RSS/Atom feed for a URL").option("--timeout <seconds>","Timeout","15").option("--locale <value>","Accept-Language","en-US,en;q=0.9").option("--pretty","Pretty-print JSON").action(async(G,J)=>{try{let U=lZ(G),K=az(J),X=await IT2(U,K),{content:Q,...Z}=X;n0(Z,Boolean(J.pretty)),QU(X)}catch(U){console.error(_8.default.red(U.message)),process.exitCode=1}}),z.command("rss:google <query>").description("Build Google News RSS URL for a query").option("--locale <value>","Locale (e.g., ko-KR)","en-US").action((G,J)=>{let U=ET2(G,J.locale??"en-US");console.log(U)}),z.command("media <url>").description("Extract media metadata via yt-dlp (1858 sites)").option("--subs","Write subtitles").option("--sub-lang <list>","Subtitle languages (comma-separated)","en").option("--format <spec>","yt-dlp format spec").option("--timeout <seconds>","Timeout","30").option("--pretty","Pretty-print JSON").action(async(G,J)=>{try{let U=lZ(G),K=az(J),X=J.subLang?J.subLang.split(",").map((Z)=>Z.trim()).filter(Boolean):void 0,Q=await vK2(U,K,{subtitles:J.subs,...X?{subLangs:X}:{},...J.format?{format:J.format}:{}});n0(Q,Boolean(J.pretty)),QU(Q)}catch(U){console.error(_8.default.red(U.message)),process.exitCode=1}}),z.command("archive <url>").description("Fetch via AMP / archive.today / Wayback").option("--timeout <seconds>","Timeout","15").option("--locale <value>","Accept-Language","en-US,en;q=0.9").option("--pretty","Pretty-print JSON").action(async(G,J)=>{try{let U=lZ(G),K=az(J),X=await nW(U,K);n0(X,Boolean(J.pretty)),QU(X)}catch(U){console.error(_8.default.red(U.message)),process.exitCode=1}}),z.command("trust <domain>").description("Resolve trust level / score for a domain").option("--pretty","Pretty-print JSON").action(async(G,J)=>{let U=await TT2(G.toLowerCase());n0(U,Boolean(J.pretty))}),z.command("code <query>").description("Search code via gh / glab").option("--host <github|gitlab>","Host","github").option("--language <lang>","Language filter").option("--repo <owner/repo>","Scope to a repo").option("--limit <n>","Max results","20").option("--pretty","Pretty-print JSON").action(async(G,J)=>{let U=J.host==="gitlab"||J.host==="github"?J.host:"github",K=az({}),X=await RK2(G,K,{host:U,...J.language?{language:J.language}:{},...J.repo?{repo:J.repo}:{},...J.limit?{limit:Number.parseInt(J.limit,10)}:{}});n0(X,Boolean(J.pretty)),QU(X)}),z.command("doctor").description("Check dependencies (Chrome, python3 curl_cffi, yt-dlp, gh)").action(async()=>{let G=[],J=kd();G.push({name:"chrome",ok:Boolean(J),detail:J??"Install Chrome or set OMA_CHROME_PATH"}),G.push(await Rd("python3",["--version"])),G.push(await GC5()),G.push(await Rd("yt-dlp",["--version"])),G.push(await Rd("gh",["--version"]));for(let U of G){let K=U.ok?_8.default.green("βœ“"):_8.default.yellow("!");console.log(`${K} ${U.name}: ${U.detail}`)}if(G.some((U)=>!U.ok))process.exitCode=1})}async function Rd($,z){return new Promise((G)=>{let{spawn:J}=Q2("node:child_process"),U=J($,z,{stdio:["ignore","pipe","pipe"]}),K="";U.stdout?.on("data",(X)=>{K+=X.toString()}),U.on("error",()=>G({name:$,ok:!1,detail:"not found"})),U.on("close",(X)=>{if(X===0)G({name:$,ok:!0,detail:K.trim()});else G({name:$,ok:!1,detail:`exit code ${X}`})})})}async function GC5(){return new Promise(($)=>{let{spawn:z}=Q2("node:child_process"),G=z("python3",["-c","import curl_cffi; print(curl_cffi.__version__)"],{stdio:["ignore","pipe","pipe"]}),J="";G.stdout?.on("data",(U)=>{J+=U.toString()}),G.on("error",()=>$({name:"curl_cffi",ok:!1,detail:"python3 not found"})),G.on("close",(U)=>{if(U===0)$({name:"curl_cffi",ok:!0,detail:`v${J.trim()}`});else $({name:"curl_cffi",ok:!1,detail:"not installed (pip install curl_cffi)"})})})}K7();var oz=p2(I4(),1);import{execSync as JC5,spawnSync as bT2}from"node:child_process";import{platform as UC5}from"node:os";function KC5(){let $=UC5();if($==="darwin")return"brew install gh";if($==="win32")return"winget install GitHub.cli";return"sudo apt install gh"}async function wT2(){if(console.clear(),d4(oz.default.bgMagenta(oz.default.white(" ⭐ oh-my-agent star "))),!MG()){let z=KC5(),G=await F3({message:`GitHub CLI (gh) is not installed. Install with ${oz.default.cyan(z)}?`});if(Y4(G)||!G){T5("Install gh manually and try again.");return}let J=E6();J.start("Installing GitHub CLI...");let U=bT2(z,{shell:!0,stdio:"pipe"});if(U.status!==0){J.stop("Installation failed"),$4.error(U.stderr?.toString()||"Unknown error"),T5("Please install gh manually.");return}J.stop("GitHub CLI installed!")}if(!J8()){$4.warn("GitHub CLI is not authenticated.");let z=await F3({message:`Run ${oz.default.cyan("gh auth login")} now?`});if(Y4(z)||!z){T5("Authenticate and try again.");return}if(bT2("gh",["auth","login"],{stdio:"inherit"}),!J8()){T5("Authentication was not completed. Try again.");return}$4.success("Authenticated!")}if(DG()){T5(`Already starred ${oz.default.cyan(K1)}! Thank you! \uD83D\uDE4F`);return}let $=await F3({message:`Star ${oz.default.cyan(K1)} on GitHub?`});if(Y4($)||!$){T5("Maybe next time!");return}try{JC5(`gh api -X PUT /user/starred/${K1}`,{stdio:"ignore"}),T5(`Starred ${oz.default.cyan(K1)}! Thank you! \uD83C\uDF1F`)}catch{$4.error("Failed to star the repository."),T5("Please try again later.")}}function CT2($){$.command("star").description("Star oh-my-agent on GitHub").action(Y5(async()=>{await wT2()}))}K7();cx();ZY();var b3=p2(I4(),1);import{existsSync as YH,mkdirSync as XC5,readdirSync as QC5,readFileSync as _T2,writeFileSync as hT2}from"node:fs";import{dirname as ZC5,join as vd}from"node:path";function jC5($){let z=oe($),G={},J=0,U=0;for(let K of z){J+=K.tokens;let X=ae(K.tokens,K.vendor);U+=X;let Q=G[K.vendor]??{tokens:0,spawns:0,usd:0};Q.tokens+=K.tokens,Q.spawns+=1,Q.usd+=X,G[K.vendor]=Q}return{totalTokens:J,totalSpawns:z.length,estimatedUsd:U,byVendor:G}}function ST2($){return $.toLocaleString("en-US")}function yT2($){if($===0)return"$0.00";if($<0.01)return"<$0.01";return`$${$.toFixed(2)}`}function Pd($){return vd($,".agents","state","metrics.json")}function YC5($){return vd($,".serena","metrics.json")}function rD(){return{sessions:0,skillsUsed:{},tasksCompleted:0,totalSessionTime:0,filesChanged:0,linesAdded:0,linesRemoved:0,lastUpdated:new Date().toISOString(),startDate:new Date().toISOString()}}function WC5($){let z=Pd($);if(YH(z))try{return JSON.parse(_T2(z,"utf-8"))}catch{return rD()}let G=YC5($);if(YH(G))try{return JSON.parse(_T2(G,"utf-8"))}catch{return rD()}return rD()}function kC5($,z){let G=Pd($),J=ZC5(G);if(!YH(J))XC5(J,{recursive:!0});z.lastUpdated=new Date().toISOString(),hT2(G,JSON.stringify(z,null,2),"utf-8")}function LC5($){let z=vd($,".serena","memories"),G={};if(!YH(z))return G;try{let J=QC5(z);for(let U of J){let K=U.match(/(?:progress|result)-(\w+)/);if(K?.[1]){let X=K[1];G[X]=(G[X]||0)+1}}}catch{}return G}async function xT2($=!1,z=!1){let G=process.cwd(),J=Pd(G);if(z){if(YH(J))hT2(J,JSON.stringify(rD(),null,2),"utf-8");if($)console.log(JSON.stringify({reset:!0}));else console.log(b3.default.green("βœ… Metrics reset successfully."));return}let U=WC5(G),K=XO(G),X=LC5(G),Q=Ee(G),Z=ZV(G),j=Z.startedAt?new Date(Z.startedAt):null,Y=j&&!Number.isNaN(j.getTime())?Math.max(0,Math.floor((Date.now()-j.getTime())/1000)):0;for(let[A,V]of Object.entries(X))U.skillsUsed[A]=(U.skillsUsed[A]||0)+V;if(Q>U.tasksCompleted)U.tasksCompleted=Q;if(Z.id){if(["completed","failed","aborted"].includes(Z.status||"")&&(U.lastSessionId!==Z.id||U.lastSessionStatus!==Z.status)&&Y>0)U.totalSessionTime+=Y;U.lastSessionId=Z.id,U.lastSessionStatus=Z.status,U.lastSessionStarted=Z.startedAt,U.lastSessionDuration=Y}U.filesChanged+=K.filesChanged,U.linesAdded+=K.linesAdded,U.linesRemoved+=K.linesRemoved,U.sessions+=1,kC5(G,U);let W=Math.max(1,Math.ceil((Date.now()-new Date(U.startDate).getTime())/86400000)),L=U.sessions>0?Math.round(U.totalSessionTime/U.sessions):0,k=jC5(G);if($){console.log(JSON.stringify({...U,gitStats:K,daysSinceStart:W,avgSessionTime:L,cost:k},null,2));return}console.clear(),d4(b3.default.bgMagenta(b3.default.white(" \uD83D\uDCCA oh-my-agent stats ")));let H=[b3.default.bold(`\uD83D\uDCC8 Productivity Metrics (${W} days)`),"β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”",`β”‚ ${b3.default.bold("Metric")} β”‚ ${b3.default.bold("Value")} β”‚`,"β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€",`β”‚ Sessions β”‚ ${String(U.sessions).padEnd(12)} β”‚`,`β”‚ Tasks Completed β”‚ ${String(U.tasksCompleted).padEnd(12)} β”‚`,`β”‚ Files Changed β”‚ ${String(U.filesChanged).padEnd(12)} β”‚`,`β”‚ Lines Added β”‚ ${b3.default.green(`+${U.linesAdded}`.padEnd(12))} β”‚`,`β”‚ Lines Removed β”‚ ${b3.default.red(`-${U.linesRemoved}`.padEnd(12))} β”‚`,"β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜"].join(`
1638
1638
  `);if(G5(H,"Overview"),k.totalSpawns>0){let A=Object.entries(k.byVendor).sort(([,F],[,N])=>N.tokens-F.tokens).map(([F,N])=>` ${F.padEnd(12)} ${ST2(N.tokens).padStart(12)} tokens Β· ${String(N.spawns).padStart(3)} spawns Β· ${yT2(N.usd).padStart(7)}`),V=[b3.default.bold("\uD83D\uDCB0 Cost Telemetry (all sessions)"),"β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”",`β”‚ ${b3.default.bold("Metric")} β”‚ ${b3.default.bold("Value")} β”‚`,"β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€",`β”‚ Total tokens (est.) β”‚ ${ST2(k.totalTokens).padEnd(12)} β”‚`,`β”‚ Total spawns β”‚ ${String(k.totalSpawns).padEnd(12)} β”‚`,`β”‚ Estimated USD β”‚ ${yT2(k.estimatedUsd).padEnd(12)} β”‚`,"β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜",b3.default.dim("By vendor (sorted by tokens):"),...A,b3.default.dim("Estimate is input-only (prompt char approximation); output tokens not yet tracked."),b3.default.dim("Configure session.quota_cap in .agents/oma-config.yaml to enforce budgets.")].join(`
1639
1639
  `);G5(V,"Cost")}let B=Object.entries(U.skillsUsed).sort(([,A],[,V])=>V-A).slice(0,5);if(B.length>0){let A=[b3.default.bold("\uD83C\uDFC6 Top Skills Used"),...B.map(([V,F],N)=>` ${N+1}. ${V} (${F})`)].join(`
1640
- `);G5(A,"Skills")}T5(b3.default.dim(`Data stored in: ${J}`))}function iT2($){$3($.command("stats").description("View productivity metrics").option("--reset","Reset metrics data")).action(Y5(async(z)=>{await xT2(l1(z),z.reset)},{supportsJsonOutput:!0}))}K7();var c4=p2(I4(),1);import{execSync as lT2}from"node:child_process";import{cpSync as eD,existsSync as x9,mkdirSync as kH,readFileSync as cZ,rmSync as bd,writeFileSync as jU}from"node:fs";import{tmpdir as OC5}from"node:os";import{dirname as cT2,join as L3}from"node:path";var sD=p2(I4(),1);import{execSync as HC5,spawn as BC5}from"node:child_process";import{realpathSync as gT2}from"node:fs";import WH from"node:process";var ZU="oh-my-agent";function AC5($=WH.argv[1]){if(!$)return{packageManager:"unknown",isGlobal:!1};if(WH.env.IS_BINARY==="true")return{packageManager:"binary",isGlobal:!0,updateMessage:"Running as a standalone binary. Download the latest release from GitHub."};let z;try{z=Y9(gT2($))}catch{return{packageManager:"unknown",isGlobal:!1}}if(z.includes("/.npm/_npx")||z.includes("/npm/_npx"))return{packageManager:"npx",isGlobal:!1,updateMessage:"Running via npx, auto-update not applicable."};if(z.includes("/.pnpm/_pnpx")||z.includes("/.cache/pnpm/dlx"))return{packageManager:"pnpx",isGlobal:!1,updateMessage:"Running via pnpx, auto-update not applicable."};if(z.includes("/.bun/install/cache"))return{packageManager:"bunx",isGlobal:!1,updateMessage:"Running via bunx, auto-update not applicable."};if(WH.platform==="darwin")try{let G=HC5(`brew --prefix ${ZU}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(G){let J=Y9(gT2(G));if(z.startsWith(J))return{packageManager:"homebrew",isGlobal:!0,updateCommand:`brew upgrade ${ZU}`,updateMessage:"Installed via Homebrew. Updating in background..."}}}catch{}if(z.includes("/.pnpm/global")||z.includes("/.local/share/pnpm"))return{packageManager:"pnpm",isGlobal:!0,updateCommand:`pnpm add -g ${ZU}@latest`,updateMessage:"Installed via pnpm. Updating in background..."};if(z.includes("/.yarn/global"))return{packageManager:"yarn",isGlobal:!0,updateCommand:`yarn global add ${ZU}@latest`,updateMessage:"Installed via yarn. Updating in background..."};if(z.includes("/.bun/install/global"))return{packageManager:"bun",isGlobal:!0,updateCommand:`bun add -g ${ZU}@latest`,updateMessage:"Installed via bun. Updating in background..."};return{packageManager:"npm",isGlobal:!0,updateCommand:`npm install -g ${ZU}@latest`,updateMessage:"Installed via npm. Updating in background..."}}var mT2=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/;function VC5($,z){let G=$.match(mT2),J=z.match(mT2);if(!G||!J)return!1;for(let U=1;U<=3;U++){let K=Number(G[U]),X=Number(J[U]);if(K<X)return!0;if(K>X)return!1}return!1}async function FC5($=ZU,z=2000){try{let G=await h$.get(`https://registry.npmjs.org/${$}/latest`,{timeout:z});return typeof G.data?.version==="string"?G.data.version:null}catch{return null}}async function fT2($){if(!$.enabled)return{triggered:!1,reason:"disabled"};if(WH.env.OMA_SKIP_VERSION_CHECK==="1")return{triggered:!1,reason:"skipped-env"};if(WH.env.NODE_ENV==="development")return{triggered:!1,reason:"skipped-env"};let z=await FC5();if(!z)return{triggered:!1,reason:"fetch-failed"};if(!VC5($.currentVersion,z))return{triggered:!1,reason:"up-to-date",latest:z};let G=AC5();if(!G.updateCommand)return $.onNotice?.(sD.default.yellow(`global oh-my-agent ${$.currentVersion} β†’ ${z} available. ${G.updateMessage??"Update manually."}`)),{triggered:!1,reason:"non-upgradable",latest:z};try{return BC5(G.updateCommand,{stdio:"ignore",shell:!0,detached:!0}).unref(),$.onSpawnStart?.(sD.default.cyan(`global oh-my-agent ${$.currentVersion} β†’ ${z} updating in background. New version applies on next run.`)),{triggered:!0,latest:z}}catch{return $.onNotice?.(sD.default.yellow(`global oh-my-agent ${$.currentVersion} β†’ ${z} available. Run: ${G.updateCommand}`)),{triggered:!1,reason:"spawn-failed",latest:z}}}var tD={name:"oh-my-agent",version:"7.22.0",description:"Portable multi-agent harness for .agents-based skills and workflows across Antigravity, Claude Code, Codex, OpenCode, and more",type:"module",bin:{"oh-my-agent":"./bin/cli.js",oma:"./bin/cli.js"},files:["bin"],keywords:["oh-my-agent","antigravity",".agents","agent","skills","agent-skills","multi-agent","orchestrator","claude","claude-code","codex","opencode","copilot","cursor","chatgpt","pm","frontend","backend","mobile","qa","debug","terraform","database","workflow","bug-fixing","gemini"],author:"our.first.fluke <our.first.fluke@gmail.com>",contributors:["gracefullight <gracefullight.dev@gmail.com>","gahyun-git <go4it.gh@gmail.com>"],license:"MIT",funding:[{type:"github",url:"https://github.com/sponsors/first-fluke"},{type:"buymeacoffee",url:"https://buymeacoffee.com/firstfluke"}],scripts:{"sync:readme":"node ./scripts/sync-readme.mjs","generate:skill-data":"node ./scripts/generate-skill-data.mjs",build:"bun run generate:skill-data && bun run sync:readme && bun build cli.ts --outfile bin/cli.js --target node --minify --external @napi-rs/keyring",dev:"bun run generate:skill-data && bun run cli.ts",lint:"biome check .","lint:fix":"biome check --write --unsafe .","check:boundaries":"node ./scripts/check-boundaries.mjs",test:"vitest run","test:coverage":"vitest run --coverage",prepublishOnly:"bun run build"},dependencies:{"@clack/prompts":"^1.1.0","@date-fns/tz":"^1.4.1","@napi-rs/keyring":"^1.3.0",axios:"^1.15.0","better-sqlite3":"^12.9.0",chokidar:"^5.0.0",commander:"^14.0.3","date-fns":"^4.2.1",eld:"^2.0.3","fast-xml-parser":"^5",minimatch:"^10.2.5","p-map":"^7.0.4",picocolors:"^1.1.1","puppeteer-core":"^24",remark:"^15.0.1","remark-frontmatter":"^5.0.0","remark-parse":"^11.0.0","smol-toml":"^1.6.1",unified:"^11.0.5",ws:"^8.18.0",yaml:"^2.8.2",zod:"^4.3.6"},devDependencies:{"@biomejs/biome":"^2.4.15","@types/better-sqlite3":"^7.6.13","@types/mdast":"^4.0.4","@types/node":"^24","@types/ws":"^8.18.1","@vitest/coverage-v8":"^4.1.4",typescript:"^6",vitest:"^4.0.18"},repository:{type:"git",url:"https://github.com/first-fluke/oh-my-agent"},antigravity:{skillsPath:".agents/skills",skills:["oma-architecture","oma-brainstorm","oma-coordination","oma-pm","oma-frontend","oma-backend","oma-db","oma-mobile","oma-qa","oma-debug","oma-orchestrator","oma-dev-workflow","oma-tf-infra","oma-scm","oma-pdf","oma-recap"]}};function uC5($){if(!$)return{intro:(G)=>d4(G),outro:(G)=>T5(G),note:(G,J)=>G5(G,J),logError:(G)=>$4.error(G),spinnerStart:(G)=>{let J=E6();return J.start(G),J}};let z={start(G){},stop(G){if(G)console.log(G)},message(G){console.log(G)}};return{intro:(G)=>console.log(G),outro:(G)=>console.log(G),note:(G,J)=>console.log(G),logError:(G)=>console.error(G),spinnerStart:(G)=>{return console.log(G),z}}}function qC5($,z){if($!==null)return"ready";return z?"legacy":"missing"}async function wd($=!1,z=!1){if(!z&&process.stdout.isTTY)console.clear();let G=uC5(z);G.intro(c4.default.bgMagenta(c4.default.white(" \uD83D\uDEF8 oh-my-agent update ")));let J=process.cwd();await fT2({currentVersion:tD.version,enabled:S82(J),onSpawnStart:(Y)=>G.note(Y,"CLI auto-update"),onNotice:(Y)=>G.note(Y,"CLI update available")});let U=await hF(J),K=I82(J),X=qC5(U,K);if(X==="missing"){if(G.logError("oh-my-agent is not installed in this project. Run `oma install` first."),z)throw Error("oh-my-agent is not installed in this project. Run `oma install` first.");process.exit(1)}let Q=nG(J);if(Q.length>0)G.note(Q.map((Y)=>`${c4.default.green("βœ“")} ${Y}`).join(`
1640
+ `);G5(A,"Skills")}T5(b3.default.dim(`Data stored in: ${J}`))}function iT2($){$3($.command("stats").description("View productivity metrics").option("--reset","Reset metrics data")).action(Y5(async(z)=>{await xT2(l1(z),z.reset)},{supportsJsonOutput:!0}))}K7();var c4=p2(I4(),1);import{execSync as lT2}from"node:child_process";import{cpSync as eD,existsSync as x9,mkdirSync as kH,readFileSync as cZ,rmSync as bd,writeFileSync as jU}from"node:fs";import{tmpdir as OC5}from"node:os";import{dirname as cT2,join as L3}from"node:path";var sD=p2(I4(),1);import{execSync as HC5,spawn as BC5}from"node:child_process";import{realpathSync as gT2}from"node:fs";import WH from"node:process";var ZU="oh-my-agent";function AC5($=WH.argv[1]){if(!$)return{packageManager:"unknown",isGlobal:!1};if(WH.env.IS_BINARY==="true")return{packageManager:"binary",isGlobal:!0,updateMessage:"Running as a standalone binary. Download the latest release from GitHub."};let z;try{z=Y9(gT2($))}catch{return{packageManager:"unknown",isGlobal:!1}}if(z.includes("/.npm/_npx")||z.includes("/npm/_npx"))return{packageManager:"npx",isGlobal:!1,updateMessage:"Running via npx, auto-update not applicable."};if(z.includes("/.pnpm/_pnpx")||z.includes("/.cache/pnpm/dlx"))return{packageManager:"pnpx",isGlobal:!1,updateMessage:"Running via pnpx, auto-update not applicable."};if(z.includes("/.bun/install/cache"))return{packageManager:"bunx",isGlobal:!1,updateMessage:"Running via bunx, auto-update not applicable."};if(WH.platform==="darwin")try{let G=HC5(`brew --prefix ${ZU}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(G){let J=Y9(gT2(G));if(z.startsWith(J))return{packageManager:"homebrew",isGlobal:!0,updateCommand:`brew upgrade ${ZU}`,updateMessage:"Installed via Homebrew. Updating in background..."}}}catch{}if(z.includes("/.pnpm/global")||z.includes("/.local/share/pnpm"))return{packageManager:"pnpm",isGlobal:!0,updateCommand:`pnpm add -g ${ZU}@latest`,updateMessage:"Installed via pnpm. Updating in background..."};if(z.includes("/.yarn/global"))return{packageManager:"yarn",isGlobal:!0,updateCommand:`yarn global add ${ZU}@latest`,updateMessage:"Installed via yarn. Updating in background..."};if(z.includes("/.bun/install/global"))return{packageManager:"bun",isGlobal:!0,updateCommand:`bun add -g ${ZU}@latest`,updateMessage:"Installed via bun. Updating in background..."};return{packageManager:"npm",isGlobal:!0,updateCommand:`npm install -g ${ZU}@latest`,updateMessage:"Installed via npm. Updating in background..."}}var mT2=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/;function VC5($,z){let G=$.match(mT2),J=z.match(mT2);if(!G||!J)return!1;for(let U=1;U<=3;U++){let K=Number(G[U]),X=Number(J[U]);if(K<X)return!0;if(K>X)return!1}return!1}async function FC5($=ZU,z=2000){try{let G=await h$.get(`https://registry.npmjs.org/${$}/latest`,{timeout:z});return typeof G.data?.version==="string"?G.data.version:null}catch{return null}}async function fT2($){if(!$.enabled)return{triggered:!1,reason:"disabled"};if(WH.env.OMA_SKIP_VERSION_CHECK==="1")return{triggered:!1,reason:"skipped-env"};if(WH.env.NODE_ENV==="development")return{triggered:!1,reason:"skipped-env"};let z=await FC5();if(!z)return{triggered:!1,reason:"fetch-failed"};if(!VC5($.currentVersion,z))return{triggered:!1,reason:"up-to-date",latest:z};let G=AC5();if(!G.updateCommand)return $.onNotice?.(sD.default.yellow(`global oh-my-agent ${$.currentVersion} β†’ ${z} available. ${G.updateMessage??"Update manually."}`)),{triggered:!1,reason:"non-upgradable",latest:z};try{return BC5(G.updateCommand,{stdio:"ignore",shell:!0,detached:!0}).unref(),$.onSpawnStart?.(sD.default.cyan(`global oh-my-agent ${$.currentVersion} β†’ ${z} updating in background. New version applies on next run.`)),{triggered:!0,latest:z}}catch{return $.onNotice?.(sD.default.yellow(`global oh-my-agent ${$.currentVersion} β†’ ${z} available. Run: ${G.updateCommand}`)),{triggered:!1,reason:"spawn-failed",latest:z}}}var tD={name:"oh-my-agent",version:"7.23.1",description:"Portable multi-agent harness for .agents-based skills and workflows across Antigravity, Claude Code, Codex, OpenCode, and more",type:"module",bin:{"oh-my-agent":"./bin/cli.js",oma:"./bin/cli.js"},files:["bin"],keywords:["oh-my-agent","antigravity",".agents","agent","skills","agent-skills","multi-agent","orchestrator","claude","claude-code","codex","opencode","copilot","cursor","chatgpt","pm","frontend","backend","mobile","qa","debug","terraform","database","workflow","bug-fixing","gemini"],author:"our.first.fluke <our.first.fluke@gmail.com>",contributors:["gracefullight <gracefullight.dev@gmail.com>","gahyun-git <go4it.gh@gmail.com>"],license:"MIT",funding:[{type:"github",url:"https://github.com/sponsors/first-fluke"},{type:"buymeacoffee",url:"https://buymeacoffee.com/firstfluke"}],scripts:{"sync:readme":"node ./scripts/sync-readme.mjs","generate:skill-data":"node ./scripts/generate-skill-data.mjs",build:"bun run generate:skill-data && bun run sync:readme && bun build cli.ts --outfile bin/cli.js --target node --minify --external @napi-rs/keyring",dev:"bun run generate:skill-data && bun run cli.ts",lint:"biome check .","lint:fix":"biome check --write --unsafe .","check:boundaries":"node ./scripts/check-boundaries.mjs",test:"vitest run","test:coverage":"vitest run --coverage",prepublishOnly:"bun run build"},dependencies:{"@clack/prompts":"^1.1.0","@date-fns/tz":"^1.4.1","@napi-rs/keyring":"^1.3.0",axios:"^1.15.0","better-sqlite3":"^12.9.0",chokidar:"^5.0.0",commander:"^14.0.3","date-fns":"^4.2.1",eld:"^2.0.3","fast-xml-parser":"^5",minimatch:"^10.2.5","p-map":"^7.0.4",picocolors:"^1.1.1","puppeteer-core":"^24",remark:"^15.0.1","remark-frontmatter":"^5.0.0","remark-parse":"^11.0.0","smol-toml":"^1.6.1",unified:"^11.0.5",ws:"^8.18.0",yaml:"^2.8.2",zod:"^4.3.6"},devDependencies:{"@biomejs/biome":"^2.4.15","@types/better-sqlite3":"^7.6.13","@types/mdast":"^4.0.4","@types/node":"^24","@types/ws":"^8.18.1","@vitest/coverage-v8":"^4.1.4",typescript:"^6",vitest:"^4.0.18"},repository:{type:"git",url:"https://github.com/first-fluke/oh-my-agent"},antigravity:{skillsPath:".agents/skills",skills:["oma-architecture","oma-brainstorm","oma-coordination","oma-pm","oma-frontend","oma-backend","oma-db","oma-mobile","oma-qa","oma-debug","oma-orchestrator","oma-dev-workflow","oma-tf-infra","oma-scm","oma-pdf","oma-recap"]}};function uC5($){if(!$)return{intro:(G)=>d4(G),outro:(G)=>T5(G),note:(G,J)=>G5(G,J),logError:(G)=>$4.error(G),spinnerStart:(G)=>{let J=E6();return J.start(G),J}};let z={start(G){},stop(G){if(G)console.log(G)},message(G){console.log(G)}};return{intro:(G)=>console.log(G),outro:(G)=>console.log(G),note:(G,J)=>console.log(G),logError:(G)=>console.error(G),spinnerStart:(G)=>{return console.log(G),z}}}function qC5($,z){if($!==null)return"ready";return z?"legacy":"missing"}async function wd($=!1,z=!1){if(!z&&process.stdout.isTTY)console.clear();let G=uC5(z);G.intro(c4.default.bgMagenta(c4.default.white(" \uD83D\uDEF8 oh-my-agent update ")));let J=process.cwd();await fT2({currentVersion:tD.version,enabled:S82(J),onSpawnStart:(Y)=>G.note(Y,"CLI auto-update"),onNotice:(Y)=>G.note(Y,"CLI update available")});let U=await hF(J),K=I82(J),X=qC5(U,K);if(X==="missing"){if(G.logError("oh-my-agent is not installed in this project. Run `oma install` first."),z)throw Error("oh-my-agent is not installed in this project. Run `oma install` first.");process.exit(1)}let Q=nG(J);if(Q.length>0)G.note(Q.map((Y)=>`${c4.default.green("βœ“")} ${Y}`).join(`
1641
1641
  `),"Migration");let Z=Q.length>0||Yy(J);if(Q.length>0&&!Yy(J))Wy(J,!0);if(!z)await gF(J);if(X==="legacy")G.note("Existing .agents installation detected without _version.json. Updating in place and restoring version metadata.","Legacy install");let j;try{j=G.spinnerStart("Checking for updates...");let Y=await b82();if(U===Y.version&&!Z){j.stop(c4.default.green("Already up to date!")),G.outro(`Current version: ${c4.default.cyan(U)}`);return}let W=U===Y.version;j.message(`Downloading ${c4.default.cyan(Y.version)}...`);let{dir:L,cleanup:k}=await pK();try{j.message("Copying files..."),nG(J);let H=L3(J,".agents","oma-config.yaml"),B=L3(J,".agents","mcp.json"),A=!$&&x9(H)?cZ(H):null,V=!$&&x9(B)?cZ(B):null,F=L3(OC5(),`oma-stack-backup-${Date.now()}`),N=L3(J,".agents","skills","oma-backend","stack"),O=!$&&x9(N);if(O)kH(F,{recursive:!0}),eD(N,L3(F,"oma-backend"),{recursive:!0});let q=["snippets.md","tech-stack.md","api-template.py"],I=L3(J,".agents","skills","oma-backend","resources"),D=!$&&!O&&q.some((J2)=>x9(L3(I,J2))),M=ky(J);if(eD(L3(L,".agents"),L3(J,".agents"),{recursive:!0,force:!0}),A)jU(H,A);if(V)jU(B,V);if(O)try{kH(N,{recursive:!0}),eD(L3(F,"oma-backend"),N,{recursive:!0,force:!0})}finally{bd(F,{recursive:!0,force:!0})}if(D){let J2=L3(L,".agents","skills","oma-backend","variants","python");if(x9(J2))kH(N,{recursive:!0}),eD(J2,N,{recursive:!0,force:!0}),jU(L3(N,"stack.yaml"),`language: python
1642
1642
  framework: fastapi
1643
1643
  orm: sqlalchemy
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-agent",
3
- "version": "7.22.0",
3
+ "version": "7.23.1",
4
4
  "description": "Portable multi-agent harness for .agents-based skills and workflows across Antigravity, Claude Code, Codex, OpenCode, and more",
5
5
  "type": "module",
6
6
  "bin": {