defenseclaw-tui
Improve the DefenseClaw Textual TUI (cli/defenseclaw/tui) consistently. Use it for any TUI work - adding or changing panels, picker and consequence modals, Setup wizards and the config editor, the hint bar and help overlay, command-palette rows, TUI tests, and TUI UX reviews or render checks. It holds the golden rules, the file map, recipes, the 80x24 layout budget, the test budget, and scripts that render the screen headlessly, run a fake-data demo, audit CLI coverage and list a panel's touchpoints. Don't use it for live certification on the Windows/macOS/Linux test hosts (use defenseclaw-live-testing) or for EC2 dev-host operations (use defenseclaw-dev-host).
- License 许可
- Apache-2.0
- 最近更新
- 2026-11-14
- Stars
- ★ 911
- Forks
- 167
01 前言 Front Matter
- name
- defenseclaw-tui
- description
- Improve the DefenseClaw Textual TUI (cli/defenseclaw/tui) consistently. Use it for any TUI work - adding or changing panels, picker and consequence modals, Setup wizards and the config editor, the hint bar and help overlay, command-palette rows, TUI tests, and TUI UX reviews or render checks. It holds the golden rules, the file map, recipes, the 80x24 layout budget, the test budget, and scripts that render the screen headlessly, run a fake-data demo, audit CLI coverage and list a panel's touchpoints. Don't use it for live certification on the Windows/macOS/Linux test hosts (use defenseclaw-live-testing) or for EC2 dev-host operations (use defenseclaw-dev-host).
02 资源文件 10
- 参考文档references/architecture.md9.0 KB
- 参考文档references/gotchas.md7.2 KB
- 参考文档references/recipes.md8.2 KB
- 参考文档references/testing.md4.4 KB
- 参考文档references/ux-rules.md4.5 KB
- 参考文档references/verification.md5.2 KB
- 脚本scripts/demo.py4.3 KB
- 脚本scripts/gap_audit.py5.8 KB
- 脚本scripts/render.py6.9 KB
- 脚本scripts/touchpoints.py6.0 KB
03 SKILL.md 正文
DefenseClaw TUI
The TUI is a Python Textual 8 app in cli/defenseclaw/tui/. app.py holds
DefenseClawTUI (with SandboxPanelMixin), and every panel renders into one
shared surface: #body, DataTable#panel-table, #detail-panel, plus one
button bar per panel. Mutations never happen in the TUI. It builds CLI intents,
previews them, and runs the real defenseclaw CLI as a subprocess. Source and
tests are authoritative. If this skill disagrees with them, trust the code and
fix the skill.
Golden rules
- Keep models pure. Panel state and logic live in
services/<x>_state.py(no I/O, no Textual). The app or a mixin does the I/O._body_textruns on a 2 s timer, so it must be cheap and must not read disk, spawn processes or make network calls. - Mutate only through CLI intents. Flow:
model.handle_key→ action/intent →_confirm_and_run_intent→CommandPreviewScreen→CommandExecutor→_handle_successful_commandrefresh. Destructive intents setrisk="destructive"and go throughConsequenceModalScreen(danger=True). A flow with its own consequence modal that shows the exact command runs it after that confirm; never stack a third prompt. The one sanctioned direct write is the Setup config editor (apply_config_field+config.save()afterConfigDiffScreen). - Send secrets over stdin, never argv. Set
intent.secret_stdinand use--value-stdin(for examplekeys set NAME --value-stdin). Secrets never appear in the preview, the Activity log or argv.click.prompt(hide_input)and getpass ignore piped stdin. - Run follow-ups only after success. A follow-up intent runs after the previous command finishes, and only if it exited 0.
- Route all text entry through
FieldEditorScreen(screens/field_editor.py). Never type into fields through panel keys._panel_keylowercases most capital letters. Test it the way a terminal sends it: a burst of keys and a paste must land whole (references/gotchas.md). - Only model config-editor fields the Python
Configcan persist.Config.save()silently drops unmodeled keys, so show those read-only with a hint. - Advertise keys only through
HintEngineor the per-view keymap (panels/setup_keys.pyfor Setup). Every advertised key must be handled, and every handled key must appear in?help. No "Keys:" lines in the body. - Fit at 80x24. Primary content (the first row, field or wizard) stays above the fold, with at most 2-3 body lines above the table. Button bars hide what doesn't apply to the current view instead of disabling it.
- Rich-escape every data string (
rich.markup.escape), send bodies through_safe_body_renderable, write hotkey labels as\\[k], and use no@clicklinks in#body. - Check Windows too. The executor uses a PTY on POSIX but pipes and a Job Object on Windows. Stdin, cancel and terminal launches behave differently there, so check that path (or say you didn't).
- Stay within the test budget. Default to pure model tests. Each new
screen gets at most 2 Pilot tests, and each new mutating flow gets 1-2
journey tests, all at 80x24. See
references/testing.mdfor banned patterns. - Check branch overlap before starting.
feat/openshell-0.1andmainboth moveapp.py/panels/setup.py. Rungit log --oneline main...HEAD -- cli/defenseclaw/tui | headand fold in what's already there instead of re-doing it.
Copy style: use plain words and sentence case, start with a verb, avoid internal
jargon, and keep refusals to one line that says what to do next
(references/ux-rules.md).
Workflow
- Map the change.
touchpoints.py <panel>shows which if-chains inapp.py/hint_bar.pyneed the panel.gap_audit.py --prefix <cmd>shows whether a CLI command is in the palette, used by the TUI, or has--json. - Pick a recipe in
references/recipes.md: panel, picker, mutating action, secret action, wizard/config field, or palette row. - Build the model first and write unit tests for keys → actions, rows and empty states.
- Wire it up: the app/mixin I/O, intents, controls, hints and help.
- Render at 80x24 and 120x40 with
render.py, and add--expectfor the thing that must be visible. - Check it interactively in tmux with
demo.py(fake executor), or with the real CLI in an isolatedmktemphome (references/verification.md). Never use the real~/.defenseclaw. - Run the gates: the TUI suite, ruff, and the touched CLI tests.
- Commit as
fix(tui): <plain-English behaviour>(orfeat(tui): …,test(tui): …). Add a short body saying why and the Co-Authored-By trailer.
Cheat-sheet (repository root)
S=.claude/skills/defenseclaw-tui/scripts
.venv/bin/python $S/render.py --list-panels
.venv/bin/python $S/render.py --panel setup --size 80x24 # screen as text
.venv/bin/python $S/render.py --keys 0 c --expect "Config" # exit 1 if missing
.venv/bin/python $S/render.py --keys : "text:policy list" enter # palette + preview
.venv/bin/python $S/render.py --panel alerts --svg /tmp/alerts.svg # SVG per size
.venv/bin/python $S/render.py --first-run
.venv/bin/python $S/demo.py --panel setup # interactive, fake exec
.venv/bin/python $S/gap_audit.py --missing-only # CLI the TUI can't reach
.venv/bin/python $S/touchpoints.py sandboxes # panel wiring checklist
.venv/bin/python -m pytest cli/tests/tui -q -p no:cacheprovider -n 4
.venv/bin/ruff check cli/defenseclaw/ <new test files>
tmux new-session -d -s dc-tui -x 80 -y 24 ".venv/bin/python $S/demo.py"
tmux send-keys -t dc-tui 0; tmux capture-pane -t dc-tui -p; tmux kill-session -t dc-tui
References
references/architecture.md: file map, render pipeline,on_keyrouting order, the intent pipeline, workers, state services, and theme tokens.references/recipes.md: add a panel (the Sandboxes mixin recipe), a picker, a mutating or destructive action, a secret action, a wizard or config field, or a palette row.references/ux-rules.md: 80x24 budget, hints per view, control bars, copy style, reserved keys, and empty states.references/testing.md: test policy and budget, smoke/journey tests with a fake executor, and banned patterns.references/verification.md: render.py, demo.py in tmux, isolated-home runs, and host passes.references/gotchas.md: verified pitfalls. Read this before touching Setup, secrets, policies or keys.
Scripts
All scripts run from the repository root with .venv/bin/python and are hermetic
(fake-data app from cli/tests/tui/fixtures.py, no agent discovery, no sandbox
doctor, and a temp DEFENSECLAW_HOME).
scripts/render.py: headless screen-text dump. Options:--panel,--keys,--size(repeatable),--first-run,--setup-config default|empty,--expect TEXT,--svg PATH,--list-panels.scripts/demo.py: runs the same app interactively. HOME, DEFENSECLAW_HOME, CLAUDE_CONFIG_DIR and CODEX_HOME point into a scratch dir. Confirmed commands only echo their argv unless you pass--real-exec. The scratch home is deleted on exit unless you pass--keep-home. Options:--panel,--first-run,--setup-config,--real-exec,--keep-home.scripts/gap_audit.py: Click tree against palette rows, TUI argv literals and--json. Options:--missing-only,--groups,--prefix.scripts/touchpoints.py PANEL [--stem S]: which per-panel if-chains mention the panel.
04 同仓库更多 Skills
parity-fixture
Fixture for the rule-pack parity test of install admission and skill scan.
malicious-skill
暂无简介
clean-skill
暂无简介
codeguard
Security-aware code generation — teaches the agent CodeGuard rules to write secure code by default
perf-hello
Prints a friendly greeting when the user asks to say hello.
defenseclaw-develop
暂无简介