Skip to content

Manage reusable email snippets from the CLI and TUI - #269

Merged
robzolkos merged 2 commits into
mainfrom
snippets-cli-tui
Aug 22, 2026
Merged

Manage reusable email snippets from the CLI and TUI#269
robzolkos merged 2 commits into
mainfrom
snippets-cli-tui

Conversation

@robzolkos

@robzolkos robzolkos commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Give people and coding agents a complete way to manage HEY’s reusable email snippets from the CLI and deliberately insert them while composing in the TUI. The picker mirrors HEY web: it never chooses a default, and the TUI inserts the selected snippet’s plain text at the current body cursor without replacing the draft.

Review readiness: ✅ Yes
Risk: 🟡 Medium — this adds a child picker to the shared new-message, reply, and forward form while preserving account-bound send behavior and draft state.
Decision: Confirm that Ctrl+T and plain-text insertion are the right terminal equivalents of HEY web’s rich-text picker.

✅ Change — snippets can be managed by scripts and explicitly inserted while composing

Before

CLI or TUI user
├── manage snippets
│   └── ❌ no command surface
└── compose or reply in the TUI
    └── ❌ leave the terminal to retrieve reusable text

After

CLI or TUI user
├── list/create/update/delete snippets
│   └── ✅ typed SDK operations and standard output formats  ← CHANGED
└── compose, reply, or forward in the TUI
    ├── press Ctrl+T
    ├── filter and explicitly choose a snippet
    └── ✅ insert at the body cursor without replacing the draft  ← CHANGED

The TUI keeps the picker inside the compose form, so opening, filtering, cancellation, failed loading, and repeated insertion retain the original draft and cursor state. Reply and forward reads use the same account-bound SDK client as their eventual send.

✅ Evidence — CLI lifecycle and TUI insertion pass against the real Haystack development server
  • ✅ Strict real-server smoke coverage creates, lists, updates, browser-verifies, and deletes a disposable snippet.
  • ✅ Unit coverage exercises every CLI format and mutation, terminal-safe rendering, picker filtering/navigation, insertion at the middle of a draft, cancellation, repeated insertion, empty/error states, stale responses, and reply-account binding.
  • Real-server TUI recording — observe Ctrl+T filtering, insertion between “Before” and “after,” then explicit insertion in a reply.
GOWORK=off make check
PASS

GOWORK=off make race-test
PASS — all internal packages

GOWORK=off make coverage
PASS — 82.2% repository coverage (70.8% floor)

cd tests/smoke
HEY_SMOKE_STRICT=1 GOWORK=off go test -run '^TestSnippet' -v -count=1
PASS — lifecycle and output/validation tests

GOWORK=off ~/.local/share/mise/installs/go/1.26.5/bin/govulncheck ./...
PASS — no called vulnerabilities

~/.local/share/mise/installs/go/1.26.2/bin/gitleaks detect --source . --verbose --redact
PASS — no leaks

The full strict smoke suite was also exercised. The new snippet tests passed; unrelated fixture/environment gates failed for attachment sending, cookie-backed auth token, absence of a seen Imbox posting, and dev-build version checks.

✅ Scope — snippet management and deliberate compose insertion only

Included:

  • hey snippets with styled, JSON, quiet, jq, Markdown, IDs, and count output.
  • hey snippet create, update, and delete using hey-sdk v0.12.0.
  • A searchable Ctrl+T picker for new-message, reply, and forward forms.
  • Exact cursor insertion, repeated use, cancellation, loading, empty, and error states.
  • README, curated help, command surface, unit tests, and real-server smoke coverage.

Deferred intentionally:

  • Clips, which remain tracked separately.
  • TUI snippet creation/editing and bulk-reply insertion.
  • Rich-text editing in the TUI; its composer remains plain text and inserts the API’s plain-text snippet representation. CLI JSON still returns HEY’s rich-text HTML.
➖ Delivery — no migration, configuration, dependency, or deployment ordering

The released SDK already supplies every snippet operation. There are no schema changes, feature flags, new runtime dependencies, backfills, or data migrations. Existing snippets appear immediately. Failures remain inline in the picker and leave the draft intact; rollback is a normal revert.

⚠️ Review decision — focus on picker ownership and the rich-text/plain-text boundary

Please confirm:

  1. Keeping the picker as child state of the compose form is preferable to introducing a global modal stack; this is what preserves the draft while the picker is open.
  2. Inserting content as plain text is the honest behavior for the existing terminal textarea, while CLI JSON preserves content_html for consumers that need HEY’s rich representation.

Compatibility: no snippet is selected automatically, existing compose shortcuts and sends remain unchanged, and existing snippets require no migration.

✅ Review path — command contract, picker lifecycle, then proof and public surface
  1. internal/cmd/snippet.go — CLI hierarchy, validation, output, and mutation contract.
  2. internal/tui/snippets.go and internal/tui/compose.go — child picker state, cursor insertion, loading, and account-bound reads.
  3. internal/cmd/snippet_test.go, internal/tui/snippets_test.go, and tests/smoke/snippets_test.go — behavioral and real-server proof.
  4. README.md, internal/cmd/help.go, and .surface — documentation and discoverability.

Origin and supporting links: Basecamp card · separate clips card · HEY SDK v0.12.0

Copilot AI balanced review requested due to automatic review settings August 22, 2026 06:51
@robzolkos
robzolkos requested a review from a team as a code owner August 22, 2026 06:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds reusable email snippet management to the CLI and insertion through a TUI compose picker.

Changes:

  • Adds snippet list/create/update/delete commands and output formats.
  • Adds Ctrl+T snippet insertion for compose, reply, and forward forms.
  • Adds documentation, command-surface updates, and extensive tests.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
.surface Records the new command surface.
README.md Documents snippet commands and TUI usage.
internal/cmd/help.go Adds snippets to curated help.
internal/cmd/help_test.go Updates help expectations.
internal/cmd/root.go Registers snippet commands.
internal/cmd/snippet.go Implements snippet CLI operations.
internal/cmd/snippet_test.go Tests CLI behavior and formats.
internal/tui/compose.go Integrates the picker into compose forms.
internal/tui/compose_test.go Extends the compose test server.
internal/tui/mail.go Handles snippet-loading responses.
internal/tui/snippets.go Implements picker state and rendering.
internal/tui/snippets_test.go Tests picker behavior and safety.
tests/smoke/snippets_test.go Covers the real-server lifecycle.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/tui/snippets.go Outdated
@robzolkos
robzolkos merged commit 5625bd0 into main Aug 22, 2026
23 checks passed
@robzolkos
robzolkos deleted the snippets-cli-tui branch August 22, 2026 07:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants