Asi libghostty-aci

libghostty-aci: Terminal ACI Integration

install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/libghostty-aci" ~/.claude/skills/plurigrid-asi-libghostty-aci && rm -rf "$T"
manifest: skills/libghostty-aci/SKILL.md
source content

libghostty-aci: Terminal ACI Integration

Trit: 0 (ERGODIC - transport layer) Color: #46F27F (Coordinator stream) Seed: 1069


Overview

Integrates libghostty terminal emulation with Agent-Computer Interface (ACI) patterns:

IntegrationTritColorLibrary
Emacs vterm/eat-1#E7B367libghostty-vt
MCP Terminal0#46F27Flibghostty embedding
Daphne ASGI+1#F0D127WebSocket streaming

GF(3): -1 + 0 + 1 = 0 ✓


libghostty Type Mapping

Core Types (from lib_vt.zig)

// Terminal state machine
pub const Terminal = terminal.Terminal;
pub const Screen = terminal.Screen;
pub const Parser = terminal.Parser;

// Display elements
pub const Cell = page.Cell;
pub const Style = terminal.Style;
pub const Cursor = Screen.Cursor;

// Input handling
pub const input = struct {
    pub const Key = key.Key;
    pub const KeyEvent = key.KeyEvent;
    pub const KeyMods = key.Mods;
    pub const encodeKey = key_encode.encode;
    pub const encodePaste = paste.encode;
};

// Escape sequences
pub const CSI = Parser.Action.CSI;
pub const DCS = Parser.Action.DCS;
pub const osc = terminal.osc;

Embedding Types (from embedded.zig)

// Application lifecycle
pub const App.Options = extern struct {
    wakeup_callback: *const fn (*anyopaque) callconv(.C) void,
    action_callback: *const fn (*anyopaque, Action) callconv(.C) bool,
    clipboard_read: *const fn (*anyopaque, Clipboard) callconv(.C) void,
    clipboard_write: *const fn (Clipboard, [*:0]const u8, usize) callconv(.C) void,
    clipboard_write_small: *const fn (Clipboard, [*]const u8, usize) callconv(.C) void,
};

// Surface management
pub const Surface = struct {
    pub fn setSize(self: *Surface, width: usize, height: usize) void;
    pub fn handleInput(self: *Surface, event: KeyEvent) void;
    pub fn render(self: *Surface) RenderState;
};

Emacs Integration (-1 MINUS)

vterm Backend

;; Use libghostty-vt for VT parsing instead of libvterm
(defcustom vterm-backend 'ghostty
  "Terminal emulation backend: 'libvterm or 'ghostty"
  :type '(choice (const libvterm) (const ghostty)))

(defun ghostty-vt-make-terminal (width height)
  "Create ghostty terminal with dimensions."
  (let ((term (ghostty-vt-new)))
    (ghostty-vt-resize term width height)
    term))

(defun ghostty-vt-process-output (term data)
  "Feed data through ghostty parser."
  (ghostty-vt-feed term data)
  (ghostty-vt-get-screen term))

eat Integration

;; eat (Emulate A Terminal) can use ghostty for parsing
(defun eat-ghostty-adapter (process output)
  "Adapt ghostty-vt output to eat display."
  (let ((parsed (ghostty-parse-stream output)))
    (eat-render-cells (ghostty-cells-to-eat parsed))))

Key Encoding

;; Use ghostty key encoding for terminal input
(defun ghostty-encode-key (key mods)
  "Encode key event for terminal using ghostty."
  (ghostty-input-encode-key
   (ghostty-make-key-event key mods)))

MCP Terminal Server (0 ERGODIC)

Terminal Streaming Protocol

// MCP server exposing terminal capabilities
interface GhosttyMCPServer {
  tools: {
    "terminal/create": {
      params: { width: number; height: number; };
      returns: { session_id: string; };
    };
    "terminal/write": {
      params: { session_id: string; data: string; };
      returns: { cells_changed: number; };
    };
    "terminal/read": {
      params: { session_id: string; };
      returns: { screen: Cell[][]; cursor: Position; };
    };
    "terminal/resize": {
      params: { session_id: string; width: number; height: number; };
      returns: { success: boolean; };
    };
    "terminal/input": {
      params: { session_id: string; key: string; mods: string[]; };
      returns: { encoded: string; };
    };
  };
}

Rust MCP Implementation

use ghostty_vt::{Terminal, Parser, Screen};

struct GhosttyMCP {
    terminals: HashMap<String, Terminal>,
}

impl GhosttyMCP {
    fn create_terminal(&mut self, width: u16, height: u16) -> String {
        let id = Uuid::new_v4().to_string();
        let term = Terminal::new(width, height);
        self.terminals.insert(id.clone(), term);
        id
    }

    fn write(&mut self, id: &str, data: &[u8]) -> usize {
        let term = self.terminals.get_mut(id)?;
        term.process(data);
        term.screen().damage_count()
    }

    fn read(&self, id: &str) -> Screen {
        self.terminals.get(id)?.screen().clone()
    }
}

WebSocket Streaming

async fn terminal_websocket(ws: WebSocket, term_id: String) {
    let (mut sink, mut stream) = ws.split();

    // Input handler
    tokio::spawn(async move {
        while let Some(msg) = stream.next().await {
            if let Ok(Message::Binary(data)) = msg {
                term.process(&data);
            }
        }
    });

    // Output streamer (60fps)
    loop {
        let screen = term.screen();
        let json = serde_json::to_string(&screen)?;
        sink.send(Message::Text(json)).await?;
        tokio::time::sleep(Duration::from_millis(16)).await;
    }
}

Daphne ASGI Integration (+1 PLUS)

Django Channels Terminal

# consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
import ghostty_vt  # Python bindings

class TerminalConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.terminal = ghostty_vt.Terminal(80, 24)
        await self.accept()

    async def receive(self, text_data=None, bytes_data=None):
        if bytes_data:
            # Process input through ghostty
            self.terminal.process(bytes_data)

            # Send screen update
            screen = self.terminal.screen_json()
            await self.send(text_data=screen)

    async def disconnect(self, close_code):
        del self.terminal

ASGI Middleware

# middleware.py
class GhosttyTerminalMiddleware:
    """ASGI middleware for terminal WebSocket connections."""

    def __init__(self, app):
        self.app = app

    async def __call__(self, scope, receive, send):
        if scope["type"] == "websocket" and scope["path"].startswith("/terminal/"):
            await self.handle_terminal(scope, receive, send)
        else:
            await self.app(scope, receive, send)

    async def handle_terminal(self, scope, receive, send):
        term = ghostty_vt.Terminal(80, 24)

        while True:
            message = await receive()
            if message["type"] == "websocket.receive":
                data = message.get("bytes", b"")
                term.process(data)

                await send({
                    "type": "websocket.send",
                    "text": term.screen_json()
                })

Daphne Configuration

# asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter([
            path("terminal/<session_id>/", TerminalConsumer.as_asgi()),
        ])
    ),
})

# Run with: daphne -b 0.0.0.0 -p 8000 myproject.asgi:application

Cross-Integration: Terminal Mesh

┌─────────────────────────────────────────────────────────────┐
│                    ACI Terminal Mesh                         │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  Emacs (-1)         MCP Server (0)        Daphne (+1)       │
│  #E7B367            #46F27F               #F0D127           │
│  ┌─────────┐        ┌─────────┐          ┌─────────┐       │
│  │ vterm   │◄──────►│ ghostty │◄────────►│ Django  │       │
│  │ eat     │        │   MCP   │          │Channels │       │
│  └─────────┘        └─────────┘          └─────────┘       │
│       │                  │                    │             │
│       └──────────────────┼────────────────────┘             │
│                          │                                   │
│                    libghostty-vt                             │
│                    (Zero Dependencies)                       │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Building libghostty

As Zig Module

// build.zig
const ghostty_vt = b.dependency("ghostty-vt", .{
    .target = target,
    .optimize = optimize,
});

exe.root_module.addImport("vt", ghostty_vt.module("ghostty-vt"));

As C Library

cd ghostty
zig build -Doptimize=ReleaseFast -Dtarget=native-native-musl lib

# Outputs: zig-out/lib/libghostty-vt.a
# Headers: zig-out/include/ghostty_vt.h

Python Bindings (cffi)

from cffi import FFI
ffi = FFI()

ffi.cdef("""
    typedef struct ghostty_terminal ghostty_terminal_t;

    ghostty_terminal_t* ghostty_terminal_new(uint16_t width, uint16_t height);
    void ghostty_terminal_free(ghostty_terminal_t* term);
    void ghostty_terminal_process(ghostty_terminal_t* term, const uint8_t* data, size_t len);
    const char* ghostty_terminal_screen_json(ghostty_terminal_t* term);
""")

lib = ffi.dlopen("libghostty-vt.so")

GF(3) Triads

libghostty-aci (0) ⊗ sheaf-cohomology (-1) ⊗ gay-mcp (+1) = 0 ✓
libghostty-aci (0) ⊗ captp (-1) ⊗ goblins (+1) = 0 ✓
emacs-vterm (-1) ⊗ libghostty-aci (0) ⊗ daphne-ws (+1) = 0 ✓

Commands

# Build libghostty-vt
just ghostty-build

# Test Emacs integration
emacs --eval '(vterm-ghostty-test)'

# Start MCP terminal server
just mcp-terminal-server

# Run Daphne with terminal support
daphne -b 0.0.0.0 -p 8000 project.asgi:application

Related Skills

SkillTritRelation
captp0Capability transport for terminal sessions
goblins+1Actor model for terminal instances
autopoiesis0Self-modifying terminal config
tree-sitter-1AST parsing of terminal output

Skill Name: libghostty-aci Type: Terminal Integration Trit: 0 (ERGODIC) Seed: 1069 Dependencies: libghostty-vt (Zig), channels (Python), tokio (Rust)


Autopoietic Marginalia

The interaction IS the skill improving itself.

Every use of this skill is an opportunity for worlding:

  • MEMORY (-1): Record what was learned
  • REMEMBERING (0): Connect patterns to other skills
  • WORLDING (+1): Evolve the skill based on use

Add Interaction Exemplars here as the skill is used.