Interactive Terminal for AI Agents β automating gdb, lldb, and other TUI applications
| Field | Value |
|---|---|
| Status | β Current as of February 2026 |
| Difficulty | βββββ β intermediate level |
| Time | ~30 minutes reading + practice |
| Goal | Learn to use interminai for automated debugging via gdb/lldb |
| Resources | β’ interminai GitHub β’ lldb docs β’ Test programs: mem_basis/example/ |
interminai is a terminal proxy that enables programmatic interaction with interactive CLI applications (vim, git, gdb, lldb, etc.).
βββββββββββββββ ββββββββββββββββ βββββββββββββββ
β AI Agent βββββββ interminai βββββββ gdb/lldb β
β (Claude) β TCP β (PTY) β PTY β (Target) β
βββββββββββββββ Socket ββββββββββββββββ βββββββββββββββ
β β
--socket PATH Debug binary
# Quick install via npx skills
npx skills add mstsirkin/interminai
# Or manually (Python)
pip install --break-system-packages pyte
cd /path/to/interminai
python3 interminai.py --help| Command | Description | Example |
|---|---|---|
start |
Start program in background daemon mode | interminai start --socket /tmp/dbg.sock -- lldb ./program |
output |
Get terminal screen contents | interminai output --socket /tmp/dbg.sock |
input |
Send input to program | interminai input --socket /tmp/dbg.sock --text "break main\n" |
stop |
Stop daemon | interminai stop --socket /tmp/dbg.sock |
status |
Check process status | interminai status --socket /tmp/dbg.sock |
- Step 1. Start debugger. Create UNIX socket and launch lldb/gdb.
- Step 2. Set breakpoints. Place stops at suspicious code locations.
- Step 3. Run program. Begin execution and wait for breakpoint hit.
- Step 4. Inspect state. Examine variables, memory, stack.
- Step 5. Continue execution. Proceed to capture ASAN/TSAN report.
Source code:
char *p = malloc(16);
free(p);
free(p); // β BUG: double free!| Action (Hard Skills) | Nuance / De-facto (Soft Skills) |
|---|---|
breakpoint set --file double_free.c --line 12 |
Set breakpoint on the second free(), not the first |
frame variable p |
Pointer value doesn't change β the problem is memory state, not the value |
continue |
ASAN will show where the first free was called β key to diagnosis |
Result: ASAN report: double-free double_free.c:12
Source code:
free(p);
char c = p[0]; // β BUG: read after free
p[0] = 'Z'; // β BUG: write after free| Action (Hard Skills) | Nuance / De-facto (Soft Skills) |
|---|---|
breakpoint set --line 17 |
Stop before reading freed memory |
frame variable p |
Pointer p is valid as an address, but memory at it is poisoned |
continue |
ASAN message "Use of deallocated memory" β first sign of UAF |
Result: ASAN report: Use of deallocated memory
Source code:
// Two threads increment same counter without synchronization
for (int i = 0; i < ITERS; ++i) {
int tmp = *counter; // read
tmp = tmp + 1; // modify
*counter = tmp; // write β RACE!
}| Action (Hard Skills) | Nuance / De-facto (Soft Skills) |
|---|---|
breakpoint set --name worker |
Stop at the beginning of thread function |
thread list |
On macOS typically 3+ threads: main + workers |
thread select 2 / thread select 3 |
Switch between threads β they read same value |
frame variable *counter |
Both threads see 0 β both will write 1 β lost update |
Result:
- Expected:
10,000,000 - Actual:
5,153,633(~48% lost to race conditions)
Source code:
char *p = malloc(16); // 16 bytes
for (int i = 0; i < 64; ++i) { // Write 64 bytes!
p[i] = 'a' + (i & 15);
}| Action (Hard Skills) | Nuance / De-facto (Soft Skills) |
|---|---|
breakpoint set --line 21 |
Stop inside the overflow loop |
frame variable p |
See p = 0x6020000000d0 β remember this address |
x/16bx p |
Examine memory to check current contents |
continue |
On next iteration ASAN will trigger at p[16] |
Result: ASAN report: heap-buffer-overflow at address 0x6020000000e0
| Bug Type | ASAN/TSAN Signal | Key Line | Characteristic Symptom |
|---|---|---|---|
| Double Free | attempting double-free |
Second free(p) |
Crash on deallocation |
| Use After Free | use-of-deallocated-memory |
p[0] = ... after free |
Read/write of poisoned memory |
| Race Condition | Lost updates (TSAN) | Unsynchronized shared access | Incorrect final values |
| Heap Corruption | heap-buffer-overflow |
Write past malloc boundary |
Allocator metadata corruption |
| Problem | Solution |
|---|---|
| gdb not working on macOS | GDB requires code-signing certificate. Use lldb instead |
pyte: not found |
Install dependency: pip install --break-system-packages pyte |
| Breakpoint not hitting | Ensure binary is compiled with debug symbols (-g) |
| ASAN shows no details | Recompile with -fsanitize=address -g |
| Socket already in use | Stop previous session: interminai stop --socket /tmp/sock |
| Output empty or has artifacts | Add sleep 0.5 between input and output for synchronization |
| lldb cannot find source files | Use absolute paths or settings set target.source-map |
| Aspect | GDB | LLDB |
|---|---|---|
| Installation | brew install gdb + code signing |
Built into Xcode |
| Stability | Requires certificate | Works out of box |
| Commands | break, run, frame var |
breakpoint set, process launch, frame variable |
Recommendation: Use lldb on macOS for simpler setup.
# 1. Create "gdb-cert" certificate in Keychain Access
# 2. Import to System keychain
# 3. Sign binary:
codesign -fs gdb-cert /opt/homebrew/bin/gdbCreate a shell script for repetitive debugging:
#!/bin/bash
SOCKET=/tmp/debug.sock
BINARY=$1
# Start lldb
interminai start --socket $SOCKET -- lldb $BINARY
sleep 1
# Set breakpoints
interminai input --socket $SOCKET --text "breakpoint set --name main\n"
sleep 0.5
# Run
interminai input --socket $SOCKET --text "run\n"
sleep 1
# Show result
interminai output --socket $SOCKET# List all threads
thread list
# Show backtrace for specific thread
thread select 2
bt
frame variable
# Switch to another thread
thread select 3
bt
frame variableCongratulations! You now know how to:
- β Use interminai for automated debugging
- β Diagnose double free, use after free, race conditions, heap corruption
- β Read and interpret ASAN/TSAN reports
- β Work with lldb through interactive terminal
- Practice: Debug your own program with memory bugs
- Learn: Study PROTOCOL.md for deep understanding
- Integrate: Incorporate interminai into your CI/CD for automated testing
- Contribute: Improve interminai β fork & PR on GitHub!
- π interminai Repository
- π LLDB Tutorial
- π AddressSanitizer Overview
- π§΅ ThreadSanitizer Overview
Author: Michael Tsirkin (mst@kernel.org) Document updated: February 2026 License: GNU GPL v2.0
π‘ Tip: Save this document to Notion or Obsidian for quick access during debugging. Use checklists as a cheat sheet when investigating bugs.