用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/mudrii/hom --skill hom-terminal-integration命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Use this skill when building, reviewing, or refactoring Rust code that requires strong maintainability discipline: SRP, DRY, OCP, explicit dependency injection, TDD/ATDD workflow, architecture review, and clean project structure. Complements the project's Rust CLAUDE.md with process rigor.
Use when adding a new harness adapter or modifying an existing one in hom-adapters
Use when modifying TUI rendering, input routing, layout, command bar, or pane management
基于 SOC 职业分类
正在显示 SKILL.md
| name | hom-terminal-integration |
| description | Use when working on terminal emulation, the TerminalBackend trait, libghostty integration, or PTY management |
Invoke this skill when:
GhosttyBackend in crates/hom-terminal/src/ghostty.rsVt100Backend in crates/hom-terminal/src/fallback_vt100.rsTerminalBackend trait in crates/hom-core/src/traits.rscrates/hom-pty/src/manager.rscrates/hom-pty/src/async_reader.rsghostty-backend feature flagThis is the hardest part of HOM. Each pane runs a REAL terminal emulator:
Harness Process (e.g., claude)
↓ writes ANSI escape sequences to stdout
PTY slave → PTY master
↓ raw bytes
AsyncPtyReader (tokio channel)
↓ Vec<u8> chunks
terminal.process(bytes) ← TerminalBackend implementation
↓ updates internal screen state
terminal.screen_snapshot() → ScreenSnapshot { rows: Vec<Vec<Cell>> }
↓ cell-by-cell mapping
pane_render.rs → ratatui Buffer
↓
ratatui renders to real terminal
Every byte from the harness flows through this pipeline. A bug anywhere means garbled output.
Defined in crates/hom-core/src/traits.rs. Any terminal emulator must implement:
| Method | What it does | Failure mode |
|---|---|---|
new(cols, rows, scrollback) | Create terminal state | — |
process(bytes) | Feed PTY output into VT state machine | Garbled screen |
resize(cols, rows) | Update terminal dimensions | Content clipped or wrapped wrong |
screen_snapshot() | Return all cells with colors and attributes | Wrong rendering |
cursor() | Return cursor position and visibility | Cursor in wrong place |
title() | Return window title set by child process | Cosmetic only |
ghostty-backend, DEFAULT)Current status: Fully implemented in ghostty.rs. This is the default backend.
To build (default):
cargo build # ghostty-backend is the default feature
Requires Zig ≥0.15.x at build time. Install Zig: brew install zig or download from ziglang.org.
Critical risk: libghostty-rs is v0.1.1, pre-1.0. Pin commits. The API WILL change.
vt100-backend)The opt-in fallback in fallback_vt100.rs. Uses the vt100 crate (v0.16).
To build with vt100 fallback (no Zig required):
cargo build --no-default-features --features vt100-backend
Known limitations:
title() always returns None (vt100 0.16 doesn't expose it)screen_mut().set_size() (not parser.set_size())These limitations are acceptable for the current implementation. Most harness TUIs use basic text, colors, and cursor positioning.
crates/hom-terminal/src/color_map.rs maps TermColor → ratatui::style::Color.
When adding a new backend, you must map its color representation to TermColor. The 16 named colors (Black through BrightWhite) plus Indexed(0-255) and Rgb(r,g,b) must all be handled.
crates/hom-pty/src/manager.rs uses portable-pty to:
Critical timing issue: After spawning, the harness needs time to initialize before accepting input. Don't send prompts immediately — wait for detect_completion() == WaitingForInput.
#[test]
fn test_process_simple_text() {
let mut term = Vt100Backend::new(80, 24, 0).unwrap();
term.process(b"Hello, World!");
let snap = term.screen_snapshot();
let first_row: String = snap.rows[0].iter().map(|c| c.character).collect();
assert!(first_row.starts_with("Hello, World!"));
}
#[test]
fn test_process_color_escape() {
let mut term = Vt100Backend::new(80, 24, 0).unwrap();
term.process(b"\x1b[31mRed text\x1b[0m");
let snap = term.screen_snapshot();
assert!(matches!(snap.rows[0][0].fg, TermColor::Red));
}
#[test]
fn test_cursor_movement() {
let = Vt100Backend::(, , ).();
term.();
= term.();
(cursor.row, );
}
() {
= Vt100Backend::(, , ).();
term.(, );
= term.();
(snap.cols, );
(snap.num_rows, );
}
#[cfg(feature = "ghostty-backend")] must never reference vt100 and vice versa.AsyncPtyReader. Blocking the tokio runtime freezes the entire TUI.cargo check passes with default features (ghostty)cargo check --no-default-features --features vt100-backend passes (vt100 fallback path)cargo test -p hom-terminalcargo test -p hom-ptyTermColor variants