Created
March 18, 2026 14:23
-
-
Save thoroc/1bd11428d8b536d6420c361d1016db77 to your computer and use it in GitHub Desktop.
Agentic harness historic ranking - based on github stars
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Agent Star History</title> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script> | |
| <style> | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| body { font-family: system-ui, sans-serif; background: #0f1117; color: #e0e0e0; padding: 24px; } | |
| h1 { font-size: 1.5rem; margin-bottom: 4px; } | |
| .subtitle { color: #888; font-size: 0.85rem; margin-bottom: 32px; } | |
| .subtitle a { color: #4a9eff; } | |
| .chart-wrap { background: #1a1d27; border-radius: 12px; padding: 24px; margin-bottom: 32px; } | |
| h2 { font-size: 1rem; margin-bottom: 16px; color: #ccc; } | |
| canvas { max-height: 480px; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>Agent Star History</h1> | |
| <p class="subtitle">Generated 2026-03-18 · Data from <a href="https://ossinsight.io" target="_blank">OSSInsight</a> · Monthly cumulative totals</p> | |
| <div class="chart-wrap"> | |
| <h2>Stars over time (log scale)</h2> | |
| <canvas id="stars"></canvas> | |
| </div> | |
| <div class="chart-wrap"> | |
| <h2>Ranking over time (rank 1 = most stars)</h2> | |
| <canvas id="ranking"></canvas> | |
| </div> | |
| <script> | |
| const labels = ["2021-07-01","2021-08-01","2021-09-01","2021-10-01","2021-11-01","2021-12-01","2022-01-01","2022-02-01","2022-03-01","2022-04-01","2022-05-01","2022-06-01","2022-07-01","2022-08-01","2022-09-01","2022-10-01","2022-11-01","2022-12-01","2023-01-01","2023-02-01","2023-03-01","2023-04-01","2023-05-01","2023-06-01","2023-07-01","2023-08-01","2023-09-01","2023-10-01","2023-11-01","2023-12-01","2024-01-01","2024-02-01","2024-03-01","2024-04-01","2024-05-01","2024-06-01","2024-07-01","2024-08-01","2024-09-01","2024-10-01","2024-11-01","2024-12-01","2025-01-01","2025-02-01","2025-03-01","2025-04-01","2025-05-01","2025-06-01","2025-07-01","2025-08-01","2025-09-01","2025-10-01","2025-11-01","2025-12-01","2026-01-01","2026-02-01","2026-03-01"]; | |
| const rawStars = {"Claude Code":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,4381,6123,7162,9076,12572,18847,21762,23341,24710,25939,28579,33319,36106,37834],"Codex":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,18368,24210,25821,26738,30285,34508,35951,36853,38378,39708,41072,41871],"Continue":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,73,1680,3405,3915,4380,4913,5373,6060,7385,9113,10330,11389,12180,13090,14222,15848,17692,18590,19655,21138,22776,23831,24680,25255,25793,26208,26652,26951,27126,27359,27618,27892,28039,28122],"Crush":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1584,6655,7707,8105,8512,9007,10013,10443,10680],"Deep Agents":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,261,1890,2270,2567,3205,3662,4052,4340,5295],"Gemini CLI":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26688,38724,42960,45647,46924,48687,50497,52074,53038,53598],"Goose":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,18,65,123,215,300,4169,8263,10107,11076,11958,13152,14609,15510,15955,16442,16948,18046,19621,20212,20637],"iFlow":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38,634,1161,1393,1603,1852,2036,2147,2207],"KiloCode":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,94,185,509,1119,3788,4558,6364,6798,7197,7548,7989,8397,8556],"MCPJam":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21,139,347,505,620,699,748,773,813,849,862],"OpenCode":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,574,4739,9476,12893,15189,16693,18562,22907,40843,46693,49252],"OpenClaw":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,90,381,42868,76894,96223],"Pi":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1,null,3,110,351,1452,5729,7321],"Qwen":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,3782,6805,7851,8276,8716,9132,9578,10106,10354],"Trae":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,25,5155,5535,5777,5867,5986,6099,6228,6292,6337],"Warp":[271,324,372,409,515,623,894,1148,1295,4992,5854,6336,6877,7281,7731,8230,9531,10153,10666,11323,12219,12901,13471,14005,14430,14857,15178,15491,16006,16462,16915,17721,18359,18811,19228,20171,20505,20859,21181,21449,21694,22002,22232,22563,23158,23529,23778,24001,24199,24426,24680,24780,24882,24988,25095,25185,25213],"Zed":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,16683,25365,28329,31336,33834,37813,41495,44662,46501,48041,49833,51204,52884,54194,55713,57038,59882,60763,61571,62638,63646,64566,65344,66101,66909,67472,67746]}; | |
| const agentNames = ["Claude Code","Codex","Continue","Crush","Deep Agents","Gemini CLI","Goose","iFlow","KiloCode","MCPJam","OpenCode","OpenClaw","Pi","Qwen","Trae","Warp","Zed"]; | |
| const palette = ["#e6194b","#3cb44b","#4363d8","#f58231","#911eb4","#42d4f4","#f032e6","#bfef45","#fabed4","#469990","#dcbeff","#9a6324","#fffac8","#800000","#aaffc3","#808000","#ffd8b1"]; | |
| // hidden[i] = true when agent i is toggled off | |
| const hidden = new Array(agentNames.length).fill(false); | |
| function dsBase(i) { | |
| return { | |
| label: agentNames[i], | |
| borderColor: palette[i], | |
| backgroundColor: palette[i] + '22', | |
| tension: 0.3, | |
| pointRadius: 3, | |
| }; | |
| } | |
| // Recompute rank data for agent[i] given current hidden state | |
| function computeRankDatasets() { | |
| return agentNames.map((name, i) => ({ | |
| ...dsBase(i), | |
| spanGaps: false, | |
| data: labels.map((_, dateIdx) => { | |
| if (hidden[i]) return null; | |
| const snapshot = agentNames | |
| .filter((_, j) => !hidden[j]) | |
| .map(n => ({ n, stars: rawStars[n][dateIdx] })) | |
| .filter(s => s.stars !== null) | |
| .sort((a, b) => b.stars - a.stars); | |
| const rank = snapshot.findIndex(s => s.n === name) + 1; | |
| return rank === 0 ? null : rank; | |
| }), | |
| })); | |
| } | |
| // Toggle agent by dataset index, sync both charts, recompute rankings | |
| function toggleAgent(idx) { | |
| hidden[idx] = !hidden[idx]; | |
| // Sync star chart visibility | |
| const sMeta = starChart.getDatasetMeta(idx); | |
| sMeta.hidden = hidden[idx]; | |
| starChart.update('none'); | |
| // Recompute and apply ranking data | |
| const newRank = computeRankDatasets(); | |
| rankChart.data.datasets.forEach((ds, i) => { | |
| ds.data = newRank[i].data; | |
| rankChart.getDatasetMeta(i).hidden = hidden[i]; | |
| }); | |
| const visibleCount = hidden.filter(h => !h).length; | |
| rankChart.options.scales.y.max = visibleCount || 1; | |
| rankChart.update(); | |
| } | |
| const legendClick = (_e, item) => toggleAgent(item.datasetIndex); | |
| const legendLabels = { color: '#ccc', boxWidth: 12, padding: 10 }; | |
| const xScale = { ticks: { color: '#888', maxTicksLimit: 14 }, grid: { color: '#333' } }; | |
| const starChart = new Chart(document.getElementById('stars'), { | |
| type: 'line', | |
| data: { | |
| labels, | |
| datasets: agentNames.map((name, i) => ({ | |
| ...dsBase(i), | |
| spanGaps: true, | |
| data: rawStars[name], | |
| })), | |
| }, | |
| options: { | |
| responsive: true, | |
| interaction: { mode: 'index', intersect: false }, | |
| plugins: { | |
| legend: { labels: legendLabels, onClick: legendClick }, | |
| tooltip: { | |
| callbacks: { | |
| label: ctx => ctx.parsed.y !== null | |
| ? ` ${ctx.dataset.label}: ${ctx.parsed.y.toLocaleString()} ⭐` | |
| : null, | |
| }, | |
| }, | |
| }, | |
| scales: { | |
| x: xScale, | |
| y: { | |
| type: 'logarithmic', | |
| ticks: { color: '#888', callback: v => v >= 1000 ? (v / 1000).toFixed(0) + 'k' : v }, | |
| grid: { color: '#333' }, | |
| }, | |
| }, | |
| }, | |
| }); | |
| const rankChart = new Chart(document.getElementById('ranking'), { | |
| type: 'line', | |
| data: { labels, datasets: computeRankDatasets() }, | |
| options: { | |
| responsive: true, | |
| interaction: { mode: 'index', intersect: false }, | |
| plugins: { | |
| legend: { labels: legendLabels, onClick: legendClick }, | |
| tooltip: { | |
| callbacks: { | |
| label: ctx => ctx.parsed.y !== null | |
| ? ` ${ctx.dataset.label}: rank #${ctx.parsed.y}` | |
| : null, | |
| }, | |
| }, | |
| }, | |
| scales: { | |
| x: xScale, | |
| y: { | |
| reverse: true, | |
| min: 1, | |
| max: 17, | |
| ticks: { color: '#888', stepSize: 1, callback: v => '#' + v }, | |
| grid: { color: '#333' }, | |
| }, | |
| }, | |
| }, | |
| }); | |
| </script> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bun | |
| /** | |
| * Fetch historical star data from OSSInsight for all open-source agents | |
| * and generate a self-contained HTML file with two charts: | |
| * 1. Stars over time (log scale line chart) | |
| * 2. Ranking over time (bump chart — rank 1 at top) | |
| * | |
| * Data source: https://ossinsight.io (no auth required, rate limits apply) | |
| * | |
| * Usage: | |
| * bun scripts/star-history.ts | |
| * bun scripts/star-history.ts --output star-history.html | |
| */ | |
| // Open-source repos from agent-stars.ts AGENTS list | |
| const OPEN_REPOS: Record<string, string> = { | |
| "Claude Code": "anthropics/claude-code", | |
| Cline: "cline/cline", | |
| Codex: "openai/codex", | |
| Continue: "continuedev/continue", | |
| Crush: "charmbracelet/crush", | |
| "Deep Agents": "langchain-ai/deepagents", | |
| "Gemini CLI": "google-gemini/gemini-cli", | |
| Goose: "block/goose", | |
| iFlow: "iflow-ai/iflow-cli", | |
| KiloCode: "Kilo-Org/kilocode", | |
| Kode: "shareAI-lab/Kode-Agent", | |
| MCPJam: "MCPJam/inspector", | |
| OpenCode: "anomalyco/opencode", | |
| OpenClaw: "openclaw/openclaw", | |
| OpenHands: "All-Hands-AI/OpenHands", | |
| Pi: "badlogic/pi-mono", | |
| Qwen: "QwenLM/qwen-code", | |
| Roo: "RooVetGit/Roo-Code", | |
| Trae: "bytedance/trae-agent", | |
| Warp: "warpdotdev/Warp", | |
| Zed: "zed-industries/zed", | |
| }; | |
| // 21-color palette (ColorBrewer + custom, perceptually distinct) | |
| const PALETTE = [ | |
| "#e6194b", "#3cb44b", "#4363d8", "#f58231", "#911eb4", | |
| "#42d4f4", "#f032e6", "#bfef45", "#fabed4", "#469990", | |
| "#dcbeff", "#9a6324", "#fffac8", "#800000", "#aaffc3", | |
| "#808000", "#ffd8b1", "#000075", "#a9a9a9", "#ffffff", | |
| "#000000", | |
| ]; | |
| interface MonthlyPoint { | |
| date: string; // "YYYY-MM-DD" | |
| stars: number; | |
| } | |
| interface AgentSeries { | |
| agent: string; | |
| repo: string; | |
| history: MonthlyPoint[]; | |
| } | |
| type OssInsightResponse = { | |
| data: { rows: Array<{ date: string; stargazers: string }> }; | |
| }; | |
| async function fetchHistory(repo: string): Promise<MonthlyPoint[] | null> { | |
| const url = `https://api.ossinsight.io/v1/repos/${repo}/stargazers/history`; | |
| const res = await fetch(url, { | |
| headers: { "User-Agent": "star-history-script" }, | |
| }); | |
| if (res.status === 404) return null; | |
| if (!res.ok) { | |
| console.error(` HTTP ${res.status} for ${repo}`); | |
| return null; | |
| } | |
| const json = (await res.json()) as OssInsightResponse; | |
| const rows = json?.data?.rows; | |
| if (!Array.isArray(rows) || rows.length === 0) return null; | |
| return rows.map((r) => ({ date: r.date.slice(0, 10), stars: Number(r.stargazers) })); | |
| } | |
| function buildHtml(series: AgentSeries[]): string { | |
| const allDates = [ | |
| ...new Set(series.flatMap((s) => s.history.map((p) => p.date))), | |
| ].sort(); | |
| // Raw stars per agent per date slot — rankings computed live in JS | |
| const rawStars: Record<string, (number | null)[]> = {}; | |
| for (const s of series) { | |
| rawStars[s.agent] = allDates.map((d) => { | |
| const p = s.history.find((h) => h.date === d); | |
| return p ? p.stars : null; | |
| }); | |
| } | |
| const agentNames = series.map((s) => s.agent); | |
| const palette = series.map((_, i) => PALETTE[i % PALETTE.length]); | |
| const generated = new Date().toISOString().slice(0, 10); | |
| return `<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Agent Star History</title> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script> | |
| <style> | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| body { font-family: system-ui, sans-serif; background: #0f1117; color: #e0e0e0; padding: 24px; } | |
| h1 { font-size: 1.5rem; margin-bottom: 4px; } | |
| .subtitle { color: #888; font-size: 0.85rem; margin-bottom: 32px; } | |
| .subtitle a { color: #4a9eff; } | |
| .chart-wrap { background: #1a1d27; border-radius: 12px; padding: 24px; margin-bottom: 32px; } | |
| h2 { font-size: 1rem; margin-bottom: 16px; color: #ccc; } | |
| canvas { max-height: 480px; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>Agent Star History</h1> | |
| <p class="subtitle">Generated ${generated} · Data from <a href="https://ossinsight.io" target="_blank">OSSInsight</a> · Monthly cumulative totals</p> | |
| <div class="chart-wrap"> | |
| <h2>Stars over time (log scale)</h2> | |
| <canvas id="stars"></canvas> | |
| </div> | |
| <div class="chart-wrap"> | |
| <h2>Ranking over time (rank 1 = most stars)</h2> | |
| <canvas id="ranking"></canvas> | |
| </div> | |
| <script> | |
| const labels = ${JSON.stringify(allDates)}; | |
| const rawStars = ${JSON.stringify(rawStars)}; | |
| const agentNames = ${JSON.stringify(agentNames)}; | |
| const palette = ${JSON.stringify(palette)}; | |
| // hidden[i] = true when agent i is toggled off | |
| const hidden = new Array(agentNames.length).fill(false); | |
| function dsBase(i) { | |
| return { | |
| label: agentNames[i], | |
| borderColor: palette[i], | |
| backgroundColor: palette[i] + '22', | |
| tension: 0.3, | |
| pointRadius: 3, | |
| }; | |
| } | |
| // Recompute rank data for agent[i] given current hidden state | |
| function computeRankDatasets() { | |
| return agentNames.map((name, i) => ({ | |
| ...dsBase(i), | |
| spanGaps: false, | |
| data: labels.map((_, dateIdx) => { | |
| if (hidden[i]) return null; | |
| const snapshot = agentNames | |
| .filter((_, j) => !hidden[j]) | |
| .map(n => ({ n, stars: rawStars[n][dateIdx] })) | |
| .filter(s => s.stars !== null) | |
| .sort((a, b) => b.stars - a.stars); | |
| const rank = snapshot.findIndex(s => s.n === name) + 1; | |
| return rank === 0 ? null : rank; | |
| }), | |
| })); | |
| } | |
| // Toggle agent by dataset index, sync both charts, recompute rankings | |
| function toggleAgent(idx) { | |
| hidden[idx] = !hidden[idx]; | |
| // Sync star chart visibility | |
| const sMeta = starChart.getDatasetMeta(idx); | |
| sMeta.hidden = hidden[idx]; | |
| starChart.update('none'); | |
| // Recompute and apply ranking data | |
| const newRank = computeRankDatasets(); | |
| rankChart.data.datasets.forEach((ds, i) => { | |
| ds.data = newRank[i].data; | |
| rankChart.getDatasetMeta(i).hidden = hidden[i]; | |
| }); | |
| const visibleCount = hidden.filter(h => !h).length; | |
| rankChart.options.scales.y.max = visibleCount || 1; | |
| rankChart.update(); | |
| } | |
| const legendClick = (_e, item) => toggleAgent(item.datasetIndex); | |
| const legendLabels = { color: '#ccc', boxWidth: 12, padding: 10 }; | |
| const xScale = { ticks: { color: '#888', maxTicksLimit: 14 }, grid: { color: '#333' } }; | |
| const starChart = new Chart(document.getElementById('stars'), { | |
| type: 'line', | |
| data: { | |
| labels, | |
| datasets: agentNames.map((name, i) => ({ | |
| ...dsBase(i), | |
| spanGaps: true, | |
| data: rawStars[name], | |
| })), | |
| }, | |
| options: { | |
| responsive: true, | |
| interaction: { mode: 'index', intersect: false }, | |
| plugins: { | |
| legend: { labels: legendLabels, onClick: legendClick }, | |
| tooltip: { | |
| callbacks: { | |
| label: ctx => ctx.parsed.y !== null | |
| ? \` \${ctx.dataset.label}: \${ctx.parsed.y.toLocaleString()} ⭐\` | |
| : null, | |
| }, | |
| }, | |
| }, | |
| scales: { | |
| x: xScale, | |
| y: { | |
| type: 'logarithmic', | |
| ticks: { color: '#888', callback: v => v >= 1000 ? (v / 1000).toFixed(0) + 'k' : v }, | |
| grid: { color: '#333' }, | |
| }, | |
| }, | |
| }, | |
| }); | |
| const rankChart = new Chart(document.getElementById('ranking'), { | |
| type: 'line', | |
| data: { labels, datasets: computeRankDatasets() }, | |
| options: { | |
| responsive: true, | |
| interaction: { mode: 'index', intersect: false }, | |
| plugins: { | |
| legend: { labels: legendLabels, onClick: legendClick }, | |
| tooltip: { | |
| callbacks: { | |
| label: ctx => ctx.parsed.y !== null | |
| ? \` \${ctx.dataset.label}: rank #\${ctx.parsed.y}\` | |
| : null, | |
| }, | |
| }, | |
| }, | |
| scales: { | |
| x: xScale, | |
| y: { | |
| reverse: true, | |
| min: 1, | |
| max: ${series.length}, | |
| ticks: { color: '#888', stepSize: 1, callback: v => '#' + v }, | |
| grid: { color: '#333' }, | |
| }, | |
| }, | |
| }, | |
| }); | |
| </script> | |
| </body> | |
| </html>`; | |
| } | |
| async function main(): Promise<void> { | |
| const outputFlagIdx = process.argv.indexOf("--output"); | |
| const outputPath: string = | |
| outputFlagIdx !== -1 | |
| ? (process.argv[outputFlagIdx + 1] ?? "star-history.html") | |
| : "star-history.html"; | |
| console.log(`Fetching history for ${Object.keys(OPEN_REPOS).length} repos from OSSInsight...\n`); | |
| const results = await Promise.all( | |
| Object.entries(OPEN_REPOS).map(async ([agent, repo]) => { | |
| process.stdout.write(` ${agent.padEnd(20)} `); | |
| const history = await fetchHistory(repo); | |
| if (!history) { | |
| console.log("no data"); | |
| return null; | |
| } | |
| console.log(`${history.length} months (latest: ${history.at(-1)?.stars.toLocaleString()} ⭐)`); | |
| return { agent, repo, history } satisfies AgentSeries; | |
| }), | |
| ); | |
| const series = results.filter((r): r is AgentSeries => r !== null); | |
| console.log(`\n${series.length} / ${Object.keys(OPEN_REPOS).length} repos have data.`); | |
| const html = buildHtml(series); | |
| await Bun.write(outputPath, html); | |
| console.log(`\nChart written to ${outputPath}`); | |
| console.log(`Open with: open ${outputPath}`); | |
| } | |
| main().catch((err: unknown) => { | |
| console.error(err); | |
| process.exit(1); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment