cli

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 4, 2026 License: MIT Imports: 7 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
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

func Accent(w io.Writer, s string) string

Accent returns s rendered as the brand accent color (orange in opencode, blood red in metal, white in noir, …).

func Banner(w io.Writer) string

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

func ConfirmDestructive(question string) (bool, error)

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 Err

func Err(w io.Writer, s string) string

Err returns s in the error color.

func Failure

func Failure(w io.Writer, msg string) string

Failure mirrors Success for error one-liners.

func Field

func Field(w io.Writer, width int, label, value string)

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 Info

func Info(w io.Writer, s string) string

Info returns s in the cool-toned info/hint color.

func Mute

func Mute(w io.Writer, s string) string

Mute returns s rendered as secondary text per the active theme.

func OK

func OK(w io.Writer, s string) string

OK returns s in the success color.

func PassphrasePromptTTY

func PassphrasePromptTTY(keyPath string) ([]byte, error)

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

func PromptSecretValue(label string) (string, error)

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

func SetTheme(name string) bool

SetTheme replaces the active theme. Returns false if name is unknown — callers can fall back to the default and warn.

func Success

func Success(w io.Writer, msg string) string

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL