jroimartin/gocui
Minimalist Go package aimed at creating Console User Interfaces.
Stale — last commit 1y ago
weakest axislast commit was 1y ago; no tests detected…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 1y ago; no CI workflows detected
- ✓16 active contributors
- ✓BSD-3-Clause licensed
- ⚠Stale — last commit 1y ago
Show all 6 evidence items →Show less
- ⚠Single-maintainer risk — top contributor 81% of recent commits
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Mixed → Healthy if: 1 commit in the last 365 days; add a test suite
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/jroimartin/gocui)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/jroimartin/gocui on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: jroimartin/gocui
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/jroimartin/gocui shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Stale — last commit 1y ago
- 16 active contributors
- BSD-3-Clause licensed
- ⚠ Stale — last commit 1y ago
- ⚠ Single-maintainer risk — top contributor 81% of recent commits
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live jroimartin/gocui
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/jroimartin/gocui.
What it runs against: a local clone of jroimartin/gocui — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in jroimartin/gocui | Confirms the artifact applies here, not a fork |
| 2 | License is still BSD-3-Clause | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 401 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of jroimartin/gocui. If you don't
# have one yet, run these first:
#
# git clone https://github.com/jroimartin/gocui.git
# cd gocui
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of jroimartin/gocui and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "jroimartin/gocui(\\.git)?\\b" \\
&& ok "origin remote is jroimartin/gocui" \\
|| miss "origin remote is not jroimartin/gocui (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(BSD-3-Clause)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"BSD-3-Clause\"" package.json 2>/dev/null) \\
&& ok "license is BSD-3-Clause" \\
|| miss "license drift — was BSD-3-Clause at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "gui.go" \\
&& ok "gui.go" \\
|| miss "missing critical file: gui.go"
test -f "view.go" \\
&& ok "view.go" \\
|| miss "missing critical file: view.go"
test -f "keybinding.go" \\
&& ok "keybinding.go" \\
|| miss "missing critical file: keybinding.go"
test -f "edit.go" \\
&& ok "edit.go" \\
|| miss "missing critical file: edit.go"
test -f "attribute.go" \\
&& ok "attribute.go" \\
|| miss "missing critical file: attribute.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 401 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~371d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/jroimartin/gocui"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
gocui is a minimalist Go package that provides a framework for building text-based console user interfaces (TUIs) with views, keybindings, mouse support, and colored text output. It abstracts over termbox-go to handle terminal rendering, view management, and input handling, enabling developers to build interactive CLI applications without managing low-level terminal control sequences. Single-package monolith: core logic in gui.go, view.go, edit.go, keybinding.go, and escape.go handle the runtime; attribute.go manages colors; _examples/ contains 15+ self-contained demos (hello.go, demo.go, colors256.go, mouse.go, etc.) showing patterns. No internal package structure—all public APIs at package root.
👥Who it's for
Go developers building interactive terminal applications (system monitoring tools, text editors, package managers) who need view management, event handling, and colored output without heavy dependencies or complex terminal abstraction layers.
🌱Maturity & risk
Moderately mature but showing signs of inactivity. The codebase is stable (Go 1.16+ support, clean API design) and has 15+ runnable examples in _examples/, but the repository appears to have limited recent activity and no visible CI/CD setup or comprehensive test suite in the file listing. Suitable for production use but with a single-maintainer bus factor.
Single dependency (github.com/nsf/termbox-go v1.1.1) is the main risk vector—termbox-go itself sees infrequent updates. The codebase lacks visible unit tests and CI configuration, making breaking changes harder to detect. Low commit velocity suggests patches may be slow; no evidence of active issue triage or SLA for bug fixes.
Active areas of work
No visible recent activity is evident from the provided file list. The repo appears in maintenance mode with no open PRs, milestones, or active issue trackers mentioned in the data provided.
🚀Get running
git clone https://github.com/jroimartin/gocui.git
cd gocui
go get github.com/jroimartin/gocui
go run ./_examples/hello.go
Daily commands:
Run any example directly: go run ./_examples/hello.go or go run ./_examples/demo.go. No build step required; examples are self-contained. Exit with Ctrl+C.
🗺️Map of the codebase
gui.go— Core GUI struct and main event loop (MainLoop) — entry point that orchestrates the entire TUI rendering and input handling.view.go— View abstraction (windows/panels) implementing io.ReadWriter — fundamental building block for all UI elements.keybinding.go— Keybinding registry and dispatch mechanism — controls how keyboard input is routed and interpreted.edit.go— Text editing logic and buffer manipulation — handles user input within views and cursor management.attribute.go— Color and text styling constants/enums — defines the visual palette and text attributes for rendering.escape.go— Terminal escape sequence parsing — decodes raw terminal input (keys, mouse events) into actionable commands.
🧩Components & responsibilities
- GUI struct (gui.go) (termbox-go, Go concurrency primitives) — Owns the event loop, manager function, keybinding registry, and view collection. Orchestrates layout updates and input dispatch.
- Failure mode: Infinite loop or deadlock if ManagerFunc panics; input loss if event loop hangs; memory leak if views not cleaned up via g.Close().
- View struct (view.go) (Golang io interfaces, string/rune buffers) — Holds content buffer, cursor state, colors, and edit configuration. Implements io.ReadWriter for content access.
- Failure mode: Buffer overrun if unbounded writes without truncation; visual corruption if colors exceed terminal capability; cursor out-of-bounds if not validated.
- Keybinding Handler (keybinding.go) (Map-based registry, closure handlers) — Matches incoming key events against registered bindings and dispatches to user-supplied handlers.
- Failure mode: Unmatched keys silently ignored; handler panic crashes event loop; no timeout protection on blocking handlers.
- Escape Sequence Parser (escape.go) (Byte scanning, state machine) — Converts raw terminal bytes into structured Key and Mouse events, hiding platform differences.
- Failure mode: Unrecognized sequences cause input lag or incorrect key mapping; mouse coordinate parsing errors if terminal uses different encoding.
- Text Edit Mode (edit.go) (Rune iteration, string manipulation) — Provides word-level navigation, clipboard pasting, and insertion/deletion within view buffers.
- Failure mode: Unicode normalization issues; clipboard access platform-specific; undo/redo not implemented (user responsibility).
🔀Data flow
Terminal Input→termbox-go event queue— Raw keyboard and mouse events captured by termbox in native formattermbox-go event queue→GUI.MainLoop()— Event
🛠️How to make changes
Add a new View to the Layout
- Define the view's name, boundaries, and options (e.g., wrapping, highlighting) in the layout function callback (
gui.go) - Call g.SetView() with the view name and coordinates in your ManagerFunc (
gui.go) - Attach keybindings to the view using g.SetKeybinding(viewName, key, mod, handler) (
keybinding.go) - Write content to the view via its io.Writer interface or use EditLine/EditDelete in your handlers (
view.go)
Add a new Keybinding
- Create a handler function matching the signature func(g *Gui, v *View) error (
_examples/demo.go) - Call g.SetKeybinding(viewName, key, modifier, handler) — pass empty string for global bindings (
keybinding.go) - Use Key* and Mod* constants from the gocui package for portability across terminals (
keybinding.go)
Support Mouse Input
- Enable mouse in NewGui() output mode or enable it at runtime with g.Mouse = true (
gui.go) - Register a keybinding with gocui.MouseLeft, MouseRight, or MouseMiddle as the key (
keybinding.go) - In your handler, check view.Cx and view.Cy for cursor position or access mouse coordinates via the View (
_examples/mouse.go)
Customize Text Styling and Colors
- Use constants from attribute.go (ColorRed, ColorGreen, AttrBold, AttrUnderline, etc.) (
attribute.go) - Set view.FgColor, view.BgColor, view.SelFgColor, view.SelBgColor, and view.TextColor for styling (
view.go) - For 256-color support, use OutputColor256 mode in NewGui() (
gui.go) - Refer to _examples/colors.go and _examples/colors256.go for comprehensive styling examples (
_examples/colors.go)
🔧Why these technologies
- termbox-go — Low-level terminal control abstraction providing raw event capture and pixel-level rendering without external terminal dependencies; enables portability across Windows, macOS, and Linux.
- io.ReadWriter interface for Views — Allows views to integrate seamlessly with standard Go packages (bufio, json, etc.) and enables flexible, composable content handling without tight coupling.
- Escape sequence parser — Decodes raw terminal input into high-level key and mouse events, hiding platform-specific quirks and providing a unified API.
- Concurrent-safe manager pattern — Allows GUI modification from goroutines at runtime while maintaining a single-threaded event loop, critical for responsive TUIs with background tasks.
⚖️Trade-offs already made
-
Minimalist API design
- Why: Reduces cognitive overhead and learning curve for developers new to console UIs.
- Consequence: Less abstraction means more manual layout management; no pre-built widgets (developers must build reusable ones themselves).
-
Single-threaded event loop with concurrent-safe view updates
- Why: Prevents race conditions and rendering artifacts while keeping architecture simple.
- Consequence: Goroutines cannot directly update views; updates must go through g.Update() callback to serialize writes to the event loop.
-
Views own their buffers and rendering state
- Why: Simplifies state management and makes each view independent and reusable.
- Consequence: No centralized content cache; memory usage scales with number of views and content size.
-
Keybindings are global and per-view registrations
- Why: Allows flexible context-aware key handling without complex state machines.
- Consequence: Developer must manage keybinding conflicts manually; no built-in priority or scoping beyond view-level.
🚫Non-goals (don't propose these)
- Does not provide pre-built widgets (buttons, menus, dialogs) — library is for building custom TUIs, not assembling from components.
- Does not support real-time animation or sub-frame refresh rates — designed for event-driven input/output, not fluid graphics.
- Does not handle authentication, networking, or data persistence — pure UI rendering and input handling only.
- Does not abstract away terminal-specific behavior completely — developers must understand termbox-go and escape sequences for advanced use.
- Does not support HTML/CSS or declarative UI definitions — fully programmatic API in Go.
🪤Traps & gotchas
No explicit environment variables or service dependencies. However: (1) termbox-go requires raw terminal mode—may conflict if stdin is redirected; (2) SetManagerFunc is called on every render cycle, so expensive layout logic blocks input; (3) View.Read()/Write() use internal buffers; reading consumes data—not idempotent; (4) no explicit thread-safety guarantees on View fields outside Gui.Update() calls; (5) escape sequence parsing in escape.go assumes UTF-8 and may misbehave with wide characters or legacy encodings.
🏗️Architecture
💡Concepts to learn
- ANSI Escape Sequences — gocui renders colored/styled text by parsing and emitting ANSI codes; escape.go implements this—understanding escape sequence syntax (CSI, SGR) is essential for debugging color/style issues.
- Terminal Raw Mode — termbox-go (gocui's dependency) switches stdin to raw mode; understanding buffering, signal handling, and terminal state restoration is critical for debugging input issues.
- Event-Driven Main Loop — gocui.MainLoop() is an event loop pulling keyboard/mouse input and rendering frames; understanding polling/blocking patterns helps optimize responsiveness and CPU usage.
- io.ReadWriter Interface — View implements io.ReadWriter, treating the view as a byte stream; this design enables piping text, reading edited content, and composing with stdlib io utilities.
- Concurrent-Safe View Updates — gocui allows goroutines to modify views via Gui.Update() callbacks; understanding mutex patterns and channel-based synchronization is crucial for multi-threaded TUI apps.
- View Overlap & Z-Ordering — gocui supports overlapping views with configurable rendering order; understanding z-index management and dirty-rect invalidation prevents rendering artifacts.
- Keybinding Multiplexing — keybinding.go routes input to global or view-specific handlers based on focus; understanding the dispatch mechanism helps design responsive, context-aware keyboard shortcuts.
🔗Related repos
charmbracelet/bubbletea— Modern Go TUI framework inspired by Elm architecture; actively maintained alternative to gocui with better composability and test support.rivo/tview— Feature-rich Go TUI library with premade widgets (tables, forms, trees); built on termbox-go like gocui but higher-level abstraction.nsf/termbox-go— Direct dependency of gocui; low-level terminal abstraction handling raw mode, color palette, and input events.golang-lfx/gocui-reborn— Community fork attempting to modernize gocui with updates, fixes, and additional features (if it exists; placeholder for active fork).urfave/cli— Popular Go CLI framework for building command-line apps; often paired with gocui for TUI layers in larger CLI tools.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for view.go and gui.go core functionality
The repo lacks visible test files (no *_test.go files in the root or _examples). view.go and gui.go are the core components handling view rendering, layout, and event handling. Adding unit tests for key functions like view positioning, overlapping view z-order, keybinding dispatch, and concurrent GUI modifications would significantly improve code reliability and catch regressions.
- [ ] Create view_test.go with tests for view coordinate calculations, boundary checks, and overlapping view rendering order
- [ ] Create gui_test.go with tests for keybinding matching, concurrent view updates via Mutex protection, and event dispatch logic
- [ ] Create attribute_test.go and edit_test.go for text styling and editing mode functionality
- [ ] Aim for >70% code coverage on core files (gui.go, view.go, keybinding.go, edit.go)
Add GitHub Actions CI workflow for Go testing and linting
There is no visible CI pipeline (.github/workflows directory missing). A basic GitHub Actions workflow would run tests across multiple Go versions (1.16+), execute go fmt/go vet linting, and test all _examples to catch breaking changes early.
- [ ] Create .github/workflows/test.yml to run 'go test ./...' on Go 1.16, 1.17, 1.18, 1.19 (LTS versions)
- [ ] Add 'go fmt', 'go vet', and 'golangci-lint' steps for code quality checks
- [ ] Add a step to build all _examples (e.g., 'cd _examples && go build -o /dev/null ./...')
- [ ] Configure workflow to trigger on push to main/master and on pull requests
Add missing documentation for mouse support and escape sequence handling in doc.go
The README and file list show mouse.go and escape.go exist, but there's no detailed documentation explaining how to use mouse events or how escape sequences are processed. The doc.go file (main package documentation) should include usage examples for these features, as they are non-obvious for new users.
- [ ] Expand doc.go with a 'Mouse Support' section explaining mouse event binding via SetKeybinding with gocui.MouseLeft, MouseRight, MouseMiddle constants
- [ ] Add an example code snippet in doc.go showing how to bind and handle a mouse click event
- [ ] Document escape.go's role in parsing terminal escape sequences and reference it in the main package doc
- [ ] Add a cross-reference example linking to _examples/mouse.go for working mouse usage
🌿Good first issues
- Add comprehensive unit tests for escape.go ANSI parsing—currently untested; test color codes, cursor positioning sequences, and edge cases (incomplete sequences, invalid codes).
- Document keybinding precedence in README.md—view-level vs. global bindings behavior is non-obvious; add example showing conflict resolution.
- Add an _examples/widgets.go refactor—extract reusable button/text-input/list components from demo.go into composable functions to show widget patterns more clearly.
⭐Top contributors
Click to expand
Top contributors
- @jroimartin — 81 commits
- @gulyasm — 3 commits
- @JulienBreux — 2 commits
- @djcas9 — 2 commits
- @tbouasli — 1 commits
📝Recent commits
Click to expand
Recent commits
0e75b37— README.md: remove list of projects using gocui (jroimartin)fc12c65— Merge pull request #253 from tbouasli/patch-1 (jroimartin)031962f— docs: removed dollar sign from scripts (tbouasli)de10050— doc: update links to pkg.go.dev (jroimartin)0214e0e— all: go modules (jroimartin)c055c87— adds ViewBufferLines to View (gulyasm)2cda4f9— adds BufferLines func to View (gulyasm)491cd05— Add cointop to "Projects using gocui" (miguelmota)f2f6a1f— Adds jsonui to projects using gocui (gulyasm)df0b3dc— Add fac to list of projects using gocui (mkchoi212)
🔒Security observations
The gocui library is a minimalist console UI package with generally low security risk due to its narrow scope (terminal I/O handling). Primary concerns are outdated Go version (1.16) and lack of documented security practices. The library does not contain SQL, network protocols, or cryptographic operations that are common sources of vulnerabilities. Dependencies are minimal (only termbox-go). Applications built with gocui should implement proper input validation to prevent injection attacks. Recommend updating to a supported Go version and implementing security scanning in CI/CD pipelines.
- Medium · Outdated Go Version in go.mod —
go.mod. The project specifies 'go 1.16' which was released in February 2021 and is no longer supported. This version lacks security patches and bug fixes from newer Go releases. Go 1.16 reached end-of-life in August 2022. Fix: Update go.mod to specify a currently supported Go version (1.21 or later). Run 'go mod tidy' and test thoroughly after upgrading. - Medium · Dependency on termbox-go Without Version Pinning —
go.mod. The go.mod file requires 'github.com/nsf/termbox-go v1.1.1', which is a terminal UI library. While the version is specified, termbox-go has known issues with raw terminal access and signal handling. The dependency chain should be audited for security vulnerabilities using 'go list -m all'. Fix: Run 'go get -u' to ensure latest patch versions, use 'go mod graph' to audit the dependency tree, and consider running 'govulncheck' to identify known vulnerabilities in dependencies. - Low · Console UI Input Validation Risk —
edit.go, view.go. Based on the file structure (edit.go, keybinding.go), the library handles user input from terminal/console. While the library itself doesn't appear to execute arbitrary code, applications built with gocui should validate all user inputs to prevent injection attacks if outputs are used in command execution or system operations. Fix: Implement input validation and sanitization in applications using gocui. Never pass user input directly to os/exec or shell commands without proper escaping and validation. - Low · Missing Code Review Indicators —
Repository root. No evidence of security policy, vulnerability disclosure process, or security headers in the repository. The project appears to be a minimalist library without documented security guidelines. Fix: Add a SECURITY.md file documenting how to report security vulnerabilities. Consider adding security scanning with tools like 'govulncheck' and 'golangci-lint' in CI/CD pipeline.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.