Shell aliases are useful when you remember them.

The problem starts when your collection grows large enough that you no longer remember:

  • the exact alias name
  • which aliases already exist
  • which one solves a specific problem
  • what arguments a command expects
  • whether a command is safe to run as-is

At that point, aliases stop being a productivity tool and start becoming another thing you need to memorize.

That is the problem I wanted to solve with cmdpeek.

cmdpeek is an open-source searchable command palette for reusable terminal workflows.

Instead of remembering an exact alias such as:

klo

you can search by what you want to do:

cmdpeek kubernetes logs

The command does not need to match the internal name exactly.

cmdpeek searches across:

title
name
description
labels
command contents

This means a workflow can be discovered using different words, old alias names, technical concepts, or even part of the underlying command.

Aliases optimize commands you remember. cmdpeek helps you discover commands you do not.


Why aliases stop scaling

A small number of aliases is easy to manage:

alias k='kubectl'
alias kgp='kubectl get pods'
alias klo='kubectl logs -f'

But over time, collections often grow into dozens or hundreds of entries covering Kubernetes, Flux, Git, GitHub Actions, AWS, Terraform, local development, troubleshooting, media conversion, and deployment workflows.

The commands may still be useful, but remembering their names becomes difficult.

You may know that you created something to download GitHub Actions logs, force a Flux HelmRelease reconciliation, switch Kubernetes context, inspect Elasticsearch shards, or convert a GIF into MP4.

But you may not remember whether the alias was called:

ghlogs
download-run
gha-debug
flux-force
hr-reconcile
gif2mp4

cmdpeek removes that dependency on exact names.

A command can include rich searchable metadata:

- name: force-reconcile-flux-helmrelease
  title: Force Flux HelmRelease reconciliation
  description: Select a namespace and HelmRelease, then force Flux to reconcile it with its source.
  labels:
    - flux
    - fluxcd
    - helm
    - helmrelease
    - reconcile
    - force
    - kubernetes
    - gitops
    - troubleshooting

That same command can be found with searches such as:

flux force
helm reconcile
gitops troubleshooting
helmrelease

Historical alias names can also remain as labels, so an existing mental shortcut still works without defining a separate shell alias.


Search by intent

The main idea behind cmdpeek is simple:

Search by intent
      โ†“
Select a workflow
      โ†“
Resolve its variables
      โ†“
Review the rendered command
      โ†“
Confirm and execute

The catalog is defined in YAML, making workflows easy to review, version, share, and extend.

A command can include:

  • a stable internal name
  • a human-readable title
  • a detailed description
  • searchable labels
  • a shell script
  • interactive variables
  • dynamic selectors generated by commands

For example:

- name: pod-logs
  title: Follow Kubernetes pod logs
  description: Select a namespace and stream logs from one of its pods
  labels:
    - kubernetes
    - pods
    - logs
    - troubleshooting
    - stream
    - klo
  run: kubectl logs -f "" -n ""

This workflow can be found through:

pod logs
kubernetes troubleshooting
stream
klo

The exact command name is no longer the only entry point.


Demo: search a large catalog

cmdpeek-search-scroll-demo

The interactive catalog supports:

/         Search
โ†‘ / โ†“     Navigate
โ† / โ†’     Change page
e         Open details
Enter     Select
q         Quit

Searches are ranked across the command metadata.

Multiple terms can be combined:

github logs
production deploy
elasticsearch size
kubernetes context

A result can therefore match because of its title, description, labels, internal name, or script contents.

This is especially useful for commands that are important but not used frequently enough to memorize.


Start with a search directly from the command line

You can also pass search terms directly after cmdpeek:

cmdpeek kubernetes context
cmdpeek github logs
cmdpeek elasticsearch shards

The arguments are joined into an initial search query.

The behavior depends on the number of results:

exact command name  โ†’ open that workflow directly
one search result   โ†’ open that workflow directly
multiple results    โ†’ show the interactive catalog already filtered
no results          โ†’ show the catalog with no matching commands

This lets cmdpeek behave like a discoverable alias system.

When you know roughly what you want, you can start with:

cmdpeek elastic

instead of opening the full catalog and typing the filter manually.


Demo: direct search and automatic selection

cmdpeek-search-demo-filter

When a search returns several workflows, cmdpeek opens the filtered list.

When the search returns only one workflow, it skips the list and enters that command directly.

For example:

cmdpeek gif

may directly open a GIF-to-MP4 conversion workflow when it is the only matching command.

This keeps the tool fast when you already know the intent, while preserving discovery when the query is broad.


Interactive variables instead of fragile aliases

Aliases become difficult to maintain when commands need parameters.

A shell alias may work for a fixed command:

alias klo='kubectl logs -f'

But real workflows usually need values such as namespace, pod, environment, branch, file path, HelmRelease, GitHub Actions URL, or commit message.

cmdpeek supports four variable sources:

Source Purpose
input Free-form user input
options Static selectable values
environment Initial value loaded from an environment variable
command Options generated by a shell command

A Kubernetes workflow can generate namespaces dynamically:

variables:
  - name: namespace
    prompt: Select Kubernetes namespace
    source:
      type: command
      command: >-
        kubectl get namespaces
        -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'

A second variable can depend on the first:

  - name: pod
    prompt: Select pod
    source:
      type: command
      command: >-
        kubectl get pods -n ""
        -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'

This turns a command into a guided workflow rather than a string you need to remember and edit manually.


Dynamic selectors

Command-generated variables are especially useful for DevOps workflows.

They can list Kubernetes namespaces, pods, contexts, Flux HelmReleases, Git branches, AWS profiles, files, releases, or environments.

For example, a Flux reconciliation workflow can first list namespaces and then list only the HelmReleases inside the selected namespace:

