Genie is built with Bun and TypeScript. This guide covers setting up a development environment, running quality gates, and building plugins. We build in public because that’s the only honest way to build developer tools.
This produces dist/genie.js (~305KB minified) with all dependencies inlined. The shebang #!/usr/bin/env bun makes it directly executable. No runtime dependencies need to be co-located.
bun run typecheck # Type checking onlybun run lint # Linting onlybun run dead-code # Dead code detection onlybun test # All testsbun test src/lib/wish-state.test.ts # Single file
Skills are markdown files that define agent behavior. To add a new skill:
Create skills/<skill-name>/SKILL.md
Add frontmatter with name, description, and optional triggers
Write the skill prompt in the body
---name: my-skilldescription: Does something usefultriggers: - "/my-skill" - "run my skill"---# My SkillInstructions for the agent when this skill is invoked...
Skills are loaded dynamically — no registration needed beyond creating the file.
File lock timeout force-removes are intentional — prevents deadlocks from crashed processes. The open('wx') after unlink is atomic, so only one process wins.
Hook dispatch has a 15-second hard timeout — handlers that exceed this silently timeout.
System prompt injection can fail silently — if the prompt file write fails, Claude Code dies on startup trying to read it.
Mailbox delivery is best-effort — dead pane = message stays deliveredAt: null forever.
Genie is open source and we want your help — code, docs, bug reports, wild ideas, even polite disagreements about our architecture choices. Especially those, actually.
Discord
Chat with contributors, ask questions, share what you’re building.
GitHub
Issues, PRs, and the code itself. Star if you’re feeling generous.