oh-my-agent 7.0.0 → 7.1.0

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 (2) hide show
  1. package/bin/cli.js +1 -1
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -1446,7 +1446,7 @@ print(json.dumps({
1446
1446
  }))
1447
1447
  `;function HA$(){return process.env.OMA_PYTHON??"python3"}function qA$($){if(UA$.some((J)=>$===J||$.endsWith(`.${J}`)))return["safari","chrome","firefox"];return["chrome","safari","firefox"]}async function VA$($,J,X){return new Promise((G)=>{let Q=KA$(HA$(),["-c",WA$],{env:{...process.env,OMA_IMPERSONATE_URL:$.toString(),OMA_IMPERSONATE_TARGET:J,OMA_IMPERSONATE_LOCALE:X.locale,OMA_IMPERSONATE_TIMEOUT:String(X.timeoutMs)},stdio:["ignore","pipe","pipe"]}),Y="",Z="";Q.stdout.on("data",(U)=>{Y+=U.toString()}),Q.stderr.on("data",(U)=>{Z+=U.toString()});let K=()=>{Q.kill("SIGTERM")};X.signal?.addEventListener("abort",K),Q.on("close",(U)=>{if(X.signal?.removeEventListener("abort",K),U!==0&&!Y){G({error:`python_exit:${U}:${Z.trim().slice(0,200)}`});return}let W=Y.trim();if(!W){G({error:"empty_stdout"});return}try{G(JSON.parse(W))}catch(H){G({error:`parse_error:${H.message}:${W.slice(0,200)}`})}}),Q.on("error",(U)=>{X.signal?.removeEventListener("abort",K),G({error:`spawn_error:${U.message}`})})})}function zA$($,J,X){let G=new Headers;if($.headers)for(let[Q,Y]of Object.entries($.headers))try{G.set(Q,Y)}catch{}return{ok:($.status??0)>=200&&($.status??0)<400,status:$.status??0,headers:G,url:$.url??J,text:$.body??"",elapsedMs:X,redirected:($.url??J)!==J}}async function $M0($,J){let X=qA$($.hostname),G=[],Q=performance.now();for(let K of X){if(J.signal?.aborted)break;let U=performance.now(),W=await VA$($,K,J),H=Math.round(performance.now()-U);if(W.error==="curl_cffi_not_installed")return S6({url:$.toString(),strategy:"impersonate",error:Error("curl_cffi is not installed. Run: pip install curl_cffi")});if(W.error){G.push({target:K,detail:W.error});continue}let q=zA$(W,$.toString(),H),z=e4(q);if(l70(z))return{url:$.toString(),status:"blocked",strategy:"impersonate",platform:K,httpStatus:q.status,content:q.text,contentType:q.headers.get("content-type")??void 0,elapsedMs:Math.round(performance.now()-Q),signals:z,error:"js-essential-markers-detected"};if(q.ok&&q.text.length>=200)return{url:$.toString(),status:I9(q,z),strategy:"impersonate",platform:K,httpStatus:q.status,content:q.text,contentType:q.headers.get("content-type")??void 0,elapsedMs:Math.round(performance.now()-Q),signals:z};G.push({target:K,detail:`status=${q.status} size=${q.text.length}`})}let Y=Math.round(performance.now()-Q),Z=G.map((K)=>`${K.target}(${K.detail})`).join(" | ");return{...S6({url:$.toString(),strategy:"impersonate",error:Error(Z?`impersonate_failed: ${Z}`:"impersonate_failed")}),elapsedMs:Y,signals:[]}}var JM0="https://r.jina.ai/";function BA$($){let J=`${$.protocol}//${$.hostname}`,X=$.hostname.startsWith("m.")?$.hostname:`m.${$.hostname.replace(/^www\./,"")}`,G=new URL($.toString());return G.hostname=X,[{label:"jina",url:`${JM0}${$.toString()}`,headers:jG({accept:"text/plain"})},{label:"jina-json",url:`${JM0}${$.toString()}`,headers:jG({accept:"application/json"})},{label:"curl-desktop",url:$.toString(),headers:jG({userAgent:s5.desktopFirefox,referer:J})},{label:"curl-mobile",url:G.toString(),headers:jG({userAgent:s5.mobileSafari,referer:J})},{label:"curl-googlebot",url:$.toString(),headers:jG({userAgent:s5.googlebot})}]}function LA$($,J){if(!$.startsWith("jina"))return J;return J}async function XM0($,J){let X=BA$($),G=new AbortController;if(J.signal)if(J.signal.aborted)G.abort(J.signal.reason);else J.signal.addEventListener("abort",()=>G.abort(J.signal?.reason));let Q=performance.now(),Y={},Z=null,K=X.map(async(U)=>{let W=await f6(U.url,{headers:U.headers,timeoutMs:J.timeoutMs,signal:G.signal,locale:J.locale}),H=e4(W);if(U.label.startsWith("jina")){let q=c70(W);if(q)throw Z=q,Error(`jina-quota:${q.detail}`)}if(!OA$(W,H))throw Y[U.label]=`status=${W.status} size=${W.text.length}`,Error(`weak-response:${U.label}`);return{label:U.label,resp:W,signals:H}});try{let U=await Promise.any(K);G.abort();let W=Math.round(performance.now()-Q);return{url:$.toString(),status:I9(U.resp,U.signals),strategy:"probe",platform:U.label,httpStatus:U.resp.status,content:LA$(U.label,U.resp.text),contentType:U.resp.headers.get("content-type")??void 0,elapsedMs:W,signals:Z?[...U.signals,Z]:U.signals}}catch(U){let W=Math.round(performance.now()-Q),H=Object.entries(Y).map(([q,z])=>`${q}:${z}`).join(" ");if(Z)return{...S6({url:$.toString(),error:Error(`probe failed — ${H}`),strategy:"probe"}),elapsedMs:W,signals:[Z]};return{...S6({url:$.toString(),error:U instanceof AggregateError?Error(H):U,strategy:"probe"}),elapsedMs:W}}}function OA$($,J){if(!$.ok)return!1;if($.text.length<200)return!1;if(J.some((X)=>X.kind==="waf-body"||X.kind==="challenge-body"||X.kind==="js-essential"||X.kind==="http-status"))return!1;return!0}var FA$=["api","probe","impersonate","browser","archive"];function NA$($){if($.only?.length)return $.only;let J=FA$.slice();if(!$.includeArchive)J=J.filter((X)=>X!=="archive");if($.skip?.length)J=J.filter((X)=>!$.skip?.includes(X));return J}async function GM0($,J,X){switch($){case"api":return await gN(J,X)??null;case"probe":return XM0(J,X);case"impersonate":return $M0(J,X);case"browser":return eA0(J,X);case"archive":return bH(J,X)}}function Pp($){if($.status==="ok")return!0;if($.status==="auth-required"&&d70($.signals))return!0;return!1}function AA$($){return $.status==="auth-required"||$.status==="invalid-input"||$.status==="not-found"}async function MA$($){let J=Math.floor(Math.random()*500);await new Promise((X)=>setTimeout(X,$+J))}function DA$($){let J=$.find((Q)=>Q.kind==="rate-limit");if(!J)return 1500;let X=J.detail.match(/retry-after=(\d+)/);if(!X?.[1])return 1500;let G=Number.parseInt(X[1],10);if(Number.isNaN(G)||G>10)return 1500;return G*1000}async function QM0($,J,X={}){let G=NA$(X),Q=[],Y=new Set,Z=null,K=!1;for(let U of G){if(J.signal?.aborted)break;if(K&&U==="impersonate")continue;let W=await GM0(U,$,J);if(!W)continue;if(Q.push({strategy:U,platform:W.platform,status:W.status,httpStatus:W.httpStatus,elapsedMs:W.elapsedMs,signals:W.signals,error:W.error}),W.signals.some((H)=>H.kind==="js-essential"))K=!0;if(Pp(W))return W.attempts=Q,W;if(AA$(W))return W.attempts=Q,W;if(X.retryOnRateLimit!==!1&&i70(W.signals)&&!Y.has(U)){Y.add(U),await MA$(DA$(W.signals));let H=await GM0(U,$,J);if(H){if(Q.push({strategy:U,platform:H.platform,status:H.status,httpStatus:H.httpStatus,elapsedMs:H.elapsedMs,signals:H.signals,error:H.error}),Pp(H))return H.attempts=Q,H;Z=H;continue}}Z=W}if(!G.includes("archive")&&X.includeArchive!==!1){let U=await bH($,J);if(Q.push({strategy:"archive",platform:U.platform,status:U.status,httpStatus:U.httpStatus,elapsedMs:U.elapsedMs,signals:U.signals,error:U.error}),Pp(U))return U.attempts=Q,U;Z=U}if(Z)return Z.attempts=Q,Z;return{url:$.toString(),status:"error",strategy:G[0]??"probe",content:"",elapsedMs:0,signals:[],attempts:Q,error:"all strategies failed"}}var lM0=i0(cM0(),1);var dM$=["/rss","/feed","/atom.xml","/rss.xml","/index.xml"],iM$=new lM0.XMLParser({ignoreAttributes:!1,attributeNamePrefix:"@_",textNodeName:"#text"});function yp($){if($===void 0||$===null)return[];return Array.isArray($)?$:[$]}function N4($){if($==null)return;if(typeof $==="string")return $;if(typeof $==="object"){let J=$;if(typeof J["#text"]==="string")return J["#text"];if(typeof J["#cdata"]==="string")return J["#cdata"]}return}function pM0($){for(let J of yp($)){let X=J?.["@_href"],G=J?.["@_rel"];if(typeof X==="string"&&(G===void 0||G==="alternate"))return X}return}function dM0($){let J;try{J=iM$.parse($)}catch{return null}let X=J.rss;if(X){let Q=X.channel;if(!Q)return null;let Y=yp(Q.item);return{kind:"rss",title:N4(Q.title),description:N4(Q.description),link:N4(Q.link),entries:Y.map((Z)=>({title:N4(Z.title),link:N4(Z.link),pubDate:N4(Z.pubDate),description:N4(Z.description),content:N4(Z["content:encoded"])??N4(Z.content)}))}}let G=J.feed;if(G){let Q=yp(G.entry);return{kind:"atom",title:N4(G.title),description:N4(G.subtitle),link:pM0(G.link),entries:Q.map((Y)=>({title:N4(Y.title),link:pM0(Y.link),pubDate:N4(Y.published)??N4(Y.updated),description:N4(Y.summary),content:N4(Y.content)??N4(Y.summary)}))}}return null}async function iM0($,J){let X=performance.now(),G;try{let Y=await f6($.toString(),{timeoutMs:J.timeoutMs,locale:J.locale,signal:J.signal});if(Y.ok)G=fN(Y.text).alternate?.[0]?.href}catch{}let Q=new Set;if(G)try{Q.add(new URL(G,$).toString())}catch{}for(let Y of dM$)Q.add(new URL(Y,`${$.protocol}//${$.host}`).toString());for(let Y of Q){if(J.signal?.aborted)break;try{let Z=await f6(Y,{timeoutMs:J.timeoutMs,locale:J.locale,signal:J.signal});if(!Z.ok||Z.text.length<50)continue;let K=dM0(Z.text);if(!K||K.entries.length===0)continue;return{url:$.toString(),status:"ok",strategy:"probe",platform:"rss",httpStatus:Z.status,content:Z.text,contentType:Z.headers.get("content-type")??void 0,elapsedMs:Math.round(performance.now()-X),signals:[],feedUrl:Y,feed:K}}catch{}}return{url:$.toString(),status:"not-found",strategy:"probe",platform:"rss",content:"",elapsedMs:Math.round(performance.now()-X),signals:[],error:"no RSS/Atom feed discovered"}}function nM0($,J="en-US"){let[X,G]=J.split("-"),Q=new URL("https://news.google.com/rss/search");return Q.searchParams.set("q",$),Q.searchParams.set("hl",X??"en"),Q.searchParams.set("gl",G??"US"),Q.searchParams.set("ceid",`${G??"US"}:${X??"en"}`),Q.toString()}var VI={"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 nM$($){return $.replace(/^www\./,"")}function oM$($){if($ in VI){let X=VI[$];return X?{...X}:null}let J=nM$($);if(J in VI){let X=VI[J];return X?{...X}:null}return null}function aM$($){let J=$.split(".").pop();if(J==="gov"||J==="edu"||J==="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 rM$($){try{let J=await f6(`https://tranco-list.eu/api/ranks/domain/${$}`,{timeoutMs:5000});if(!J.ok)return null;let G=JSON.parse(J.text).ranks?.[0]?.rank;if(!G)return null;let Q=G<1e4?0.6:G<1e5?0.4:0.2;return{domain:$,level:G<1e4?"community":"external",score:Q,tags:["tranco"],source:"tranco",rank:G}}catch{return null}}async function oM0($){let J=oM$($);if(J)return J;let X=aM$($);if(X)return X;let G=await rM$($);if(G)return G;return{domain:$,level:"unknown",score:null,tags:[],source:"heuristic"}}var aM0=["api","probe","impersonate","browser","archive"];function rM0($){if(!$)return;let J=$.split(",").map((G)=>G.trim()).filter(Boolean),X=J.filter((G)=>!aM0.includes(G));if(X.length>0)throw Error(`Unknown strategy: ${X.join(", ")}. Valid: ${aM0.join(", ")}`);return J}function XU($){try{return new URL($)}catch{throw Error(`Invalid URL: ${$}`)}}function F3($){return{timeoutMs:$.timeout?Math.max(1000,Math.floor(Number($.timeout)*1000)):15000,locale:$.locale??"en-US,en;q=0.9"}}function DJ($,J){if(J)console.log(JSON.stringify($,null,2));else console.log(JSON.stringify($))}function SQ($){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 sM0($){let J=$.command("search").description("Mechanical search primitives — fetch, meta, rss, media, trust, code").alias("s");J.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(X,G)=>{try{let Q=XU(X),Y=F3(G),Z=await QM0(Q,Y,{only:rM0(G.only),skip:rM0(G.skip),includeArchive:G.includeArchive});DJ(Z,Boolean(G.pretty)),SQ(Z)}catch(Q){console.error(O7.default.red(Q.message)),process.exitCode=1}}),J.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(X,G)=>{try{let Q=XU(X);if(!wk(Q)){console.error(O7.default.yellow(`No API handler matches host ${Q.hostname}`)),process.exitCode=3;return}let Z=F3(G),K=await gN(Q,Z);if(!K){process.exitCode=3;return}DJ(K,Boolean(G.pretty)),SQ(K)}catch(Q){console.error(O7.default.red(Q.message)),process.exitCode=1}}),J.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(X,G)=>{let Q=F3(G),Y=G.platforms?G.platforms.split(",").map((K)=>K.trim()).filter(Boolean):void 0,Z=await VJ0(X,Q,Y);DJ(Z,Boolean(G.pretty))}),J.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(X,G)=>{try{let Q=XU(X),Y=F3(G),Z=await m70(Q,Y),{content:K,...U}=Z;DJ(U,Boolean(G.pretty)),SQ(Z)}catch(Q){console.error(O7.default.red(Q.message)),process.exitCode=1}}),J.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(X,G)=>{try{let Q=XU(X),Y=F3(G),Z=await iM0(Q,Y),{content:K,...U}=Z;DJ(U,Boolean(G.pretty)),SQ(Z)}catch(Q){console.error(O7.default.red(Q.message)),process.exitCode=1}}),J.command("rss:google <query>").description("Build Google News RSS URL for a query").option("--locale <value>","Locale (e.g., ko-KR)","en-US").action((X,G)=>{let Q=nM0(X,G.locale??"en-US");console.log(Q)}),J.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(X,G)=>{try{let Q=XU(X),Y=F3(G),Z=G.subLang?G.subLang.split(",").map((U)=>U.trim()).filter(Boolean):void 0,K=await f70(Q,Y,{subtitles:G.subs,...Z?{subLangs:Z}:{},...G.format?{format:G.format}:{}});DJ(K,Boolean(G.pretty)),SQ(K)}catch(Q){console.error(O7.default.red(Q.message)),process.exitCode=1}}),J.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(X,G)=>{try{let Q=XU(X),Y=F3(G),Z=await bH(Q,Y);DJ(Z,Boolean(G.pretty)),SQ(Z)}catch(Q){console.error(O7.default.red(Q.message)),process.exitCode=1}}),J.command("trust <domain>").description("Resolve trust level / score for a domain").option("--pretty","Pretty-print JSON").action(async(X,G)=>{let Q=await oM0(X.toLowerCase());DJ(Q,Boolean(G.pretty))}),J.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(X,G)=>{let Q=G.host==="gitlab"||G.host==="github"?G.host:"github",Y=F3({}),Z=await u70(X,Y,{host:Q,...G.language?{language:G.language}:{},...G.repo?{repo:G.repo}:{},...G.limit?{limit:Number.parseInt(G.limit,10)}:{}});DJ(Z,Boolean(G.pretty)),SQ(Z)}),J.command("doctor").description("Check dependencies (Chrome, python3 curl_cffi, yt-dlp, gh)").action(async()=>{let X=[],G=jp();X.push({name:"chrome",ok:Boolean(G),detail:G??"Install Chrome or set OMA_CHROME_PATH"}),X.push(await kp("python3",["--version"])),X.push(await sM$()),X.push(await kp("yt-dlp",["--version"])),X.push(await kp("gh",["--version"]));for(let Q of X){let Y=Q.ok?O7.default.green("✓"):O7.default.yellow("!");console.log(`${Y} ${Q.name}: ${Q.detail}`)}if(X.some((Q)=>!Q.ok))process.exitCode=1})}async function kp($,J){return new Promise((X)=>{let{spawn:G}=Y0("node:child_process"),Q=G($,J,{stdio:["ignore","pipe","pipe"]}),Y="";Q.stdout?.on("data",(Z)=>{Y+=Z.toString()}),Q.on("error",()=>X({name:$,ok:!1,detail:"not found"})),Q.on("close",(Z)=>{if(Z===0)X({name:$,ok:!0,detail:Y.trim()});else X({name:$,ok:!1,detail:`exit code ${Z}`})})})}async function sM$(){return new Promise(($)=>{let{spawn:J}=Y0("node:child_process"),X=J("python3",["-c","import curl_cffi; print(curl_cffi.__version__)"],{stdio:["ignore","pipe","pipe"]}),G="";X.stdout?.on("data",(Q)=>{G+=Q.toString()}),X.on("error",()=>$({name:"curl_cffi",ok:!1,detail:"python3 not found"})),X.on("close",(Q)=>{if(Q===0)$({name:"curl_cffi",ok:!0,detail:`v${G.trim()}`});else $({name:"curl_cffi",ok:!1,detail:"not installed (pip install curl_cffi)"})})})}N8();var N3=i0(M1(),1);import{execSync as tM$,spawnSync as tM0}from"node:child_process";import{platform as eM$}from"node:os";function $D$(){let $=eM$();if($==="darwin")return"brew install gh";if($==="win32")return"winget install GitHub.cli";return"sudo apt install gh"}async function eM0(){if(console.clear(),u1(N3.default.bgMagenta(N3.default.white(" ⭐ oh-my-agent star "))),!d3()){let J=$D$(),X=await U4({message:`GitHub CLI (gh) is not installed. Install with ${N3.default.cyan(J)}?`});if(q1(X)||!X){P$("Install gh manually and try again.");return}let G=z9();G.start("Installing GitHub CLI...");let Q=tM0(J,{shell:!0,stdio:"pipe"});if(Q.status!==0){G.stop("Installation failed"),s$.error(Q.stderr?.toString()||"Unknown error"),P$("Please install gh manually.");return}G.stop("GitHub CLI installed!")}if(!p5()){s$.warn("GitHub CLI is not authenticated.");let J=await U4({message:`Run ${N3.default.cyan("gh auth login")} now?`});if(q1(J)||!J){P$("Authenticate and try again.");return}if(tM0("gh",["auth","login"],{stdio:"inherit"}),!p5()){P$("Authentication was not completed. Try again.");return}s$.success("Authenticated!")}if(i3()){P$(`Already starred ${N3.default.cyan(s1)}! Thank you! \uD83D\uDE4F`);return}let $=await U4({message:`Star ${N3.default.cyan(s1)} on GitHub?`});if(q1($)||!$){P$("Maybe next time!");return}try{tM$(`gh api -X PUT /user/starred/${s1}`,{stdio:"ignore"}),P$(`Starred ${N3.default.cyan(s1)}! Thank you! \uD83C\uDF1F`)}catch{s$.error("Failed to star the repository."),P$("Please try again later.")}}function $D0($){$.command("star").description("Star oh-my-agent on GitHub").action(V$(async()=>{await eM0()}))}N8();Fk();OW();var T5=i0(M1(),1);import{existsSync as zI,mkdirSync as JD$,readdirSync as XD$,readFileSync as GD$,writeFileSync as JD0}from"node:fs";import{dirname as QD$,join as XD0}from"node:path";function up($){return XD0($,".serena","metrics.json")}function hp(){return{sessions:0,skillsUsed:{},tasksCompleted:0,totalSessionTime:0,filesChanged:0,linesAdded:0,linesRemoved:0,lastUpdated:new Date().toISOString(),startDate:new Date().toISOString()}}function YD$($){let J=up($);if(zI(J))try{return JSON.parse(GD$(J,"utf-8"))}catch{return hp()}return hp()}function ZD$($,J){let X=up($),G=QD$(X);if(!zI(G))JD$(G,{recursive:!0});J.lastUpdated=new Date().toISOString(),JD0(X,JSON.stringify(J,null,2),"utf-8")}function KD$($){let J=XD0($,".serena","memories"),X={};if(!zI(J))return X;try{let G=XD$(J);for(let Q of G){let Y=Q.match(/(?:progress|result)-(\w+)/);if(Y?.[1]){let Z=Y[1];X[Z]=(X[Z]||0)+1}}}catch{}return X}async function GD0($=!1,J=!1){let X=process.cwd(),G=up(X);if(J){if(zI(G))JD0(G,JSON.stringify(hp(),null,2),"utf-8");if($)console.log(JSON.stringify({reset:!0}));else console.log(T5.default.green("✅ Metrics reset successfully."));return}let Q=YD$(X),Y=SN(X),Z=KD$(X),K=Ra(X),U=gL(X),W=U.startedAt?new Date(U.startedAt):null,H=W&&!Number.isNaN(W.getTime())?Math.max(0,Math.floor((Date.now()-W.getTime())/1000)):0;for(let[L,O]of Object.entries(Z))Q.skillsUsed[L]=(Q.skillsUsed[L]||0)+O;if(K>Q.tasksCompleted)Q.tasksCompleted=K;if(U.id){if(["completed","failed","aborted"].includes(U.status||"")&&(Q.lastSessionId!==U.id||Q.lastSessionStatus!==U.status)&&H>0)Q.totalSessionTime+=H;Q.lastSessionId=U.id,Q.lastSessionStatus=U.status,Q.lastSessionStarted=U.startedAt,Q.lastSessionDuration=H}Q.filesChanged+=Y.filesChanged,Q.linesAdded+=Y.linesAdded,Q.linesRemoved+=Y.linesRemoved,Q.sessions+=1,ZD$(X,Q);let q=Math.max(1,Math.ceil((Date.now()-new Date(Q.startDate).getTime())/86400000)),z=Q.sessions>0?Math.round(Q.totalSessionTime/Q.sessions):0;if($){console.log(JSON.stringify({...Q,gitStats:Y,daysSinceStart:q,avgSessionTime:z},null,2));return}console.clear(),u1(T5.default.bgMagenta(T5.default.white(" \uD83D\uDCCA oh-my-agent stats ")));let V=[T5.default.bold(`\uD83D\uDCC8 Productivity Metrics (${q} days)`),"┌─────────────────────┬──────────────┐",`│ ${T5.default.bold("Metric")} │ ${T5.default.bold("Value")} │`,"├─────────────────────┼──────────────┤",`│ Sessions │ ${String(Q.sessions).padEnd(12)} │`,`│ Tasks Completed │ ${String(Q.tasksCompleted).padEnd(12)} │`,`│ Files Changed │ ${String(Q.filesChanged).padEnd(12)} │`,`│ Lines Added │ ${T5.default.green(`+${Q.linesAdded}`).padEnd(12)} │`,`│ Lines Removed │ ${T5.default.red(`-${Q.linesRemoved}`).padEnd(12)} │`,"└─────────────────────┴──────────────┘"].join(`
1448
1448
  `);G$(V,"Overview");let B=Object.entries(Q.skillsUsed).sort(([,L],[,O])=>O-L).slice(0,5);if(B.length>0){let L=[T5.default.bold("\uD83C\uDFC6 Top Skills Used"),...B.map(([O,F],N)=>` ${N+1}. ${O} (${F})`)].join(`
1449
- `);G$(L,"Skills")}P$(T5.default.dim(`Data stored in: ${G}`))}function QD0($){n6($.command("stats").description("View productivity metrics").option("--reset","Reset metrics data")).action(V$(async(J)=>{await GD0(h6(J),J.reset)},{supportsJsonOutput:!0}))}N8();var u4=i0(M1(),1);import{execSync as BD$}from"node:child_process";import{cpSync as OI,existsSync as E5,mkdirSync as aV,readFileSync as GU,rmSync as fp,writeFileSync as bQ}from"node:fs";import{tmpdir as LD$}from"node:os";import{dirname as UD0,join as Y4}from"node:path";var BI=i0(M1(),1);import{execSync as UD$,spawn as WD$}from"node:child_process";import{realpathSync as YD0}from"node:fs";import oV from"node:process";var xQ="oh-my-agent";function HD$($=oV.argv[1]){if(!$)return{packageManager:"unknown",isGlobal:!1};if(oV.env.IS_BINARY==="true")return{packageManager:"binary",isGlobal:!0,updateMessage:"Running as a standalone binary. Download the latest release from GitHub."};let J;try{J=r9(YD0($))}catch{return{packageManager:"unknown",isGlobal:!1}}if(J.includes("/.npm/_npx")||J.includes("/npm/_npx"))return{packageManager:"npx",isGlobal:!1,updateMessage:"Running via npx, auto-update not applicable."};if(J.includes("/.pnpm/_pnpx")||J.includes("/.cache/pnpm/dlx"))return{packageManager:"pnpx",isGlobal:!1,updateMessage:"Running via pnpx, auto-update not applicable."};if(J.includes("/.bun/install/cache"))return{packageManager:"bunx",isGlobal:!1,updateMessage:"Running via bunx, auto-update not applicable."};if(oV.platform==="darwin")try{let X=UD$(`brew --prefix ${xQ}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(X){let G=r9(YD0(X));if(J.startsWith(G))return{packageManager:"homebrew",isGlobal:!0,updateCommand:`brew upgrade ${xQ}`,updateMessage:"Installed via Homebrew. Updating in background..."}}}catch{}if(J.includes("/.pnpm/global")||J.includes("/.local/share/pnpm"))return{packageManager:"pnpm",isGlobal:!0,updateCommand:`pnpm add -g ${xQ}@latest`,updateMessage:"Installed via pnpm. Updating in background..."};if(J.includes("/.yarn/global"))return{packageManager:"yarn",isGlobal:!0,updateCommand:`yarn global add ${xQ}@latest`,updateMessage:"Installed via yarn. Updating in background..."};if(J.includes("/.bun/install/global"))return{packageManager:"bun",isGlobal:!0,updateCommand:`bun add -g ${xQ}@latest`,updateMessage:"Installed via bun. Updating in background..."};return{packageManager:"npm",isGlobal:!0,updateCommand:`npm install -g ${xQ}@latest`,updateMessage:"Installed via npm. Updating in background..."}}var ZD0=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/;function qD$($,J){let X=$.match(ZD0),G=J.match(ZD0);if(!X||!G)return!1;for(let Q=1;Q<=3;Q++){let Y=Number(X[Q]),Z=Number(G[Q]);if(Y<Z)return!0;if(Y>Z)return!1}return!1}async function VD$($=xQ,J=2000){try{let X=await VX.get(`https://registry.npmjs.org/${$}/latest`,{timeout:J});return typeof X.data?.version==="string"?X.data.version:null}catch{return null}}async function KD0($){if(!$.enabled)return{triggered:!1,reason:"disabled"};if(oV.env.OMA_SKIP_VERSION_CHECK==="1")return{triggered:!1,reason:"skipped-env"};if(oV.env.NODE_ENV==="development")return{triggered:!1,reason:"skipped-env"};let J=await VD$();if(!J)return{triggered:!1,reason:"fetch-failed"};if(!qD$($.currentVersion,J))return{triggered:!1,reason:"up-to-date",latest:J};let X=HD$();if(!X.updateCommand)return $.onNotice?.(BI.default.yellow(`global oh-my-agent ${$.currentVersion} → ${J} available. ${X.updateMessage??"Update manually."}`)),{triggered:!1,reason:"non-upgradable",latest:J};try{return WD$(X.updateCommand,{stdio:"ignore",shell:!0,detached:!0}).unref(),$.onSpawnStart?.(BI.default.cyan(`global oh-my-agent ${$.currentVersion} → ${J} updating in background. New version applies on next run.`)),{triggered:!0,latest:J}}catch{return $.onNotice?.(BI.default.yellow(`global oh-my-agent ${$.currentVersion} → ${J} available. Run: ${X.updateCommand}`)),{triggered:!1,reason:"spawn-failed",latest:J}}}var LI={name:"oh-my-agent",version:"7.0.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",build:"bun run sync:readme && bun build cli.ts --outfile bin/cli.js --target node --minify",dev:"bun run cli.ts",lint:"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",axios:"^1.15.0","better-sqlite3":"^12.9.0",chokidar:"^5.0.0",commander:"^14.0.3","date-fns":"^4.1.0","fast-xml-parser":"^4",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.5","@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 OD$($){if(!$)return{intro:(X)=>u1(X),outro:(X)=>P$(X),note:(X,G)=>G$(X,G),logError:(X)=>s$.error(X),spinnerStart:(X)=>{let G=z9();return G.start(X),G}};let J={start(X){},stop(X){if(X)console.log(X)},message(X){console.log(X)}};return{intro:(X)=>console.log(X),outro:(X)=>console.log(X),note:(X,G)=>console.log(X),logError:(X)=>console.error(X),spinnerStart:(X)=>{return console.log(X),J}}}function FD$($,J){if($!==null)return"ready";return J?"legacy":"missing"}async function gp($=!1,J=!1){if(!J&&process.stdout.isTTY)console.clear();let X=OD$(J);X.intro(u4.default.bgMagenta(u4.default.white(" \uD83D\uDEF8 oh-my-agent update ")));let G=process.cwd();await KD0({currentVersion:LI.version,enabled:l90(G),onSpawnStart:(H)=>X.note(H,"CLI auto-update"),onNotice:(H)=>X.note(H,"CLI update available")});let Q=await qF(G),Y=N60(G),Z=FD$(Q,Y);if(Z==="missing"){if(X.logError("oh-my-agent is not installed in this project. Run `oma install` first."),J)throw Error("oh-my-agent is not installed in this project. Run `oma install` first.");process.exit(1)}let K=zG(G);if(K.length>0)X.note(K.map((H)=>`${u4.default.green("✓")} ${H}`).join(`
1449
+ `);G$(L,"Skills")}P$(T5.default.dim(`Data stored in: ${G}`))}function QD0($){n6($.command("stats").description("View productivity metrics").option("--reset","Reset metrics data")).action(V$(async(J)=>{await GD0(h6(J),J.reset)},{supportsJsonOutput:!0}))}N8();var u4=i0(M1(),1);import{execSync as BD$}from"node:child_process";import{cpSync as OI,existsSync as E5,mkdirSync as aV,readFileSync as GU,rmSync as fp,writeFileSync as bQ}from"node:fs";import{tmpdir as LD$}from"node:os";import{dirname as UD0,join as Y4}from"node:path";var BI=i0(M1(),1);import{execSync as UD$,spawn as WD$}from"node:child_process";import{realpathSync as YD0}from"node:fs";import oV from"node:process";var xQ="oh-my-agent";function HD$($=oV.argv[1]){if(!$)return{packageManager:"unknown",isGlobal:!1};if(oV.env.IS_BINARY==="true")return{packageManager:"binary",isGlobal:!0,updateMessage:"Running as a standalone binary. Download the latest release from GitHub."};let J;try{J=r9(YD0($))}catch{return{packageManager:"unknown",isGlobal:!1}}if(J.includes("/.npm/_npx")||J.includes("/npm/_npx"))return{packageManager:"npx",isGlobal:!1,updateMessage:"Running via npx, auto-update not applicable."};if(J.includes("/.pnpm/_pnpx")||J.includes("/.cache/pnpm/dlx"))return{packageManager:"pnpx",isGlobal:!1,updateMessage:"Running via pnpx, auto-update not applicable."};if(J.includes("/.bun/install/cache"))return{packageManager:"bunx",isGlobal:!1,updateMessage:"Running via bunx, auto-update not applicable."};if(oV.platform==="darwin")try{let X=UD$(`brew --prefix ${xQ}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(X){let G=r9(YD0(X));if(J.startsWith(G))return{packageManager:"homebrew",isGlobal:!0,updateCommand:`brew upgrade ${xQ}`,updateMessage:"Installed via Homebrew. Updating in background..."}}}catch{}if(J.includes("/.pnpm/global")||J.includes("/.local/share/pnpm"))return{packageManager:"pnpm",isGlobal:!0,updateCommand:`pnpm add -g ${xQ}@latest`,updateMessage:"Installed via pnpm. Updating in background..."};if(J.includes("/.yarn/global"))return{packageManager:"yarn",isGlobal:!0,updateCommand:`yarn global add ${xQ}@latest`,updateMessage:"Installed via yarn. Updating in background..."};if(J.includes("/.bun/install/global"))return{packageManager:"bun",isGlobal:!0,updateCommand:`bun add -g ${xQ}@latest`,updateMessage:"Installed via bun. Updating in background..."};return{packageManager:"npm",isGlobal:!0,updateCommand:`npm install -g ${xQ}@latest`,updateMessage:"Installed via npm. Updating in background..."}}var ZD0=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/;function qD$($,J){let X=$.match(ZD0),G=J.match(ZD0);if(!X||!G)return!1;for(let Q=1;Q<=3;Q++){let Y=Number(X[Q]),Z=Number(G[Q]);if(Y<Z)return!0;if(Y>Z)return!1}return!1}async function VD$($=xQ,J=2000){try{let X=await VX.get(`https://registry.npmjs.org/${$}/latest`,{timeout:J});return typeof X.data?.version==="string"?X.data.version:null}catch{return null}}async function KD0($){if(!$.enabled)return{triggered:!1,reason:"disabled"};if(oV.env.OMA_SKIP_VERSION_CHECK==="1")return{triggered:!1,reason:"skipped-env"};if(oV.env.NODE_ENV==="development")return{triggered:!1,reason:"skipped-env"};let J=await VD$();if(!J)return{triggered:!1,reason:"fetch-failed"};if(!qD$($.currentVersion,J))return{triggered:!1,reason:"up-to-date",latest:J};let X=HD$();if(!X.updateCommand)return $.onNotice?.(BI.default.yellow(`global oh-my-agent ${$.currentVersion} → ${J} available. ${X.updateMessage??"Update manually."}`)),{triggered:!1,reason:"non-upgradable",latest:J};try{return WD$(X.updateCommand,{stdio:"ignore",shell:!0,detached:!0}).unref(),$.onSpawnStart?.(BI.default.cyan(`global oh-my-agent ${$.currentVersion} → ${J} updating in background. New version applies on next run.`)),{triggered:!0,latest:J}}catch{return $.onNotice?.(BI.default.yellow(`global oh-my-agent ${$.currentVersion} → ${J} available. Run: ${X.updateCommand}`)),{triggered:!1,reason:"spawn-failed",latest:J}}}var LI={name:"oh-my-agent",version:"7.1.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",build:"bun run sync:readme && bun build cli.ts --outfile bin/cli.js --target node --minify",dev:"bun run cli.ts",lint:"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",axios:"^1.15.0","better-sqlite3":"^12.9.0",chokidar:"^5.0.0",commander:"^14.0.3","date-fns":"^4.1.0","fast-xml-parser":"^4",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.5","@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 OD$($){if(!$)return{intro:(X)=>u1(X),outro:(X)=>P$(X),note:(X,G)=>G$(X,G),logError:(X)=>s$.error(X),spinnerStart:(X)=>{let G=z9();return G.start(X),G}};let J={start(X){},stop(X){if(X)console.log(X)},message(X){console.log(X)}};return{intro:(X)=>console.log(X),outro:(X)=>console.log(X),note:(X,G)=>console.log(X),logError:(X)=>console.error(X),spinnerStart:(X)=>{return console.log(X),J}}}function FD$($,J){if($!==null)return"ready";return J?"legacy":"missing"}async function gp($=!1,J=!1){if(!J&&process.stdout.isTTY)console.clear();let X=OD$(J);X.intro(u4.default.bgMagenta(u4.default.white(" \uD83D\uDEF8 oh-my-agent update ")));let G=process.cwd();await KD0({currentVersion:LI.version,enabled:l90(G),onSpawnStart:(H)=>X.note(H,"CLI auto-update"),onNotice:(H)=>X.note(H,"CLI update available")});let Q=await qF(G),Y=N60(G),Z=FD$(Q,Y);if(Z==="missing"){if(X.logError("oh-my-agent is not installed in this project. Run `oma install` first."),J)throw Error("oh-my-agent is not installed in this project. Run `oma install` first.");process.exit(1)}let K=zG(G);if(K.length>0)X.note(K.map((H)=>`${u4.default.green("✓")} ${H}`).join(`
1450
1450
  `),"Migration");let U=K.length>0||Gv(G);if(K.length>0&&!Gv(G))Qv(G,!0);if(!J)await UF(G);if(Z==="legacy")X.note("Existing .agents installation detected without _version.json. Updating in place and restoring version metadata.","Legacy install");let W;try{W=X.spinnerStart("Checking for updates...");let H=await A60();if(Q===H.version&&!U){W.stop(u4.default.green("Already up to date!")),X.outro(`Current version: ${u4.default.cyan(Q)}`);return}let q=Q===H.version;W.message(`Downloading ${u4.default.cyan(H.version)}...`);let{dir:z,cleanup:V}=await L2();try{W.message("Copying files..."),zG(G);let B=Y4(G,".agents","oma-config.yaml"),L=Y4(G,".agents","mcp.json"),O=!$&&E5(B)?GU(B):null,F=!$&&E5(L)?GU(L):null,N=Y4(LD$(),`oma-stack-backup-${Date.now()}`),A=Y4(G,".agents","skills","oma-backend","stack"),M=!$&&E5(A);if(M)aV(N,{recursive:!0}),OI(A,Y4(N,"oma-backend"),{recursive:!0});let T=["snippets.md","tech-stack.md","api-template.py"],w=Y4(G,".agents","skills","oma-backend","resources"),R=!$&&!M&&T.some((n)=>E5(Y4(w,n)));if(OI(Y4(z,".agents"),Y4(G,".agents"),{recursive:!0,force:!0}),O)bQ(B,O);if(F)bQ(L,F);if(M)try{aV(A,{recursive:!0}),OI(Y4(N,"oma-backend"),A,{recursive:!0,force:!0})}finally{fp(N,{recursive:!0,force:!0})}if(R){let n=Y4(z,".agents","skills","oma-backend","variants","python");if(E5(n))aV(A,{recursive:!0}),OI(n,A,{recursive:!0,force:!0}),bQ(Y4(A,"stack.yaml"),`language: python
1451
1451
  framework: fastapi
1452
1452
  orm: sqlalchemy
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-agent",
3
- "version": "7.0.0",
3
+ "version": "7.1.0",
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": {