Documentation
¶
Overview ¶
Package cli holds CLI-only helpers — TTY prompts, output formatting, anything that only makes sense in the context of running kvlt on a terminal. Never imported by pkg/kvlt: the public library should not pull in `golang.org/x/term` for its callers.
Index ¶
- Variables
- func Accent(w io.Writer, s string) string
- func Banner(w io.Writer) string
- func ConfirmDestructive(question string) (bool, error)
- func Err(w io.Writer, s string) string
- func Failure(w io.Writer, msg string) string
- func Field(w io.Writer, width int, label, value string)
- func Info(w io.Writer, s string) string
- func Mute(w io.Writer, s string) string
- func OK(w io.Writer, s string) string
- func PassphrasePromptTTY(keyPath string) ([]byte, error)
- func PromptSecretValue(label string) (string, error)
- func SetTheme(name string) bool
- func Success(w io.Writer, msg string) string
- func ThemeNames() []string
- type Theme
Constants ¶
This section is empty.
Variables ¶
var ( // ThemeOpencode mirrors opencode's installer palette — friendly // orange + soft green. The default for visual continuity between // `curl … | bash` and the installed binary. ThemeOpencode = Theme{ Name: "opencode", Mute: "\033[0;2m", Accent: "\033[38;5;214m", OK: "\033[38;5;114m", Err: "\033[0;31m", Info: "\033[38;5;110m", BannerTop: "\033[38;5;240m", BannerBot: "\033[38;5;214m", } // ThemeMetal leans into the kvlt/cult metal aesthetic — bone // muted, blood-red accent, cold-steel info. Errors stay brighter // red so they're distinct from the dull-red accent. ThemeMetal = Theme{ Name: "metal", Mute: "\033[38;5;253;2m", Accent: "\033[38;5;124m", OK: "\033[38;5;108m", Err: "\033[38;5;203m", Info: "\033[38;5;67m", BannerTop: "\033[38;5;253;2m", BannerBot: "\033[38;5;124m", } // ThemeCrimson is metal with the saturation cranked — brighter // red across the board, slightly less austere than metal but // still firmly in the "danger / dark" register. ThemeCrimson = Theme{ Name: "crimson", Mute: "\033[38;5;245m", Accent: "\033[38;5;160m", OK: "\033[38;5;107m", Err: "\033[38;5;196m", Info: "\033[38;5;103m", BannerTop: "\033[38;5;245m", BannerBot: "\033[38;5;160m", } // ThemeNoir is monochrome — only greys and a single white accent. // For operators who hate color but still want hierarchy. Errors // remain red because no-color in errors is unsafe ergonomics. ThemeNoir = Theme{ Name: "noir", Mute: "\033[38;5;240m", Accent: "\033[38;5;255m", OK: "\033[38;5;250m", Err: "\033[38;5;203m", Info: "\033[38;5;245m", BannerTop: "\033[38;5;240m", BannerBot: "\033[38;5;255m", } // ThemeForge is the middle-ground compromise — orange ember kept // from opencode for the accent, but a steelier grey palette and // muted greens. Reads industrial rather than friendly. ThemeForge = Theme{ Name: "forge", Mute: "\033[38;5;244m", Accent: "\033[38;5;208m", OK: "\033[38;5;107m", Err: "\033[38;5;167m", Info: "\033[38;5;67m", BannerTop: "\033[38;5;244m", BannerBot: "\033[38;5;208m", } // ThemeAsh — the desaturated take on the metal aesthetic. Brick- // dust accent (131) instead of blood red, soft greys throughout. // Atmospheric without the harshness; reads like a faded patch on // a denim jacket. ThemeAsh = Theme{ Name: "ash", Mute: "\033[38;5;245m", Accent: "\033[38;5;131m", OK: "\033[38;5;108m", Err: "\033[38;5;167m", Info: "\033[38;5;103m", BannerTop: "\033[38;5;245m", BannerBot: "\033[38;5;131m", } // ThemeOxblood pushes red as far toward black as it can go while // still reading as red — a very dark wine accent (88) on dim // muted greys. Brooding; the accent is barely a color at all, // which is what makes it feel kvlt rather than warning-light. // Errors stay brighter so they remain distinguishable from the // accent. ThemeOxblood = Theme{ Name: "oxblood", Mute: "\033[38;5;240m", Accent: "\033[38;5;88m", OK: "\033[38;5;100m", Err: "\033[38;5;124m", Info: "\033[38;5;60m", BannerTop: "\033[38;5;240m", BannerBot: "\033[38;5;88m", } // ThemeRust shifts the accent toward orange-red — weathered // industrial rather than gothic metal. 130 reads as oxidized // iron on a sun-bleached fence; pairs naturally with steel-grey // muted text. ThemeRust = Theme{ Name: "rust", Mute: "\033[38;5;243m", Accent: "\033[38;5;130m", OK: "\033[38;5;107m", Err: "\033[38;5;167m", Info: "\033[38;5;66m", BannerTop: "\033[38;5;243m", BannerBot: "\033[38;5;130m", } )
Built-in themes. Pick one with `KVLT_THEME=<name>` (default "opencode"). Adding a new theme is a single Theme literal here + register in themes.
Functions ¶
func Accent ¶
Accent returns s rendered as the brand accent color (orange in opencode, blood red in metal, white in noir, …).
func Banner ¶
Banner returns the kvlt block-letter logo, themed via the active theme's BannerTop/BannerBot colors. Line-level coloring (rather than the half-block midline trick) — 2-row letterforms don't give us enough vertical room for a true middle stripe.
On non-color outputs the banner falls back to plain block letters.
func ConfirmDestructive ¶
ConfirmDestructive shows a yes/no prompt on /dev/tty for the "delete this thing" path. Returns true only on an exact "y" or "yes" (case-insensitive). Anything else — empty enter, "n", gibberish — returns false. We deliberately do NOT default to yes on enter: destructive actions should require an affirmative key.
Returns an error if no /dev/tty is available, so callers in CI can rely on `--force` rather than silently waiting on Read.
func Field ¶
Field renders a `label: value` line styled MUTED-then-NC, padded so successive labels of varying length still align. Width is the column where the value starts (label + ":" + spaces fills to it).
Used by `vault info` and `vault list` so the on-disk vault layout reads consistently with the install summary.
func PassphrasePromptTTY ¶
PassphrasePromptTTY reads a passphrase from /dev/tty with echo suppressed. Going through /dev/tty (not stdin/stderr) is deliberate so prompts work inside command substitutions like $(kvlt get …) — stdout might be captured, stderr might be redirected, but /dev/tty always points at the user's terminal.
Returns an error if the process has no controlling terminal (CI, detached daemon, …) so callers can surface a clear "no TTY available" message rather than silently hanging on a Read.
func PromptSecretValue ¶
PromptSecretValue reads a secret value (`kvlt put <vault> <key>` with no `=` and no piped stdin) from /dev/tty with echo suppressed. Same /dev/tty rationale as PassphrasePromptTTY.
func SetTheme ¶
SetTheme replaces the active theme. Returns false if name is unknown — callers can fall back to the default and warn.
func Success ¶
Success renders a leading "✓" mark in the OK color followed by msg. Falls back to "[ok]" on NO_COLOR / non-TTY for log-friendliness.
func ThemeNames ¶
func ThemeNames() []string
ThemeNames returns every registered theme name, sorted. The first element is the default (opencode); subsequent are alphabetical so listings are deterministic.
Types ¶
type Theme ¶
type Theme struct {
Name string
Mute string
Accent string
OK string
Err string
Info string
BannerTop string
BannerBot string
}
Theme is a six-role palette covering every place kvlt emits styled text. Roles are kept stable across themes so a theme swap is a pure recolor — no callers change.
Mute labels, secondary metadata ("name:", "version:")
Accent primary highlight — paths, IDs, vault names, headlines
OK success events (vault created, secret stored)
Err errors at the CLI boundary
Info cool-toned hints and pointers
Banner* the two banner lines — Top/Bot let themes decide whether
the brand color sits above or below the implicit midline
Each field is a raw SGR escape string, applied as `code + text + reset` at render time. Empty string disables coloring for that role, which is how the no-color and NO_COLOR fallbacks short-circuit.
func ActiveTheme ¶
func ActiveTheme() *Theme
ActiveTheme returns the currently-active theme. Useful for `kvlt themes` listing or for tests that want to assert behavior under a specific palette.