variables:
  - name: namespace
    prompt: Select Kubernetes namespace
    source:
      type: command
      command: kubectl get namespaces -o name

  - name: helmrelease
    prompt: Select Flux HelmRelease
    source:
      type: command
      command: >-
        flux get helmreleases
        --namespace ""
        --no-header
        | awk '{print $1}'

The user does not need to remember or type resource names manually.


Preview before execution

Variable values are inserted into the command preview as they are selected.

Long commands and scripts remain scrollable, allowing the final result to be reviewed before execution.

After all variables are resolved, cmdpeek displays the fully rendered command and requires explicit confirmation:

Execute this command?

โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ flux reconcile helmrelease svc-time       โ”‚
โ”‚   -n devbox-phoenix-2                     โ”‚
โ”‚   --with-source                           โ”‚
โ”‚   --force                                 โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

y execute   n cancel   enter cancel

This is particularly useful for commands involving production environments, deployments, deletes, forced reconciliations, pushes, migrations, or infrastructure changes.

The command remains visible before execution instead of being hidden behind an alias.


Non-interactive mode

Interactive discovery is useful when you do not remember the exact workflow.

But sometimes you already know the command name and want to reuse it from a shell function, a script, CI, documentation, or another tool.

For those cases, cmdpeek also supports non-interactive execution:

cmdpeek \
  --no-interactive \
  --name gcommit \
  --set "message=Add non-interactive execution demo"

Values can be supplied with repeatable --set flags:

cmdpeek \
  --no-interactive \
  --name deploy \
  --set environment=staging \
  --set version=1.4.2

The same YAML catalog can therefore support both interactive discovery and scriptable execution.


Demo: reuse a workflow non-interactively

cmdpeek-non-interactive-gcommit

This mode still renders the command and asks for confirmation unless --yes is provided.

A dry run is also available:

cmdpeek \
  --no-interactive \
  --name gcommit \
  --set "message=Preview this commit" \
  --dry-run

This prints the final command without executing it.


Local and shared catalogs

By default, cmdpeek looks for:

.cmdpeek.yaml

A local path can be configured through:

export CMDPEEK_CONFIG_FILE="$HOME/.config/cmdpeek/commands.yaml"

Catalogs can also be loaded from GitHub:

export CMDPEEK_CONFIG_GITHUB="company/platform-config:cmdpeek/commands.yaml@main"

For private repositories, authentication can be supplied through:

export CMDPEEK_GITHUB_TOKEN="github_pat_..."

Remote configurations are cached locally and refreshed using GitHub ETags.

This makes it possible to maintain a personal workflow catalog, a repository-specific catalog, a shared team catalog, or a versioned platform engineering catalog.

The YAML file becomes executable documentation for workflows that would otherwise be scattered across aliases, shell history, snippets, and README files.


Example workflows

The same catalog can describe very different tasks.

Analyze GitHub Actions logs

cmdpeek github logs

The workflow can request a GitHub Actions run or job URL, download the logs, extract them, and prepare them for analysis.

Force a Flux HelmRelease reconciliation

cmdpeek flux force

The workflow can interactively select a namespace and HelmRelease before running:

flux reconcile helmrelease <name> \
  --namespace <namespace> \
  --with-source \
  --force

Switch Kubernetes context

cmdpeek kubernetes context

Available contexts can be generated dynamically from the current kubeconfig.

Convert GIF to MP4

cmdpeek gif mp4

The workflow can request input and output paths and execute a consistent ffmpeg conversion.

Run a Git commit workflow

cmdpeek \
  --no-interactive \
  --name gcommit \
  --set "message=Document cmdpeek workflows"

Installation

Homebrew

Linux and macOS:

brew install --cask pierinho13/tools/cmdpeek

Upgrade:

brew update
brew upgrade --cask cmdpeek

GitHub Releases

Precompiled binaries are available through GitHub Releases.

Build from source

git clone https://github.com/pierinho13/cmdpeek.git
cd cmdpeek

go build -o cmdpeek ./cmd/cmdpeek
sudo mv cmdpeek /usr/local/bin/

Quick start

Create .cmdpeek.yaml:

version: 1
shell: bash

commands:
  - name: greet
    title: Greet a person
    description: Print a personalized greeting
    labels:
      - example
      - greeting
      - hello
    run: |
      name=""
      echo "Hello, ${name}!"
    variables:
      - name: name
        prompt: Person name
        default: world
        source:
          type: input

Then run:

cmdpeek

Or search directly:

cmdpeek greeting

Why not just use aliases, fzf, or a task runner?

cmdpeek is not intended to replace every shell alias, fuzzy finder, or task runner.

Aliases are still ideal for very short commands you use constantly and remember easily.

Task runners are excellent for repository-defined build and automation tasks.

fzf is excellent for filtering arbitrary streams of text.

The focus of cmdpeek is different:

structured command discovery by intent
+
guided variable resolution
+
live preview
+
safe execution

The searchable metadata belongs to the command model itself.

A workflow is not just a command string. It has a title, description, labels, variables, and execution behavior.

That makes it easier to discover months later, share with other people, and evolve without creating more aliases.


Final thoughts

The main goal of cmdpeek is not simply to execute commands.

The goal is to make useful terminal workflows discoverable.

A command you cannot remember effectively does not exist when you need it.

By searching names, titles, descriptions, labels, and command contents, cmdpeek makes it possible to find workflows using the words you remember at that moment.

That is what makes it different from a large alias file.

Instead of asking:

What did I call that alias?

You can ask:

What do I want to do?

The project is open source:

https://github.com/pierinho13/cmdpeek

Contributions, feedback, workflow examples, documentation improvements, tests, packaging support, and TUI ideas are very welcome.

If youโ€™re interested in this kind of platform engineering work, you can learn more about my experience or get in touch.