Skip to main content

A Friendly CLI Alias Manager

Project description

qwik — A Friendly CLI Alias Manager

Coverage Bugs Quality Gate Status

Create, manage, and run shell aliases from a single interface. Works cross-platform with bash, zsh, fish, PowerShell, and cmd.

Two ways to run any alias:

  • gs — native shell command (after one-time hook install)
  • qwik -r gs — works anywhere, no setup needed

Table of Contents


Installation

Not yet published to PyPI; install from source.

pipx install git+https://github.com/ragilhadi/qwik.git

Or with uv:

uv tool install git+https://github.com/ragilhadi/qwik.git

Quick Start

qwik add gs "git status"
qwik init zsh --install
source ~/.zshrc

gs                      # native shell alias
qwik -r gs               # same thing, no hook needed

Core Concepts

Two ways to run

Way Example When to use
Native gs Daily use after one-time shell hook setup
Via qwik qwik -r gs Scripts, CI, restricted shells, or pre-setup

Both share the same store and substitution engine — behavior is identical.

How it works

  1. You register aliases with qwik add
  2. You install a one-line shell hook with qwik init --install
  3. Every new shell session regenerates shell-native aliases from the store
  4. You type gs just like a normal alias — because it is one

Commands

add — Create alias

qwik add gs "git status"
qwik add gs "git status" --tag git --description "Repo status"
qwik add gs "git status" --group git
qwik add gs "git status" --force       # overwrite existing
qwik add                               # interactive mode

rm — Delete alias

qwik rm gs
qwik rm gs --yes                       # skip confirmation

rename — Rename alias

qwik rename gs gstat                   # preserves stats

edit — Edit in $EDITOR

qwik edit gs
# Opens TOML snippet in your $EDITOR:
#   command = "git status"
#   tag = ["git"]
#   description = ""
#   enabled = true
# Save and quit to apply changes.

enable / disable — Toggle without deleting

qwik disable gs                        # hides from shell hook
qwik enable gs                         # re-enables

list — Pretty table

qwik list                              # all aliases
qwik -l                                # shortcut
qwik list --tag git                    # filter by tag
qwik list --group git                   # filter by group
qwik list --search stat                # filter by query

Output:

  Name   Command                     Group   Tag    Used   Last
 ─────  ──────────────────────────  ──────  ─────  ─────  ───────────
  gs     git status                  git     git     42     2 min ago
  gco    git checkout {1}            git     git     18     1 hour ago
  k      kubectl                     —       k8s     7     yesterday

show — Detailed view

qwik show gs                           # full metadata

search — Fuzzy search

qwik search "git"
qwik -s "git"                          # shortcut
qwik search "git" --group git          # restrict to a group

pick — Interactive fuzzy picker

qwik                                   # bare invocation
qwik pick
  • Type characters to filter matching aliases live
  • / navigate
  • Enter runs the selected alias
  • Ctrl+E edits it
  • Ctrl+D deletes it
  • Esc cancels

run — Execute alias

qwik run gs
qwik run gs --short                    # pass extra args
qwik -r gs --short                     # shortcut flag

tag / untag

qwik tag gs git
qwik tag gs work
qwik untag gs work

group / ungroup

qwik group gs git                      # assign primary group
qwik ungroup gs                        # remove the group

An alias has at most one group (the canonical primary namespace it belongs to) but may carry many tags (free-form labels). Use --group on add, list, and search to filter by group.

export / import

qwik export ~/aliases.toml             # share / backup
qwik import ~/aliases.toml             # merge
qwik import ~/aliases.toml --overwrite

sync — Dotfile sharing across machines

qwik sync keeps a separate git repo at <config_dir>/qwik-sync/ so your aliases travel between machines. push exports the live store → commits → pushes; pull pulls the remote → import-merges into your live store (with the same trust-boundary preview as qwik import).

qwik sync init --remote <git-url>      # one-time setup; exports current store + first commit
qwik sync push [-m "msg"]              # export → commit (if dirty) → push
qwik sync pull [-y]                    # pull → preview → merge into live store
qwik sync status                       # branch, remote, dirty, ahead/behind, alias count

sync init writes sync.toml (remote + branch) and aliases.toml (your store) into the sync repo and makes the first commit. sync push overwrites aliases.toml with the current live store, commits only if the tree is dirty, then pushes to origin <branch>. sync pull runs git pull, then shows the same trust-boundary preview as qwik import — incoming commands run under shell=True, so review the preview before confirming.

Trust warning: pulled stores are a code-execution vector. Always review the command preview before confirming a sync pull; only sync with repos you control.

doctor — Health check

qwik doctor                            # shell, hook, store, conflicts, sync repo

init — Shell hook

qwik init zsh                          # print hook to stdout
qwik init zsh --install                # append to ~/.zshrc with backup

Supported shells: bash, zsh, fish, pwsh.

completion — Shell completions

Generate or install shell completion scripts for qwik itself (so qwik <Tab> offers command/alias suggestions).

qwik completion bash            # print completion script to stdout
qwik completion zsh --install   # install into ~/.zshrc + ~/.zfunc/_qwik
Shell --install action
bash writes ~/.bash_completions/qwik.sh + appends source line to ~/.bashrc
zsh writes ~/.zfunc/_qwik + appends fpath/compinit to ~/.zshrc
fish writes <fish config>/completions/qwik.fish (auto-loaded, no rc edit)
pwsh / powershell appends the script to $PROFILE

Installs are idempotent (a # qwik completion (<shell>) marker is checked before appending) and back up the rc file with a timestamp before modifying it.

Typer's built-in qwik --install-completion <shell> / qwik --show-completion <shell> also works; qwik completion provides the same scripts with qwik's own backup + idempotency behavior.

Version & Help

qwik --version
qwik -v
qwik --help
qwik -h
qwik --no-color           # disable colored output for this invocation

Alias Templates & Arguments

Aliases can pass arguments through unchanged or interpolate them into the command.

Append mode (default — no placeholders)

Extra args are appended after quoting.

qwik add gs "git status"
gs --short              # → git status --short

Template mode (placeholders)

Use {…} markers to substitute arguments into the command.

Placeholder Meaning
{1}, {2}, {3} Nth positional argument (1-based)
{name} Named slot — mapped to a positional index by order of first appearance (see below)
{@} All arguments joined with spaces
{*} All arguments as a single quoted string
{1:-default} Nth positional, falling back to default if missing
{name:-default} Named slot, falling back to default if the arg is missing

Single positional:

qwik add gco "git checkout {1}"
gco main                # → git checkout main

Note: {1}, {@}, and {N:-default} interpolations are shlex.quoted at runtime, so args containing shell metacharacters are passed safely. {*} is shell-quoted as a single string. For example, qwik run gco '; rm -rf /' expands to git checkout '; rm -rf /' — the ; is quoted and treated as a literal argument, not a command separator.

Multiple positionals:

qwik add gcm 'git commit -m "{1}: {2}"'
gcm feat "add login"
# → git commit -m "feat: add login"

Named placeholders (readable):

qwik add gco "git checkout {branch}"
gco main                # → git checkout main

qwik add gcm 'git commit -m "{type}: {scope}"'
gcm feat login          # → git commit -m "feat: login"

Named placeholders are mapped to positional arguments by order of first appearance: the first distinct name is {1}, the second is {2}, and so on. Repeating a name reuses its index (echo {a} {a} with arg xecho x x). Named and numeric placeholders share the same index space — echo {1} {name} with args a becho a b ({1}=a, {name}=b at index 2).

Note: Named placeholder names must start with a letter or underscore and contain only letters, digits, underscores, and hyphens (^[A-Za-z_][A-Za-z0-9_-]*$). A {…} that doesn't match this pattern and isn't a numeric/@/* placeholder is left as a literal — so {123bad} and {some text} in a command are passed through untouched.

Default value:

qwik add gpo "git push origin {1:-main}"
gpo                     # → git push origin main
gpo feature/x           # → git push origin feature/x

All args joined:

qwik add gc-chore 'git commit -m "chore: {@}"'
gc-chore init version
# → git commit -m "chore: init version"

All args as one quoted string:

qwik add note 'echo "Note: {*}"'
note hello world
# → echo "Note: 'hello world'"

Mixed — template + appended extras:

qwik add k "kubectl {1}"
k get pods -n kube-system
# → kubectl get pods -n kube-system
#     {1}=get, "pods -n kube-system" appended after template

Placeholder defaults

{N:-default} is especially useful for aliases with a sensible fallback:

qwik add co "git checkout {1:-main}"
co feature              # → git checkout feature
co                      # → git checkout main (default)

Validation

  • {0} is rejected at add-time and at run-time — positional placeholders are 1-based
  • Named placeholders ({name}) are 1-based by order of appearance, so there is no {0name} form; {0name} is a literal
  • Invalid brace content (e.g. {123bad}, {some text}) is left untouched as a literal, not an error
  • Missing required args produce a clear error at runtime instead of silently expanding to empty strings

Shell Integration

Make aliases available as real shell commands.

One-time setup

bash:

qwik init bash --install
source ~/.bashrc

zsh:

qwik init zsh --install
source ~/.zshrc

fish:

qwik init fish --install
source ~/.config/fish/config.fish

PowerShell:

qwik init pwsh --install

The --install flag:

  • Creates a timestamped backup of your rc file
  • Appends the hook (idempotent — safe to run multiple times)

Manual setup

If you prefer to edit your rc file directly, qwik init <shell> prints the hook:

eval "$(qwik init zsh)"

Per-shell rendering

The hook generates native aliases/functions for each shell:

Shell Append mode Template mode
bash / zsh alias gs='git status' gs() { git checkout "$1" ; }
fish alias gs 'git status' function gs ; … ; end
PowerShell function gs { echo hi @args } function gs { echo "{1}" $args[0] }
cmd doskey gs=git status $* (best-effort, no template)

Conflict Detection

Every add and rename validates the new name:

# Check Result
1 Already an alias? Refuse unless --force
2 Shell builtin? (cd, echo, alias, …) Refuse unless --force
3 Binary on $PATH? Warn but allow
4 Valid syntax? Refuse if it contains spaces, slashes, $, backticks, semicolons

Example UX:

qwik add ls "ls --color=auto" Warning: "ls" shadows /usr/bin/ls.
  Continue? [y/N]

qwik add cd "echo nope" "cd" is a shell builtin. Shadowing it can break your shell.

qwik add "my alias" "echo hi" Invalid name "my alias": contains whitespace.

Storage & Backups

  • Linux/macOS: $XDG_CONFIG_HOME/qwik/aliases.toml (usually ~/.config/qwik/aliases.toml)
  • Windows: %APPDATA%\qwik\aliases.toml
  • Backups: every destructive operation writes to qwik/backups/aliases-<timestamp>.toml (last 20 kept)
  • Atomic writes: temp file + rename to prevent corruption
  • Format: human-readable TOML, safe to edit by hand

Example store file:

version = 1

[aliases.gs]
command = "git status"
tag = ["git"]
group = "git"
description = "Quick git status"
enabled = true
created_at = "2026-05-10T10:00:00Z"
updated_at = "2026-05-10T10:00:00Z"
last_used = "2026-05-10T11:30:00Z"
run_count = 42

Store versioning

qwik writes a version = N field to the top of aliases.toml describing the schema of the file. On load, if the file's version is older than the current schema, qwik auto-migrates it forward (one migrator per version step) and backs up the pre-migration file before writing the new shape. Migration is forward-only — downgrade is not supported; restore from a backup (see qwik doctor) instead.

If the file's version is newer than the version qwik understands, qwik refuses to load it and points at qwik doctor — typically you need to upgrade qwik to a newer release.


Environment Variables

Variable Purpose
EDITOR Editor for qwik edit (default: vi)
QWIK_CONFIG_DIR Override default config directory
XDG_CONFIG_HOME Base config dir (used by fish rc resolution)
QWIK_DEBUG=1 Enable debug logs to stderr
NO_COLOR Disable colored output (also --no-color)

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run the test suite
pytest

# With coverage report
pytest --cov=qwik --cov-report=term-missing

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qwik-0.3.0.tar.gz (94.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qwik-0.3.0-py3-none-any.whl (59.2 kB view details)

Uploaded Python 3

File details

Details for the file qwik-0.3.0.tar.gz.

File metadata

  • Download URL: qwik-0.3.0.tar.gz
  • Upload date:
  • Size: 94.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for qwik-0.3.0.tar.gz
Algorithm Hash digest
SHA256 39c4b30501a70146312f37fb810ef6fb99c69a3568fd9fe7b33f9be04c52b000
MD5 87223618d879864c4ec6f83b787f6b78
BLAKE2b-256 b1044f77285a861449b5ac60bbcb2f43668a6761343729fc922fcbf43d2c27b8

See more details on using hashes here.

File details

Details for the file qwik-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: qwik-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 59.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for qwik-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cdb8d913c87155cde121a26c840d0e2c632b8ae85abc839bae6ae2c8b754bc3a
MD5 59c75c3382706bde84ca959b488fd673
BLAKE2b-256 545032ec922c8f9d4c2af41bdf936c0522ee7d10aa6cb564a94b8706b11bc67f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page