shux

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

shux — terminal multiplexer with a JSON-RPC API + pixel snapshotter

shux — 具备JSON-RPC API与像素快照功能的终端复用器

Install

安装

sh
npx skills add indrasvat/shux --global --yes
shux is a Rust terminal multiplexer (sessions / windows / panes, like tmux) that also exposes a length-prefixed JSON-RPC surface over UDS and TCP, atomic declarative templates, optimistic concurrency on every entity, a sealed event bus, and a built-in rasterizer that returns PNG bytes for any pane — no terminal emulator in the loop.
sh
npx skills add indrasvat/shux --global --yes
shux是一款基于Rust开发的终端复用器(支持会话/窗口/面板,类似tmux),它还通过UDS和TCP暴露了带长度前缀的JSON-RPC接口,提供原子化声明式模板、全实体乐观并发机制、封闭事件总线,以及内置光栅化器——无需终端模拟器即可返回任意面板的PNG字节数据。

When to reach for it

适用场景

Pick shux instead of the alternatives when any of these apply:
  • You need to drive a TUI from outside (agent, CI, script) without a human at the keyboard.
  • You want a PNG of what a terminal looks like right now, headless, no display server.
  • You're running scripted CLI/REPL interactions that need typed keystrokes and known wait points.
  • You're doing visual regression on a TUI you built (Bubbletea, Charm, ratatui, anything).
  • You want declarative workspace templates that apply atomically.
If you're a human at a keyboard and tmux works for you, keep using tmux. When a human does attach to shux, the normal interactions should still feel modern: click panes to focus, drag borders to resize, drag visible text to copy via OSC 52, and right-click a visible selection for the inline Copy / Clear menu. Reserve prefix copy mode for scrollback, search, and keyboard-only selection.
当以下任意一种情况成立时,选择shux替代其他工具:
  • 你需要从外部(Agent、CI、脚本)驱动TUI,无需人工操作键盘。
  • 你需要获取终端当前状态的PNG截图,无需显示服务器的无头环境。
  • 你需要运行脚本化CLI/REPL交互,需模拟按键输入并处理等待逻辑。
  • 你需要为自己开发的TUI(Bubbletea、Charm、ratatui等)做视觉回归测试。
  • 你需要原子化应用的声明式工作区模板。
如果你是人工操作键盘且tmux能满足需求,建议继续使用tmux。当用户连接到shux时,常规交互体验依然现代:点击面板切换焦点、拖动边框调整大小、拖动可见文本通过OSC 52复制、右键选中内容调出内嵌的复制/清除菜单。保留前缀复制模式用于回滚、搜索和纯键盘选择。

Where shux artifacts live:
.shux/

shux文件存储位置:
.shux/

Run
shux init
once per project. It creates a top-level
.shux/
dir:
.shux/
├── templates/       # spec.toml files you commit            (committed)
├── scripts/         # automation scripts you commit         (committed)
├── goldens/         # reference PNGs for visual regression  (committed)
├── out/             # snapshots, diffs, logs, anything ephemeral  (gitignored)
└── .gitignore       # ignores `out/`
When you write code that produces shux artifacts:
  • Put templates under
    .shux/templates/
    (apply with
    shux state apply .shux/templates/<name>.toml
    ).
  • Put driver scripts under
    .shux/scripts/
    .
  • Write snapshots, diffs, debug logs into
    .shux/out/
    (gitignored by default).
  • Commit golden images to
    .shux/goldens/
    so visual-regression diffs have a ground truth.
Never pollute
.claude/
,
~/
, or the project root with shux output.
每个项目只需运行一次
shux init
,它会在项目根目录创建
.shux/
文件夹:
.shux/
├── templates/       # 需提交的spec.toml文件            (已提交)
├── scripts/         # 需提交的自动化脚本         (已提交)
├── goldens/         # 视觉回归测试用的参考PNG  (已提交)
├── out/             # 快照、差异文件、日志等临时文件  (已加入git忽略)
└── .gitignore       # 忽略`out/`目录
当你编写生成shux产物的代码时:
  • 模板放在
    .shux/templates/
    目录下(通过
    shux state apply .shux/templates/<name>.toml
    应用)。
  • 驱动脚本放在
    .shux/scripts/
    目录下。
  • 快照、差异文件、调试日志写入
    .shux/out/
    目录(默认已加入git忽略)。
  • 基准图片提交到
    .shux/goldens/
    目录,为视觉回归测试提供对比基准。
请勿将shux输出文件混入
.claude/
、用户主目录或项目根目录。

80% quickstart (three RPCs)

80%快速入门(三个RPC调用)

bash
undefined
bash
undefined

1. Spawn a session running any command (or shell). Capture the

1. 生成运行任意命令(或Shell)的会话。从响应中获取pane_id,以便后续调用定位目标面板。

pane_id from the response so the next calls can target it. CLI

除非指定--cwd参数,否则CLI会话创建默认使用调用者的当前目录。

session creation starts in the caller's current directory unless

you pass --cwd.

RESP=$(shux --format json session create demo -d --title demo -- lazygit) PID=$(echo "$RESP" | jq -r .pane_id)
RESP=$(shux --format json session create demo -d --title demo -- lazygit) PID=$(echo "$RESP" | jq -r .pane_id)

2. Drive it.

2. 驱动会话。

shux pane set-size -s demo --cols 200 --rows 60 shux pane send-keys -s demo --text 'j' # text input shux pane send-keys -s demo --data 'Gw==' # base64 control (here: Esc)
shux pane set-size -s demo --cols 200 --rows 60 shux pane send-keys -s demo --text 'j' # 文本输入 shux pane send-keys -s demo --data 'Gw==' # Base64编码的控制字符(此处为Esc)

3. Get a PNG back.

3. 获取PNG截图。

shux --format json pane snapshot -s demo
| jq -r .png_base64 | base64 -d > frame.png
shux --format json pane snapshot -s demo
| jq -r .png_base64 | base64 -d > frame.png

Tear down when done.

完成后销毁会话。

shux session kill demo

Every CLI verb maps 1:1 to an RPC method (RPC dots become CLI spaces —
`session.create` ↔ `shux session create`). Drop to the raw form with
`shux rpc call <method> --params @file` whenever you'd rather write
the payload in JSON directly. `--params -` reads from stdin.

For declarative multi-pane workspaces, use a template:

```toml
shux session kill demo

每个CLI命令都与RPC方法一一对应(RPC中的点号对应CLI中的空格——`session.create` ↔ `shux session create`)。如果更倾向于直接编写JSON负载,可使用`shux rpc call <method> --params @file`形式调用原生RPC。`--params -`表示从标准输入读取参数。

对于声明式多面板工作区,可使用模板:

```toml

spec.toml

spec.toml

[session] name = "review" [[windows]] title = "vivecaka" [[windows.panes]] command = ["vivecaka", "--repo", "cli/cli"]

```bash
shux state apply spec.toml      # atomic — all or nothing
[session] name = "review" [[windows]] title = "vivecaka" [[windows.panes]] command = ["vivecaka", "--repo", "cli/cli"]

```bash
shux state apply spec.toml      # 原子化操作——要么全部生效,要么全部不生效

Tools shux replaces

shux可替代的工具

