I published the first public version of termbox-glib, a small C wrapper around termbox2 for GLib/GObject programs and languages using GObject Introspection.
The goal is simple: make termbox2 feel natural in a GLib application. The library exposes a TbgTerminal object that owns the terminal lifetime, reports errors with GError, integrates input events with GMainContext, and ships introspection metadata for bindings such as GJS and Vala.
The current API is alpha quality. It is usable enough to write small terminal applications, and the C wrapper should already cover the useful termbox2 API surface. Source and ABI stability are not promised yet.
What is already there:
- terminal initialization and shutdown through a GObject lifetime
- text, cell, cursor, and attribute drawing helpers
- input, resize, and mouse events through a
GSource - typed key, mouse, resize, cell, and attribute boxed types
- C, GJS, and Vala examples
- gi-docgen and Valadoc documentation
- SourceHut CI coverage for Arch Linux, Alpine Linux, Debian, and FreeBSD
Arch Linux users can install the development package from the AUR:
paru -S termbox-glib-gitGetting started
Applications compile against the installed pkg-config package:
cc hello.c `pkg-config --cflags --libs termbox-glib-0.1` -o hello
Use the umbrella header:
#include <termbox-glib.h>
The simplest program creates a TbgTerminal, draws text into the back buffer,
and presents the buffer:
#include <glib.h>
#include <termbox-glib.h>
int
main (void)
{
g_autoptr (TbgTerminal) terminal = tbg_terminal_new (NULL);
if (terminal == NULL)
return 1;
TbgAttr fg = tbg_attr_color (TBG_COLOR_GREEN, TBG_ATTR_FLAGS_BOLD);
TbgAttr bg = tbg_attr_default ();
tbg_terminal_print (terminal, 0, 0, fg, bg, "hello from termbox-glib", NULL);
tbg_terminal_present (terminal, NULL);
g_usleep (G_USEC_PER_SEC * 3);
return 0;
}

To receive input without blocking GLib, attach the terminal event source to a
GMainContext and listen to typed terminal signals:
#include <glib.h>
#include <termbox-glib.h>
static void
on_key (TbgTerminal *terminal, TbgKeyEvent *event, gpointer user_data)
{
GMainLoop *loop = user_data;
if (tbg_key_event_get_char (event) == 'q')
g_main_loop_quit (loop);
}
int
main (void)
{
g_autoptr (TbgTerminal) terminal = tbg_terminal_new (NULL);
g_autoptr (GSource) source = NULL;
g_autoptr (GMainLoop) loop = NULL;
if (terminal == NULL)
return 1;
loop = g_main_loop_new (NULL, FALSE);
g_signal_connect (terminal, "key", G_CALLBACK (on_key), loop);
TbgAttr fg = tbg_attr_color (TBG_COLOR_GREEN, TBG_ATTR_FLAGS_BOLD);
TbgAttr bg = tbg_attr_default ();
tbg_terminal_print (terminal, 0, 0, fg, bg, "press q to quit", NULL);
tbg_terminal_present (terminal, NULL);
source = tbg_terminal_create_event_source (terminal, NULL);
if (source == NULL)
return 1;
g_source_attach (source, NULL);
g_main_loop_run (loop);
g_source_destroy (source);
return 0;
}

Links:
A lot of the wrapper and documentation was generated with AI assistance from the termbox2 source code, then reviewed and adapted to GLib/GObject and GObject Introspection conventions.