Skip to content

Instantly share code, notes, and snippets.

@ekaone
Created April 14, 2026 11:18
Show Gist options
  • Select an option

  • Save ekaone/cd657c047eb15b3c06b23d1d7e22d5c6 to your computer and use it in GitHub Desktop.

Select an option

Save ekaone/cd657c047eb15b3c06b23d1d7e22d5c6 to your computer and use it in GitHub Desktop.
Package Universe
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ekaone package universe</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
:root{
--color-background-primary:#ffffff;
--color-background-secondary:#f5f5f3;
--color-background-tertiary:#eeede8;
--color-text-primary:#1a1a18;
--color-text-secondary:#6b6b67;
--color-text-tertiary:#9b9b97;
--color-border-tertiary:rgba(0,0,0,0.1);
--color-border-secondary:rgba(0,0,0,0.18);
--font-mono:'Fira Code','Cascadia Code','JetBrains Mono',monospace;
--border-radius-md:8px;
--border-radius-lg:12px;
}
@media(prefers-color-scheme:dark){
:root{
--color-background-primary:#1c1c1a;
--color-background-secondary:#252523;
--color-background-tertiary:#2e2e2b;
--color-text-primary:#f0efe8;
--color-text-secondary:#9b9b97;
--color-text-tertiary:#6b6b67;
--color-border-tertiary:rgba(255,255,255,0.08);
--color-border-secondary:rgba(255,255,255,0.15);
}
}
html,body{height:100%;background:var(--color-background-tertiary);font-family:var(--font-mono)}
body{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px;min-height:100vh}
h1{font-size:13px;font-weight:500;color:var(--color-text-secondary);letter-spacing:0.05em;margin-bottom:16px}
#app{width:100%;max-width:860px;border-radius:var(--border-radius-lg);border:0.5px solid var(--color-border-tertiary);background:var(--color-background-primary);overflow:hidden}
#filter-bar{display:flex;gap:6px;padding:10px 14px;flex-wrap:wrap;border-bottom:0.5px solid var(--color-border-tertiary)}
.ftag{font-size:11px;padding:3px 10px;border-radius:12px;cursor:pointer;border:0.5px solid var(--color-border-tertiary);background:var(--color-background-primary);color:var(--color-text-secondary);transition:all .15s;font-family:var(--font-mono)}
.ftag.active{background:var(--color-background-secondary);color:var(--color-text-primary);border-color:var(--color-border-secondary)}
#legend{display:flex;gap:16px;padding:10px 14px;flex-wrap:wrap;border-bottom:0.5px solid var(--color-border-tertiary)}
.leg{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--color-text-secondary)}
.leg-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
#universe{width:100%;position:relative;overflow:hidden}
canvas{display:block;width:100%;height:100%}
#tooltip{position:absolute;pointer-events:none;background:var(--color-background-primary);border:0.5px solid var(--color-border-secondary);border-radius:var(--border-radius-md);padding:10px 14px;font-size:12px;opacity:0;transition:opacity .15s;max-width:220px;z-index:10;font-family:var(--font-mono)}
#tooltip .pkg-name{font-size:13px;font-weight:500;color:var(--color-text-primary);margin-bottom:6px}
#tooltip .pkg-desc{color:var(--color-text-secondary);line-height:1.5;margin-bottom:6px}
#tooltip .pkg-tags{display:flex;flex-wrap:wrap;gap:4px}
#tooltip .tag{font-size:10px;padding:2px 6px;border-radius:4px;background:var(--color-background-secondary);color:var(--color-text-secondary)}
#footer{font-size:11px;color:var(--color-text-tertiary);margin-top:12px;text-align:center}
</style>
</head>
<body>
<h1>@ekaone / package universe</h1>
<div id="app">
<div id="filter-bar">
<span style="font-size:11px;color:var(--color-text-tertiary);align-self:center;margin-right:4px">filter</span>
<span class="ftag active" data-cat="all">all</span>
<span class="ftag" data-cat="agent">agent</span>
<span class="ftag" data-cat="security">security</span>
<span class="ftag" data-cat="cli">cli</span>
<span class="ftag" data-cat="util">util</span>
<span class="ftag" data-cat="ui">ui</span>
</div>
<div id="legend">
<span class="leg"><span class="leg-dot" style="background:#5DCAA5"></span>shipped</span>
<span class="leg"><span class="leg-dot" style="background:#EF9F27"></span>active dev</span>
<span class="leg"><span class="leg-dot" style="background:#AFA9EC"></span>planned</span>
<span class="leg" style="margin-left:auto;font-size:11px;color:var(--color-text-tertiary)">hover · drag to pan</span>
</div>
<div id="universe">
<canvas id="c"></canvas>
<div id="tooltip">
<div class="pkg-name" id="t-name"></div>
<div class="pkg-desc" id="t-desc"></div>
<div class="pkg-tags" id="t-tags"></div>
</div>
</div>
</div>
<div id="footer">21 packages · prasetia.me</div>
<script>
const PACKAGES = [
{id:'n-agent',name:'@ekaone/n-agent',desc:'Multi-agent conversation loop. Ping-pong turn rotation, per-agent history, AbortController, human-in-the-loop.',cat:'agent',status:'shipped',deps:['mock-ai'],x:0.35,y:0.22},
{id:'agent-relay',name:'@ekaone/agent-relay',desc:'Framework-agnostic multi-agent task delegation. In-memory bus, dead-letter queue, LLM coordinator.',cat:'agent',status:'active',deps:['n-agent','hermes'],x:0.55,y:0.3},
{id:'mock-ai',name:'@ekaone/mock-ai',desc:'DX layer over ai/test. Model factories, fluent builders, scenario presets.',cat:'util',status:'shipped',deps:[],x:0.2,y:0.38},
{id:'hermes',name:'@ekaone/hermes',desc:'Typed event bus with wildcards, priority, once-listeners, async emit. Zero deps.',cat:'util',status:'shipped',deps:[],x:0.72,y:0.2},
{id:'json-cli',name:'@ekaone/json-cli',desc:'AI-powered CLI task runner. Multi-intent extraction, --resume, --history, token cost tracking.',cat:'cli',status:'active',deps:[],x:0.8,y:0.45},
{id:'killx',name:'@ekaone/killx',desc:'Zero-dep cross-platform process tree killer. Dual ESM/CJS, dry-run, CLI.',cat:'cli',status:'shipped',deps:[],x:0.65,y:0.58},
{id:'repo-intel',name:'@ekaone/repo-intel',desc:'Rust core + TS wrapper. Repo analysis with 4 platform binaries.',cat:'cli',status:'shipped',deps:[],x:0.45,y:0.68},
{id:'vault',name:'@ekaone/vault',desc:'Encrypted ephemeral in-memory KV. AES-GCM 256-bit, Web Crypto, zero deps.',cat:'security',status:'shipped',deps:[],x:0.2,y:0.62},
{id:'masker',name:'@ekaone/masker',desc:'Universal data masking. Auto-detects sensitive types.',cat:'security',status:'shipped',deps:['mask-email','mask-card','mask-token','mask-name'],x:0.15,y:0.22},
{id:'mask-email',name:'@ekaone/mask-email',desc:'Email masking primitive.',cat:'security',status:'shipped',deps:[],x:0.05,y:0.42},
{id:'mask-card',name:'@ekaone/mask-card',desc:'Credit card masking primitive.',cat:'security',status:'shipped',deps:[],x:0.08,y:0.55},
{id:'mask-token',name:'@ekaone/mask-token',desc:'Token masking. #1 Google ranking.',cat:'security',status:'shipped',deps:[],x:0.08,y:0.68},
{id:'mask-name',name:'@ekaone/mask-name',desc:'Name masking with Latin/CJK/Japanese support.',cat:'security',status:'shipped',deps:[],x:0.15,y:0.78},
{id:'mcp-tools',name:'@ekaone/mcp-tools',desc:'MCP server: mask_email + mask_card as AI-callable tools via stdio.',cat:'util',status:'shipped',deps:['mask-email','mask-card'],x:0.3,y:0.82},
{id:'prompt-kit',name:'@ekaone/prompt-kit',desc:'Prompt template builder. Zero-dep, hand-rolled YAML frontmatter, strict variable injection.',cat:'util',status:'shipped',deps:[],x:0.55,y:0.12},
{id:'react-prompt-kit',name:'@ekaone/react-prompt-kit',desc:'React companion. /server + /client subpath exports, usePrompt hook.',cat:'ui',status:'shipped',deps:['prompt-kit'],x:0.7,y:0.08},
{id:'init',name:'@ekaone/init',desc:'pnpm create scaffolder for Next.js and Vite+React with shadcn.',cat:'cli',status:'shipped',deps:[],x:0.85,y:0.72},
{id:'rounded',name:'@ekaone/rounded',desc:'Financial rounding. Half Up, Banker\'s, Cash. 153-currency ISO 4217 map.',cat:'util',status:'shipped',deps:[],x:0.88,y:0.28},
{id:'entropy',name:'@ekaone/entropy',desc:'Shannon entropy primitive. Foundation layer for higher-level packages.',cat:'util',status:'shipped',deps:[],x:0.82,y:0.6},
{id:'nano-otp',name:'@ekaone/nano-otp',desc:'Zero-dep OTP with Web Crypto and toDataURL for authenticator apps.',cat:'security',status:'shipped',deps:[],x:0.3,y:0.58},
{id:'use-claude',name:'@ekaone/use-claude',desc:'React hook for Tauri IPC with Claude Code CLI. Callback API.',cat:'ui',status:'shipped',deps:[],x:0.55,y:0.82},
];
const CAT_COLORS={agent:'#7F77DD',security:'#1D9E75',cli:'#EF9F27',util:'#378ADD',ui:'#D4537E'};
const STATUS_OPACITY={shipped:1,active:0.85,planned:0.55};
const STATUS_STROKE={shipped:'#5DCAA5',active:'#EF9F27',planned:'#AFA9EC'};
let W,H,scale,dpr,pan={x:0,y:0},dragging=false,dragStart={x:0,y:0},panStart={x:0,y:0};
let hoveredId=null,activeFilter='all';
const canvas=document.getElementById('c');
const ctx=canvas.getContext('2d');
const container=document.getElementById('universe');
const tooltip=document.getElementById('tooltip');
function isDark(){return window.matchMedia('(prefers-color-scheme:dark)').matches}
function resize(){
dpr=window.devicePixelRatio||1;
W=container.offsetWidth;
H=Math.round(W*0.62);
container.style.height=H+'px';
canvas.width=W*dpr;canvas.height=H*dpr;
canvas.style.width=W+'px';canvas.style.height=H+'px';
ctx.scale(dpr,dpr);
scale=Math.min(W,H);
draw();
}
function nodePos(pkg){return{x:pkg.x*W+pan.x,y:pkg.y*H+pan.y}}
function nodeRadius(pkg){const base=pkg.deps&&pkg.deps.length>2?14:10;return base*(scale/600)}
function isVisible(pkg){return activeFilter==='all'||pkg.cat===activeFilter}
function draw(){
ctx.clearRect(0,0,W,H);
const dark=isDark();
const gridCol=dark?'rgba(255,255,255,0.03)':'rgba(0,0,0,0.03)';
ctx.strokeStyle=gridCol;ctx.lineWidth=1;
for(let x=0;x<W;x+=40){ctx.beginPath();ctx.moveTo(x,0);ctx.lineTo(x,H);ctx.stroke();}
for(let y=0;y<H;y+=40){ctx.beginPath();ctx.moveTo(0,y);ctx.lineTo(W,y);ctx.stroke();}
PACKAGES.forEach(pkg=>{
if(!isVisible(pkg))return;
pkg.deps&&pkg.deps.forEach(depId=>{
const dep=PACKAGES.find(p=>p.id===depId);
if(!dep||!isVisible(dep))return;
const a=nodePos(pkg),b=nodePos(dep);
ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);
ctx.strokeStyle=dark?'rgba(255,255,255,0.08)':'rgba(0,0,0,0.07)';
ctx.lineWidth=1;ctx.setLineDash([3,4]);ctx.stroke();ctx.setLineDash([]);
});
});
PACKAGES.forEach(pkg=>{
if(!isVisible(pkg))return;
const{x,y}=nodePos(pkg);
const r=nodeRadius(pkg);
const col=CAT_COLORS[pkg.cat]||'#888';
const alpha=STATUS_OPACITY[pkg.status];
const stroke=STATUS_STROKE[pkg.status];
const hov=hoveredId===pkg.id;
ctx.save();
ctx.globalAlpha=alpha*(hov?1:0.88);
if(hov){ctx.shadowColor=col;ctx.shadowBlur=12;}
ctx.beginPath();ctx.arc(x,y,r+(hov?2:0),0,Math.PI*2);
ctx.fillStyle=col;ctx.fill();
ctx.strokeStyle=stroke;ctx.lineWidth=hov?2:1.5;ctx.stroke();
ctx.shadowBlur=0;
if(hov||r>11){
ctx.font=`${Math.round(10*(scale/600))}px var(--font-mono)`;
ctx.fillStyle=dark?'rgba(255,255,255,0.7)':'rgba(0,0,0,0.6)';
ctx.textAlign='center';
ctx.fillText(pkg.id,x,y+r+12*(scale/600));
}
ctx.restore();
});
}
function getHovered(mx,my){
for(let i=PACKAGES.length-1;i>=0;i--){
const pkg=PACKAGES[i];
if(!isVisible(pkg))continue;
const{x,y}=nodePos(pkg);
if(Math.hypot(mx-x,my-y)<nodeRadius(pkg)+4)return pkg.id;
}
return null;
}
canvas.addEventListener('mousemove',e=>{
const rect=canvas.getBoundingClientRect();
const mx=e.clientX-rect.left,my=e.clientY-rect.top;
if(dragging){pan.x=panStart.x+(mx-dragStart.x);pan.y=panStart.y+(my-dragStart.y);draw();return;}
const id=getHovered(mx,my);
if(id!==hoveredId){hoveredId=id;draw();}
if(id){
const pkg=PACKAGES.find(p=>p.id===id);
const{x,y}=nodePos(pkg);
document.getElementById('t-name').textContent=pkg.name;
document.getElementById('t-desc').textContent=pkg.desc;
const tagsEl=document.getElementById('t-tags');
tagsEl.innerHTML=`<span class="tag">${pkg.cat}</span><span class="tag">${pkg.status}</span>${pkg.deps&&pkg.deps.length?`<span class="tag">${pkg.deps.length} dep${pkg.deps.length>1?'s':''}</span>`:''}`;
let tx=x+20,ty=y-10;
if(tx+230>W)tx=x-240;
if(ty+120>H)ty=H-120;
tooltip.style.left=tx+'px';tooltip.style.top=ty+'px';tooltip.style.opacity='1';
canvas.style.cursor='pointer';
} else {
tooltip.style.opacity='0';canvas.style.cursor='grab';
}
});
canvas.addEventListener('mousedown',e=>{
dragging=true;
const rect=canvas.getBoundingClientRect();
dragStart={x:e.clientX-rect.left,y:e.clientY-rect.top};
panStart={x:pan.x,y:pan.y};
canvas.style.cursor='grabbing';
});
window.addEventListener('mouseup',()=>{dragging=false;canvas.style.cursor='grab';});
canvas.addEventListener('mouseleave',()=>{hoveredId=null;tooltip.style.opacity='0';draw();});
document.querySelectorAll('.ftag').forEach(btn=>{
btn.addEventListener('click',()=>{
document.querySelectorAll('.ftag').forEach(b=>b.classList.remove('active'));
btn.classList.add('active');
activeFilter=btn.dataset.cat;
hoveredId=null;tooltip.style.opacity='0';
draw();
});
});
window.addEventListener('resize',resize);
resize();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment