Skip to content
55 changes: 55 additions & 0 deletions .agents/skills/simplify/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
name: simplify
description: Review changed code for reuse, quality, and efficiency, then fix any issues found.
allowed-tools: Read, Grep, Glob, Bash, Edit
---

# Simplify: Code Review and Cleanup

Review all changed files for reuse, quality, and efficiency. Fix any issues found.

## Phase 1: Identify Changes

Run `git diff` (or `git diff HEAD` if there are staged changes) to see what changed. If there are no git changes, review the most recently modified files that the user mentioned or that you edited earlier in this conversation.

## Phase 2: Launch Three Review Agents in Parallel

Use the Agent tool to launch all three agents concurrently in a single message. Pass each agent the full diff so it has the complete context.

### Agent 1: Code Reuse Review

For each change:

1. **Search for existing utilities and helpers** that could replace newly written code. Look for similar patterns elsewhere in the codebase — common locations are utility directories, shared modules, and files adjacent to the changed ones.
2. **Flag any new function that duplicates existing functionality.** Suggest the existing function to use instead.
3. **Flag any inline logic that could use an existing utility** — hand-rolled string manipulation, manual path handling, custom environment checks, ad-hoc type guards, and similar patterns are common candidates.

### Agent 2: Code Quality Review

Review the same changes for hacky patterns:

1. **Redundant state**: state that duplicates existing state, cached values that could be derived
2. **Parameter sprawl**: adding new parameters to a function instead of generalizing or restructuring existing ones
3. **Copy-paste with slight variation**: near-duplicate code blocks that should be unified with a shared abstraction
4. **Leaky abstractions**: exposing internal details that should be encapsulated, or breaking existing abstraction boundaries
5. **Stringly-typed code**: using raw strings where constants, enums, or typed structures already exist in the codebase
6. **Unnecessary nesting**: wrapper containers or indirection that add no value
7. **Unnecessary comments**: comments explaining WHAT the code does (well-named identifiers already do that), narrating the change, or referencing the task/caller — delete; keep only non-obvious WHY (hidden constraints, subtle invariants, workarounds)

### Agent 3: Efficiency Review

Review the same changes for efficiency:

1. **Unnecessary work**: redundant computations, repeated file reads, duplicate network/API calls, N+1 patterns
2. **Missed concurrency**: independent operations run sequentially when they could run in parallel
3. **Hot-path bloat**: new blocking work added to startup or per-request hot paths
4. **Recurring no-op updates**: state updates inside polling loops or event handlers that fire unconditionally — add a change-detection guard so downstream consumers aren't notified when nothing changed
5. **Unnecessary existence checks**: pre-checking file/resource existence before operating (TOCTOU anti-pattern) — operate directly and handle the error
6. **Memory**: unbounded data structures, missing cleanup, event listener leaks
7. **Overly broad operations**: reading entire files when only a portion is needed, loading all items when filtering for one

## Phase 3: Fix Issues

Wait for all three agents to complete. Aggregate their findings and fix each issue directly. If a finding is a false positive or not worth addressing, note it and move on — do not argue with the finding, just skip it.

When done, briefly summarize what was fixed (or confirm the code was already clean).
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ htmlcov/
# MCP
**/.mcp.json

# App data (user-specific)
**/.wingman/
# App data (user-specific). Repo-root .wingman/ holds the skills mirror,
# which IS tracked; user config lives in ~/.wingman/ and never enters the repo.
**/.agent/

# OS
Expand Down
122 changes: 122 additions & 0 deletions .wingman/skills/better-interface/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
name: better-interface
description: Design engineering principles for making TUI interfaces feel polished. Use when building Textual widgets, reviewing TUI code, implementing transitions, focus states, alignment, spacing, or any visual detail work. Triggers on TUI polish, design details, "make it feel better", "feels off", layout alignment, color consistency, responsive sizing.
---

# Details that make TUI interfaces feel better

Great TUIs rarely come from a single thing. It's a collection of small details that compound into a professional experience. Apply these principles when building or reviewing Textual/terminal UI code.

## Quick Reference