If you'd reach forFor this jobUse this shux primitive
tmux
·
screen
·
byobu
Multiplex sessions / windows / panes
shux state apply spec.toml
·
shux session attach
iTerm2 (Python SDK / AppleScript)Drive a terminal app from outside
shux pane send-keys
+
shux pane snapshot
expect
·
pexpect
·
sexpect
Scripted CLI / REPL interaction
pane send-keys
pane wait-for
pane capture
iTerm2
wait_for_text
/
wait_for_absent
Block until screen contains (or stops containing) a needle
shux pane wait-for
(text · regex ·
--absent
)
asciinema rec
·
script(1)
Record a terminal session
pane.output.watch
(sealed data-plane stream)
vhs
·
agg
·
terminalizer
Generate TUI demo GIFs / WebPs
shux window snapshot
loop →
ffmpeg
termshot
·
freezeframe
Still PNG of a terminal frame
shux pane snapshot
or
shux window snapshot
iTerm2 broadcast inputSend keystrokes to many panes at once
shux pane send-keys
fan-out (one RPC per pane)
ttyrec
·
termsh
Replay a recorded sessionRe-feed VT bytes through a fresh pane →
pane snapshot
GNU parallel
--tmux
mode
Run N tasks in N panes, watch in one placeTemplate with N panes + RPC orchestrator
Custom Bubbletea / ratatui test harnessVisual regression for your TUI
shux window snapshot
+ golden-image diff (SSIM or raw RGBA)
原本会选用的工具对应工作场景可使用的shux功能
tmux
·
screen
·
byobu
复用会话/窗口/面板
shux state apply spec.toml
·
shux session attach
iTerm2(Python SDK / AppleScript)从外部驱动终端应用
shux pane send-keys
+
shux pane snapshot
expect
·
pexpect
·
sexpect
脚本化CLI/REPL交互
pane send-keys
pane wait-for
pane capture
iTerm2
wait_for_text
/
wait_for_absent
阻塞直到屏幕出现(或消失)指定内容
shux pane wait-for
(支持文本、正则表达式、
--absent
参数)
asciinema rec
·
script(1)
录制终端会话
pane.output.watch
(封闭数据平面流)
vhs
·
agg
·
terminalizer
生成TUI演示GIF/WebP
shux window snapshot
循环调用 →
ffmpeg
termshot
·
freezeframe
终端界面静态PNG截图
shux pane snapshot
shux window snapshot
iTerm2广播输入同时向多个面板发送按键
shux pane send-keys
批量调用(每个面板一次RPC)
ttyrec
·
termsh
重放录制的会话将VT字节重新输入到新面板 →
pane snapshot
GNU parallel
--tmux
模式
在N个面板中运行N个任务,集中监控包含N个面板的模板 + RPC编排器
自定义Bubbletea/ratatui测试框架TUI视觉回归测试
shux window snapshot
+ 基准图片对比(SSIM或原始RGBA)

The common RPC surface

通用RPC接口

Every CLI verb maps 1:1 to an RPC method — RPC dots become CLI spaces (
session.create
shux session create
,
pane.send_keys
shux pane send-keys
). All RPCs accept JSON in, return JSON out, on stdin/stdout.
references/api.md
lists the full request/response shape per method.
CategoryMethods
Session
session.create
·
session.list
·
session.rename
·
session.kill
·
session.ensure
Window
window.create
·
window.list
·
window.focus
·
window.kill
·
window.ensure
Pane I/O
pane.send_keys
·
pane.set_size
·
pane.snapshot
·
pane.capture
·
pane.output.watch
Pane mgmt
pane.split
·
pane.focus
·
pane.zoom
·
pane.swap
·
pane.kill
·
pane.set_title
Window snap
window.snapshot
·
session.snapshot
(composed multi-pane PNG)
State
state.apply
(atomic batch) ·
events.history
·
system.version
Every entity carries a
version
field. Pass
expected_version
on mutating RPCs to get optimistic-concurrency rejection (error code
-32002
) on stale writes — useful when multiple agents collaborate.
每个CLI命令都与RPC方法一一对应——RPC中的点号对应CLI中的空格(
session.create
shux session create
pane.send_keys
shux pane send-keys
)。所有RPC均接收JSON输入并返回JSON输出,通过标准输入/输出交互。
references/api.md
列出了每个方法的完整请求/响应格式。
分类方法
会话
session.create
·
session.list
·
session.rename
·
session.kill
·
session.ensure
窗口
window.create
·
window.list
·
window.focus
·
window.kill
·
window.ensure
面板I/O
pane.send_keys
·
pane.set_size
·
pane.snapshot
·
pane.capture
·
pane.output.watch
面板管理
pane.split
·
pane.focus
·
pane.zoom
·
pane.swap
·
pane.kill
·
pane.set_title
窗口快照
window.snapshot
·
session.snapshot
(多面板合成PNG)
状态
state.apply
(原子化批量操作) ·
events.history
·
system.version
每个实体都包含
version
字段。在修改型RPC调用中传入
expected_version
参数,可在写入过时数据时触发乐观并发拒绝(错误码
-32002
)——适用于多Agent协作场景。

Common control bytes for
pane.send_keys --data

pane.send_keys --data
常用控制字节

