writing-user-outputs
CLI output formatting standards for worktrunk. Use when writing user-facing messages, error handling, progress output, hints, warnings, or working with the output system.
Install
mkdir -p .claude/skills/writing-user-outputs && curl -L -o skill.zip "https://mcp.directory/api/skills/download/7255" && unzip -o skill.zip -d .claude/skills/writing-user-outputs && rm skill.zipInstalls to .claude/skills/writing-user-outputs
About this skill
Output System Architecture
Shell Integration
Worktrunk uses file-based directive passing for shell integration:
- Shell wrapper creates a temp file via
mktemp - Shell wrapper sets
WORKTRUNK_DIRECTIVE_FILEenv var to the file path - wt writes shell commands (like
cd '/path') to that file - Shell wrapper sources the file after wt exits
When WORKTRUNK_DIRECTIVE_FILE is not set (direct binary call), commands execute
directly and shell integration hints are shown.
Output Functions
The output system handles shell integration automatically. Just call output functions — they do the right thing regardless of whether shell integration is active.
// NEVER DO THIS - don't check mode in command code
if is_shell_integration_active() {
// different behavior
}
// ALWAYS DO THIS - just call output functions
eprintln!("{}", success_message("Created worktree"));
output::change_directory(&path)?; // Writes to directive file if set, else no-op
Printing output:
Use eprintln! and println! from worktrunk::styling (re-exported from
anstream for automatic color support and TTY detection):
use worktrunk::styling::{eprintln, println, stderr};
// Status messages to stderr
eprintln!("{}", success_message("Created worktree"));
// Primary output to stdout (tables, JSON, pipeable)
println!("{}", table_output);
// Flush before interactive prompts
stderr().flush()?;
Shell integration functions (src/output/global.rs):
| Function | Purpose |
|---|---|
change_directory(path) | Shell cd after wt exits (writes to directive file if set) |
execute(command) | Shell command after wt exits |
terminate_output() | Reset ANSI state on stderr |
is_shell_integration_active() | Check if directive file set (rarely needed) |
pre_hook_display_path(path) | Compute display path for pre-hooks |
post_hook_display_path(path) | Compute display path for post-hooks |
Message formatting functions (worktrunk::styling):
| Function | Symbol | Color |
|---|---|---|
success_message() | ✓ | green |
progress_message() | ◎ | cyan |
info_message() | ○ | symbol dim, text plain |
warning_message() | ▲ | yellow |
hint_message() | ↳ | dim |
error_message() | ✗ | red |
prompt_message() | ❯ | cyan |
Section headings (worktrunk::styling):
use worktrunk::styling::format_heading;
// Plain heading
format_heading("BINARIES", None) // => "BINARIES" (cyan)
// Heading with suffix
format_heading("USER CONFIG", Some("@ ~/.config/wt.toml"))
// => "USER CONFIG @ ~/.config/wt.toml" (title cyan, suffix plain)
stdout vs stderr
Decision principle: If this command is piped, what should the receiving program get?
- stdout → Data for pipes, scripts,
eval(tables, JSON, shell code) - stderr → Status for the human watching (progress, success, errors, hints)
- directive file → Shell commands executed after wt exits (cd, exec)
Examples:
wt list→ table/JSON to stdout (for grep, jq, scripts)wt config shell init→ shell code to stdout (foreval)wt switch→ status messages only (nothing to pipe)
Security
WORKTRUNK_DIRECTIVE_FILE is automatically removed from spawned subprocesses
(via shell_exec::Cmd). This prevents hooks from writing to the directive
file.
Windows Compatibility (Git Bash / MSYS2)
On Windows with Git Bash, mktemp returns POSIX-style paths like /tmp/tmp.xxx.
The native Windows binary (wt.exe) needs a Windows path to write to the
directive file.
No explicit path conversion is needed. MSYS2 automatically converts POSIX
paths in environment variables when spawning native Windows binaries — shell
wrappers can use $directive_file directly. See:
https://www.msys2.org/docs/filesystem-paths/
CLI Output Formatting Standards
User Message Principles
Output messages should acknowledge user-supplied arguments (flags, options, values) by reflecting those choices in the message text.
// User runs: wt switch --create feature --base=main
// GOOD - acknowledges the base branch
"Created new worktree for feature from main @ /path/to/worktree"
// BAD - ignores the base argument
"Created new worktree for feature @ /path/to/worktree"
Avoid "you/your" pronouns: Messages should refer to things directly, not address the user. Imperatives like "Run", "Use", "Add" are fine — they're concise CLI idiom.
// BAD - "Use 'wt merge' to rebase your changes onto main"
// GOOD - "Use 'wt merge' to rebase onto main"
Avoid redundant parenthesized content: Parenthesized text should add new information, not restate what's already said.
// BAD - parentheses restate "no changes"
"No changes after squashing 3 commits (commits resulted in no net changes)"
// GOOD - clear and concise
"No changes after squashing 3 commits"
// GOOD - parentheses add supplementary info
"Committing with default message... (3 files, +45, -12)"
Two types of parenthesized content with different styling:
-
Stats parentheses → Gray (
[90mbright-black): Supplementary numerical info that could be omitted without losing meaning.✓ Merged to main (1 commit, 1 file, +1) ◎ Squashing 2 commits into a single commit (2 files, +2)... -
Reason parentheses → Message color: Explains WHY an action is happening; integral to understanding.
◎ Removing feature worktree & branch in background (same commit as main, _)
Stats are truly optional context. Reasons answer "why is this safe/happening?" and belong with the main message. Symbols within reason parentheses still render in their native styling (see "Symbol styling" below).
Show path when hooks run in a different directory: When hooks run in a worktree other than the user's current (or eventual) location, show the path. Use the appropriate helper function:
-
Pre-hooks and manual
wt hook— User is at cwd, no cd happens. Useoutput::pre_hook_display_path(hooks_run_at). Examples: pre-commit, pre-merge, pre-remove, manualwt hook post-merge. -
Post-hooks — User will cd to destination if shell integration is active. Use
output::post_hook_display_path(destination). Examples: pre-start, post-switch, post-start, post-merge (after removal).
// Pre-hooks: user is at cwd, no cd happens
run_hook_with_filter(..., crate::output::pre_hook_display_path(ctx.worktree_path))?;
// Post-hooks: user will cd to destination if shell integration active
ctx.spawn_post_start_commands(crate::output::post_hook_display_path(&destination))?;
Avoid pronouns with cross-message referents: Hints appear as separate messages from errors. Don't use pronouns like "it" that refer to something mentioned in the error message.
// BAD - "it" refers to branch name in error message
// Error: "Branch 'feature' not found"
// Hint: "Use --create to create it"
// GOOD - self-contained hint
// Error: "Branch 'feature' not found"
// Hint: "Use --create to create a new branch"
Heading Case
Use sentence case for help text headings: "Configuration files", "JSON output", "LLM commit messages".
Message Consistency Patterns
Use consistent punctuation and structure for related messages.
Ampersand for combined actions: Use & when a single operation does
multiple things:
"Removing feature worktree & branch in background"
"Commands approved & saved to config"
Semicolon for joining clauses: Use semicolons to connect related information:
"Removing feature worktree in background; retaining branch (--no-delete-branch)"
"Branch unmerged; to delete, run <underline>wt remove -D</>" // hint uses underline
"{tool} not authenticated; run <bold>{tool} auth login</>" // warning uses bold
Explicit flag acknowledgment: Show flags in parentheses when they change behavior:
// GOOD - shows the flag explicitly
"Removing feature worktree in background; retaining branch (--no-delete-branch)"
// BAD - doesn't acknowledge user's explicit choice
"Removing feature worktree in background; retaining branch"
Flag locality: Place flag indicators adjacent to the concept they modify. Flags should appear immediately after the noun/action they affect, not at the end of the message:
// GOOD - (--force) is adjacent to "worktree" which it modifies
"Removing feature worktree (--force) & branch in background (same commit as main, _)"
// BAD - (--force) at end, disconnected from the worktree removal it enables
"Removing feature worktree & branch in background (same commit as main, _) (--force)"
This principle ensures readers can immediately understand what each annotation modifies.
Parallel structure: Related messages should follow the same pattern:
// GOOD - parallel structure with integration reason explaining branch deletion
// Target branch is bold; symbol uses its standard styling (dim for _ and ⊂)
"Removing feature worktree & branch in background (same commit as <bold>main</>, <dim>_</>)" // Integrated
"Removing feature worktree in background; retaining unmerged branch" // Unmerged
"Removing feature worktree in background; retaining branch (--no-delete-branch)" // User flag
Symbol styling: Symbols are atomic with their color — the styling is part of the symbol's identity, not a presentation choice. Each symbol has a defined appearance that must be preserved in all contexts:
_and⊂— dim (integration/safe-to-delete indicators)+Nand-N— green/red (diff indicators)
When a symbol appears in a colored message (cyan progress, green success), close
the message color before the symbol so it renders in its native styling. This
requires breaking out of the message color and reopening it after the symbol.
See FlagNote in src/output/handlers.rs for an example — it handles flag
acknowledgment notes (like integra
Content truncated.
More by max-sixty
View all skills by max-sixty →You might also like
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
drawio-diagrams-enhanced
jgtolentino
Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.
ui-ux-pro-max
nextlevelbuilder
"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."
godot
bfollington
This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.
nano-banana-pro
garg-aayush
Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
Related MCP Servers
Browse all serversUnlock AI-ready web data with Firecrawl: scrape any website, handle dynamic content, and automate web scraping for resea
Optimize your codebase for AI with Repomix—transform, compress, and secure repos for easier analysis with modern AI tool
Structured spec-driven development workflow for AI-assisted software development. Creates detailed specifications before
Automate Excel file tasks without Microsoft Excel using openpyxl and xlsxwriter for formatting, formulas, charts, and ad
Edit PDF and DOC files online with Office Word. Access advanced text formatting, table editing, and image scaling in you
Create and edit PowerPoint presentations in Python with Office PowerPoint. Use python pptx or pptx python tools to add s
Stay ahead of the MCP ecosystem
Get weekly updates on new skills and servers.