| Category | When to Use |
| --- | --- |
| [Layout](layout.md) | Alignment, spacing, responsive sizing, content regions |
| [Color](color.md) | Palette consistency, contrast, semantic color usage |
| [Interaction](interaction.md) | Focus management, key hints, modal flow, feedback |
| [Typography](typography.md) | Text truncation, wrapping, Unicode, monospace alignment |

## Core Principles

### 1. Consistent Spacing

Use a spacing scale (1, 2, 4 cells). Mismatched padding between related
elements is the most common thing that makes TUIs feel off. Textual's
`padding` and `margin` CSS properties use cell units.

### 2. Optical Alignment Over Grid Alignment

When geometric centering looks wrong in a terminal, adjust optically.
Asymmetric Unicode characters (arrows, bullets) and mixed-width content
need manual nudging. A centered title above left-aligned content often
needs 1 cell of left padding removed.

### 3. Color Hierarchy

Use 3-4 color tiers consistently:
- **Primary**: key actions, active focus (bright, saturated)
- **Secondary**: labels, metadata (dimmed)
- **Muted**: borders, separators (very dim)
- **Danger/Success**: semantic states only (red/green)

Never use bright colors for passive elements. Reserve saturation for
things the user needs to notice.

### 4. Focus is Sacred

The focused widget must be visually distinct at a glance. Use border
color changes, not just cursor position. A user glancing at the screen
should instantly know where input will go.

### 5. Responsive Layout

TUI must work at 80x24 minimum. Use `fr` units and `max-width`/
`min-width` in Textual CSS to adapt. Content that overflows should
truncate with ellipsis, never wrap into garbage.

### 6. Feedback on Every Action

Every keypress that does something should produce visible feedback
within one frame. If an operation takes time, show a spinner or
status message immediately — don't let the user wonder if their
input was received.

### 7. Subtle Transitions

Textual supports CSS transitions. Use short durations (150-300ms)
for background color and opacity changes on hover/focus. Never
animate layout properties (width, height) — terminal reflow is
not smooth.

### 8. Border Consistency

Pick one border style and stick with it. `tall` for primary
containers, `round` for cards/modals, `heavy` for emphasis. Mixing
`ascii`, `tall`, `round`, and `heavy` in one screen looks
incoherent.

### 9. Key Hints

Always show available keys in a footer or status bar. Format as
`key action` pairs separated by thin spaces. Dim the keys relative
to the actions. Update hints contextually as focus moves.

### 10. Content Density

Terminal space is precious. Default to dense layouts. Use blank
lines only to separate logical groups, never for decoration.
Single-line headers over multi-line. Abbreviate labels when
the full form is obvious from context.

## Common Mistakes

| Mistake | Fix |
| --- | --- |
| Inconsistent padding between similar widgets | Use a spacing constant |
| Bright colors on passive/decorative elements | Reserve bright for actions and focus |
| No visible focus indicator | Add border color or background change on focus |
| Content overflows and wraps badly | Set `overflow: hidden` with `text-overflow: ellipsis` |
| No key hints visible | Add contextual footer with available actions |
| Large empty regions at default size | Use `fr` units to distribute space |
| Mixed border styles in one view | Standardize on one style per element tier |
| No feedback on async operations | Show spinner/status immediately on action |

## Review Checklist

- [ ] Spacing is consistent between related elements
- [ ] Focused widget is visually distinct (border or background)
- [ ] Color usage follows the 3-4 tier hierarchy
- [ ] Layout works at 80x24 minimum terminal size
- [ ] Long text truncates with ellipsis, never wraps into garbage
- [ ] Key hints are visible and contextually updated
- [ ] Every user action produces visible feedback
- [ ] Border styles are consistent within each tier
- [ ] No bright colors on passive elements
- [ ] Transitions are short (150-300ms) and only on color/opacity

## Reference Files

- [layout.md](layout.md) — Alignment, spacing, responsive sizing
- [color.md](color.md) — Palette consistency, contrast, semantic usage
- [interaction.md](interaction.md) — Focus management, key hints, modals
- [typography.md](typography.md) — Truncation, wrapping, Unicode alignment
67 changes: 67 additions & 0 deletions .wingman/skills/better-interface/color.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Color

Palette consistency, contrast, and semantic color usage in terminal UIs.

## Color Hierarchy

Use 3-4 tiers. Every color in the palette belongs to exactly one tier.