The
text
field sends raw text. For control characters, use
data
(base64).
KeyBytesBase64
Enter
0x0d
DQ==
Escape
0x1b
Gw==
Tab
0x09
CQ==
Backspace
0x7f
fw==
Ctrl+C
0x03
Aw==
Ctrl+L
0x0c
DA==
Up arrow
\e[A
G1tB
Down arrow
\e[B
G1tC
text
字段用于发送原始文本。对于控制字符,需使用
data
参数(Base64编码)。
按键字节Base64编码
回车键
0x0d
DQ==
退出键
0x1b
Gw==
制表键
0x09
CQ==
退格键
0x7f
fw==
Ctrl+C
0x03
Aw==
Ctrl+L
0x0c
DA==
上箭头
\e[A
G1tB
下箭头
\e[B
G1tC

Decide which method to use

方法选择指南

Need to spawn something?           → session.create  (shux session create --title <label> -- <cmd>)
Need a multi-pane workspace?       → state.apply     (shux state apply spec.toml)
Need to type into a TUI?           → pane.send_keys  (shux pane send-keys --text|--data)
Need pixel feedback of one pane?   → pane.snapshot   (shux pane snapshot)
Need a snapshot of the whole
window (borders, titles, status)?  → window.snapshot (shux window snapshot)
Need a snapshot of the session's
active window?                     → session.snapshot (shux session snapshot)
Need plain text of the screen?     → pane.capture    (shux pane capture)
Need to block until text appears?  → pane.wait_for   (shux pane wait-for --text|--regex)
Need a stream of PTY output?       → pane.output.watch (event-bus, sealed)
Want raw RPC for a new method?     → shux rpc call <method> --params @file
需要生成会话?           → session.create (shux session create --title <标签> -- <命令>)
需要多面板工作区?       → state.apply    (shux state apply spec.toml)
需要向TUI输入内容?           → pane.send_keys (shux pane send-keys --text|--data)
需要单个面板的像素级反馈?   → pane.snapshot  (shux pane snapshot)
需要整个窗口(边框、标题、状态栏)的快照?  → window.snapshot(shux window snapshot)
需要会话活动窗口的快照?                     → session.snapshot(shux session snapshot)
需要屏幕纯文本内容?     → pane.capture   (shux pane capture)
需要等待指定文本出现?  → pane.wait_for  (shux pane wait-for --text|--regex)
需要PTY输出流?       → pane.output.watch(事件总线,封闭)
需要调用原生RPC方法?     → shux rpc call <方法> --params @file

Extend shux with a process plugin

使用进程插件扩展shux

shux has a process-plugin host. A plugin is any executable that speaks shux's line-delimited JSON-RPC dialect on stdin/stdout — bash, python, node, anything. It:
  • Subscribes to bus events listed in its manifest.
  • Calls any registered shux RPC method (
    window.rename
    ,
    pane.send_keys
    ,
    state.apply
    , …) to react.
  • Publishes its own events via
    event.publish
    . The daemon namespaces them under
    plugin.<plugin_id>.<type>
    so other plugins (or
    shux events watch --filter plugin.<id>.
    ) can subscribe to them cleanly — see references/plugins.md.
  • Persists its own state across hot reload via
    plugin.state.get/set/delete
    . The CLI pins it to the calling project's root at install time (walks up from cwd for
    .shux/
    , anchors there) — so a daemon shared across checkouts keeps each project's state isolated. Atomic writes, 256 KiB cap, per-plugin isolation. Path:
    <project-root>/.shux/plugins/<name>/state.json
    .
bash
shux plugin install ./my-plugin.sh   # spawn, handshake, register. Hot reload ON
                                      #   by default — saves respawn the plugin
                                      #   in <500ms. Use `--no-watch` to opt out.
shux plugin list                      # name · version · pid · subscribes · watching
shux plugin reload <name>             # manual hot-reload tick (kill + respawn)
shux plugin kill <name>               # graceful shutdown (2s) → SIGKILL

shux plugin grant <name> <method>     # opt the plugin in to a sensitive RPC.
                                      #   Default-deny model: every plugin RPC
                                      #   passes through a permission check
                                      #   before reaching the daemon router
                                      #   (v0.19+).
shux plugin grant <name> <method> --target <id>   # scoped to one entity
shux plugin grant <name> <filter> --subscribe     # widen manifest subscribes
shux plugin revoke <name> <method>    # mirror of grant
shux plugin grants <name>             # show the allow-set
shux plugin audit <name> --tail 50    # tail NDJSON audit log
Reference plugins:
  • examples/plugins/hello/plugin.sh
    — smallest working example (~50 lines): handshake + PTY output + state mutation.
  • examples/plugins/watcher/plugin.sh
    — subscribes to
    pane.exited
    , emits a namespaced
    plugin.watcher.command_exit
    via
    event.publish
    for downstream plugins.
  • examples/plugins/conductor/plugin.sh
    — VT-poll watchdog + settle-snapshot archive ⭐ + window-aggregation OS notifications for coding-agent panes (claude / codex / opencode / gemini). Identifies the agent on
    pane.created
    , polls
    pane.capture
    every 2 s, classifies state, updates the pane border title (
    agent · ○|●|✓|!
    ), auto-dismisses trust prompts via
    pane.send_keys
    . On every
    ready→idle
    transition, calls
    pane.snapshot
    and saves the resulting PNG to
    .shux/conductor/snapshots/
    with a rolling
    INDEX.tsv
    — a feature literally impossible in any tool that doesn't own its own rasterizer.
    Tracks per-window in-flight counts and fires ONE
    osascript
    /
    notify-send
    notification when a window's last in-flight agent goes idle.
Full protocol — handshake, event payload shape, RPC-out direction,
event.publish
, shutdown grace, UUID vs name rule, what's not in v0 — lives in references/plugins.md.
shux内置进程插件宿主环境。插件可以是任何能通过标准输入/输出与shux进行行分隔JSON-RPC通信的可执行文件——bash、python、node等均可。插件具备以下能力:
  • 订阅其清单中列出的总线事件。
  • 调用任何已注册的shux RPC方法(
    window.rename
    pane.send_keys
    state.apply
    等)做出响应。
  • 发布自定义事件,通过
    event.publish
    方法。守护进程会将事件命名为
    plugin.<plugin_id>.<type>
    ,以便其他插件(或
    shux events watch --filter plugin.<id>.
    )能清晰订阅——详情见references/plugins.md
  • 持久化自身状态,支持热重载,通过
    plugin.state.get/set/delete
    方法。安装插件时,CLI会将状态存储路径固定在调用项目的根目录(从当前目录向上查找
    .shux/
    目录作为锚点)——因此跨代码共享的守护进程会隔离每个项目的状态。支持原子写入,每个插件状态上限为256 KiB。存储路径:
    <项目根目录>/.shux/plugins/<名称>/state.json
bash
shux plugin install ./my-plugin.sh   # 启动插件、握手、注册。默认开启热重载——插件重启耗时<500ms。使用`--no-watch`关闭热重载。
shux plugin list                      # 显示名称·版本·进程ID·订阅事件·是否监控
shux plugin reload <名称>             # 手动触发热重载(杀死并重启插件)
shux plugin kill <名称>               # 优雅关闭(等待2秒)→ SIGKILL强制终止

shux plugin grant <名称> <方法>     # 授权插件调用敏感RPC方法。
                                      #   默认拒绝模型:每个插件RPC调用都会经过权限检查
                                      #   后才会到达守护进程路由(v0.19+版本)。
shux plugin grant <名称> <方法> --target <ID>   # 限制权限至指定实体
shux plugin grant <名称> <过滤器> --subscribe     # 扩展插件订阅事件范围
shux plugin revoke <名称> <方法>    # 撤销权限,与grant操作对应
shux plugin grants <名称>             # 显示当前允许调用的方法集合
shux plugin audit <名称> --tail 50    # 查看最新50条NDJSON审计日志
参考插件:
  • examples/plugins/hello/plugin.sh
    — 最小可用示例(约50行):握手 + PTY输出 + 状态变更。
  • examples/plugins/watcher/plugin.sh
    — 订阅
    pane.exited
    事件,通过
    event.publish
    发送命名空间为
    plugin.watcher.command_exit
    的事件供下游插件使用。
  • examples/plugins/conductor/plugin.sh
    — VT轮询监控 + 就绪-空闲状态快照归档 ⭐ + 窗口聚合系统通知,适用于编码Agent面板(claude / codex / opencode / gemini)。在
    pane.created
    事件中识别Agent,每2秒轮询
    pane.capture
    ,分类状态,更新面板边框标题(
    agent · ○|●|✓|!
    ),通过
    pane.send_keys
    自动处理信任提示。每次从就绪切换到空闲状态时,调用
    pane.snapshot
    并将生成的PNG保存到
    .shux/conductor/snapshots/
    目录,同时维护滚动更新的
    INDEX.tsv
    ——这一功能在不具备自有光栅化器的工具中完全无法实现。
    跟踪每个窗口的活跃Agent数量,当窗口最后一个活跃Agent变为空闲时,触发一次
    osascript
    /
    notify-send
    通知。
完整协议——握手流程、事件负载格式、RPC输出方向、
event.publish
方法、优雅关闭、UUID与名称规则、v0版本未包含的功能——详见references/plugins.md

Deep dives

深度指南

TopicWhere
Full RPC inventory + JSON request/response shapesreferences/api.md
Apply-template TOML shape, lowering rules, multi-window workspacesreferences/templates.md
Scenario-driver patterns (send/wait/snap loops, golden-image diff)references/scenarios.md
Process plugins — protocol, manifest, event/RPC shapes, gotchasreferences/plugins.md
主题文档位置
完整RPC清单 + JSON请求/响应格式references/api.md
模板TOML格式、转换规则、多窗口工作区references/templates.md
场景驱动模式(发送/等待/快照循环、基准图片对比)references/scenarios.md
进程插件——协议、清单、事件/RPC格式、注意事项references/plugins.md

Worked examples

实践示例

  • examples/headless-tui-test.md — drive a TUI in CI, snapshot at every step, diff against checked-in goldens.
  • examples/vision-llm-feedback.md — agent builds a Bubbletea app, snapshots its own UI, feeds PNG to a vision model, self-corrects.
  • examples/replace-tmux-workflow.md — common
    tmux new-session / send-keys / capture-pane
    patterns translated to shux.
  • examples/headless-tui-test.md — 在CI环境中驱动TUI,每一步都生成快照,与已提交的基准图片对比。
  • examples/vision-llm-feedback.md — Agent构建Bubbletea应用,自身UI生成快照,将PNG输入视觉模型,实现自我修正。
  • examples/replace-tmux-workflow.md — 常见
    tmux new-session / send-keys / capture-pane
    模式转换为shux操作。

Gotchas

注意事项

  • pane.set_size
    is synchronous (oneshot ack). The next
    pane.snapshot
    sees the new dims. No sleep needed between them.
  • pane.snapshot
    caps the output at 16M pixels (~4000×4000). Resize first if you'd exceed.
  • pane wait-for -s SESSION
    targets the session's active pane (often the last-spawned). In multi-pane templates pass
    --pane <UUID>
    (from
    pane list
    or
    state.apply
    's
    spawn_results
    ) — otherwise the wait will silently watch the wrong pane and time out.
  • pane.send_keys --text
    is JSON-quoted text. For raw control bytes (Esc/Enter/Tab/Ctrl+letter), use
    --data
    with base64.
  • shux state apply foo.toml
    atomically commits the graph but PTY spawn outcomes are reported per-pane in
    spawn_results
    . A spawn failure does not roll back the graph.
  • The first pane of the first template window is folded into the session's auto-created initial window — there is no phantom default-shell pane.
  • The bundled font (JetBrains Mono Regular, OFL-1.1) is monochrome. Color emoji and CJK glyphs render as
    .notdef
    tofu in the current rasterizer (P2 roadmap).
  • pane.set_size
    是同步操作(一次性确认)。后续的
    pane.snapshot
    会使用新的尺寸,无需在两者之间添加等待。
  • pane.snapshot
    输出上限为1600万像素(约4000×4000)。如果超出此范围,请先调整面板尺寸。
  • pane wait-for -s SESSION
    会定位到会话的活跃面板(通常是最后生成的面板)。在多面板模板中,需传入
    --pane <UUID>
    (来自
    pane list
    state.apply
    spawn_results
    )——否则等待操作会静默监控错误的面板并超时。
  • pane.send_keys --text
    接收JSON转义后的文本。对于原始控制字节(Esc/Enter/Tab/Ctrl+字母),需使用
    --data
    参数传入Base64编码内容。
  • shux state apply foo.toml
    会原子化提交状态图,但PTY生成结果会在
    spawn_results
    中按面板返回。生成失败不会回滚状态图。
  • 模板第一个窗口的第一个面板会合并到会话自动创建的初始窗口中——不存在默认Shell的虚拟面板。
  • 内置字体(JetBrains Mono Regular,OFL-1.1许可证)为单色字体。当前光栅化器中,彩色表情符号和CJK字符会显示为
    .notdef
    豆腐块(已列入P2 roadmap)。