by thebanri
Terminal UI engine for Go that tests can click and AI agents can drive (MCP). Zero-allocation rendering, immediate mode + Elm architecture, 3D, images, charts, accessibility, WebAssembly.
# Add to your Claude Code skills
git clone https://github.com/thebanri/limoniSee how limoni compares with popular alternatives.
limoni is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by thebanri. Terminal UI engine for Go that tests can click and AI agents can drive (MCP). Zero-allocation rendering, immediate mode + Elm architecture, 3D, images, charts, accessibility, WebAssembly. It has 124 GitHub stars.
limoni's catalog security scan is still queued. You can run an instant dependency and prompt-injection check now with the "Scan for vulnerabilities" button above.
Clone the repository with "git clone https://github.com/thebanri/limoni" and add it to your Claude Code skills directory (see the Installation section above).
limoni is primarily written in Go. It is open-source under thebanri on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh limoni against similar tools.
No comments yet. Be the first to share your thoughts!
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
The deep catalog scan for this skill is still queued. Run an instant dependency check now instead.
go get github.com/thebanri/limoni
package main
import "github.com/thebanri/limoni"
func main() {
limoni.Run(func(f *limoni.Frame, ev *limoni.Event) bool {
if ev != nil && ev.Type == limoni.EventKey && ev.Key.Type == limoni.KeyEsc {
return false // quit
}
f.RenderComponent(limoni.Border(
limoni.Center(limoni.Label("Hello from Limoni 🍋 (Esc quits)", limoni.Bold())),
limoni.SymbolsRounded,
limoni.Fg(limoni.Hex("#FFCC00")),
), f.Area())
return true
})
}
Or generate a project that runs straight away, with a test already written:
go run github.com/thebanri/limoni/cmd/limoni@latest new myapp # -template counter|dashboard|form|ssh
cd myapp && go mod tidy && go run .
go test ./... # a uitest test comes with every template
Next: Getting started · Widget gallery · Examples
Most terminal automation, such as termwright or mcp-tui-test, parses the rendered character grid, so a test breaks when the layout moves by one column. A Limoni app builds a semantic tree every frame (the same tree a screen reader uses), and the tools below work on that tree instead.
uitest: Playwright-style tests. Checks wait instead of sleeping, and a failure
prints the whole tree of the last frame.
page := uitest.Run(t, 80, 24, app.draw) // in process: no terminal needed
page.GetByRole("input", "New task").Type("Tag v1.0")
page.GetByRole("button", "Add task").Click()
page.Expect(page.GetByRole("list-item", "").Within(page.GetByRole("list", "Tasks"))).ToHaveCount(3)
page.Expect(page.GetByID("status")).ToContainLabel("Added")
limoni-mcp: let an AI agent drive the app. It gives Claude Code, Cursor or any
MCP client eight tools (tree, click, type_text, wait_for…) that work on the
same tree. In one recorded run, Claude Code completed a release checklist in 17 tool
calls. That run included typing a deploy token the agent could not read back.
go run -tags limoni_debug ./examples/agent_checklist
claude mcp add limoni -- limoni-mcp -socket "$XDG_RUNTIME_DIR/limoni-checklist.sock"
The automation socket only exists in -tags limoni_debug builds. It is closed by
default, only the same user can connect, and secret fields are never exposed.
→ Semantic automation, MCP and uitest
ECH/EL and repeats become REP: a full-screen redraw is 377 bytes, and an idle app sends nothing. Bytes, not CPU, are what you feel over SSH.| Measured on a Ryzen 5 5600, Go 1.27.1 | Latency | Allocations |
|---|---|---|
| Full-screen diff, 120×40, every cell changed | ~50 µs | 0 |
| 10% of the screen changed | ~24 µs | 0 |
| Nothing changed | ~2 ns | 0 |
| 100 layered blocks, drawn and diffed | ~68 µs | 0 |
Absolute numbers depend on the machine. The comparisons against Ratatui 0.30.2, Ultraviolet and Bubble Tea v1.3.10, including which ratios are not meaningful, are in docs/benchmarks.md and the methodology. One earlier run showed a 4,700× lead; it came from a bug in the benchmark harness, and the methodology explains how it was caught.
| 🕶️ 3D | A software rasteriser for OBJ/STL/PLY/GLB with Lambert and Gouraud shading, drawn in terminal cells |
| 🖼️ Images | Kitty, Sixel, iTerm2 and half-block fallback |
| 📊 Charts | Braille line charts, bar charts, pie charts, sparklines |
| 📝 Markdown | GFM rendering with a scrollable reader |
| ♿ Accessibility | A semantic tree, a screen-reader line mode, NO_COLOR, high contrast, reduced motion |
| 🧬 Unicode | UAX #29 grapheme clusters (Unicode 17.0, all 766 conformance tests), so flags and emoji families take one cell |
| 🔗 Hyperlinks | OSC 8 links, in markdown or any style — and where the terminal cannot show them, the address is printed instead |
| 📃 Inline mode | Render in a band of the normal screen, like gum, with scrollback intact |
| ⏺️ Session replay | Record a session, replay it as a regression test (docs) |
| 🌐 Everywhere | Linux, macOS, BSD, Windows, WebAssembly in the browser, SSH sessions |
The only dependencies are golang.org/x/sys and golang.org/x/crypto.
Pick Limoni if you are writing a terminal app in Go and any of these matter:
uitest, limoni-mcp).limoni.Run) for
dashboards, the Elm architecture (limoni.RunProgram) for forms and wizards.golang.org/x/sys and golang.org/x/crypto.Pick something else if:
compat/bubbletea runs your models on Limoni
(migration guide), so you can try it without a rewrite.A feature-by-feature table against Bubble Tea v1/v2 and Ratatui 0.30 is in docs/comparison.md.
zest is a log viewer and Limoni's flagship app. It follows files and pipes, colours by level, and filters a million lines without stalling. A 67 MiB, 1,000,000-line log is on screen in about half a second.
go install github.com/thebanri/limoni/cmd/zest@latest
zest -demo 1000000 # or: zest app.log, kubectl logs -f pod | zest
Or try it in the browser: the "Logs · zest" scene.
globe is a world you can turn, search, zoom into and pin — and what a Limoni application looks like from the outside, since it is a module of its own that depends on a published Limoni and uses nothing but its public API.
go install github.com/thebanri/limoni/apps/globe@latest
globe -at Türkiye
go install puts the binary in $(go env GOPATH)/bin — ~/go/bin unless you changed it —
which a fresh Go install does not add to your PATH. If globe is "command not found", add
that directory to PATH or run ~/go/bin/globe.
Everything on it is in the semantic tree, so "find Turkey on the world map" is something an agent
can do over MCP: type into search, click the