| Tier | Purpose | Example (Tokyo Night) |
| --- | --- | --- |
| Primary | Key actions, active focus, links | `#7aa2f7` (blue) |
| Secondary | Labels, metadata, inactive tabs | `#565f89` (dim) |
| Muted | Borders, separators, background accents | `#3b4261` (very dim) |
| Semantic | Success, error, warning — state only | `#9ece6a`, `#f7768e`, `#e0af68` |

### Rules

- Never use semantic colors for decoration. Red means error. Green means success.
- Body text uses the default foreground — don't override it unless it's a label.
- Background colors should have enough contrast with text (4.5:1 minimum for
accessibility, though terminal users typically tolerate lower).

## Consistency

Pick colors from one palette. Mixing hex values from different themes
creates visual noise.

```python
# Good — centralized palette
class Colors:
PRIMARY = "#7aa2f7"
DIM = "#565f89"
BORDER = "#3b4261"
ERROR = "#f7768e"
SUCCESS = "#9ece6a"

# Bad — ad-hoc hex values scattered across widgets
label.styles.color = "#6699ff" # close to primary but not quite
border.styles.color = "#444444" # doesn't match the palette
```

## Dark-on-Dark Contrast

Terminal UIs are almost always dark mode. Common mistakes:

- Borders that are invisible against the background (too close in value)
- Dim text that disappears on some terminal themes
- Bright white text that causes eye strain

Test with at least two terminal themes (one dark, one light-on-dark)
to catch contrast issues.

## Focus Color

The focused widget gets the primary color on its border or background.
Everything else stays muted. This creates an immediate visual hierarchy
without any animation.

```tcss
Widget:focus {
border: tall $primary;
}

Widget {
border: tall $muted;
}
```
108 changes: 108 additions & 0 deletions .wingman/skills/better-interface/interaction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Interaction

Focus management, key hints, modal flow, and feedback in terminal UIs.

## Focus Management

Focus is the primary navigation mechanism in a TUI. It must be obvious,
predictable, and never lost.

### Rules

- Exactly one widget has focus at any time
- Focus moves in a logical order (top-to-bottom, left-to-right)
- After closing a modal, focus returns to the widget that opened it
- After deleting an item, focus moves to the next item (not the previous)
- Tab cycles through focusable widgets; Shift+Tab goes backwards
- Never trap focus in a non-modal context

### Visual Indicator

The focused widget must be immediately identifiable:

```tcss
/* Good — clear focus state */
Input:focus {
border: tall $accent;
background: $surface-darken-1;
}

/* Bad — focus is only indicated by cursor position */
Input:focus {
/* no visual change */
}
```

## Key Hints

Show available actions in a footer bar. Update contextually as the
user navigates.

### Format

```
key1 action1 key2 action2 key3 action3
```

- Keys are dimmed, actions are normal weight
- Separate pairs with 2+ spaces
- Show only contextually relevant keys (not every global binding)
- Put destructive actions (delete, quit without save) last

### Example

```python
# Good — contextual hints
def get_hints(self) -> str:
if self.mode == "list":
return "↑↓ navigate Enter select d delete q quit"
elif self.mode == "edit":
return "Ctrl+S save Esc cancel"
```

## Modal Flow

Modals must:

1. Capture all input (no key leaking to widgets behind)
2. Show a clear title and available actions
3. Be dismissible with Esc (cancel) and Enter (confirm)
4. Return focus to the opener on close
5. Dim or overlay the background to show modality

### Anti-patterns

- Modal that doesn't capture Tab (focus escapes to background)
- Modal with no Esc binding (user feels trapped)
- Stacked modals (modal opens another modal) — flatten the flow instead

## Feedback

### Immediate

Every action needs visible confirmation within one frame:

| Action | Feedback |
| --- | --- |
| Key press | Widget state changes visually |
| Submit form | Status message or transition |
| Delete item | Item disappears, focus moves |
| Error | Error message in status bar or inline |

### Async Operations

For anything that takes >100ms:

1. Show a spinner or "Loading..." immediately
2. Update with result when done
3. Show error inline if it fails — don't silently revert

```python
# Good — immediate feedback
self.status.update("Saving...")
await save()
self.status.update("Saved")

# Bad — no feedback during save
await save()
```
Loading
Loading