Skip to content
shuymnPublic

About

Rust prompt engine for zsh with per-session workers, async updates, and generic TOML modules.

Topics

Resources

Stars

9 stars

Watchers

0 watching

Forks

Repository files navigation

capsule

English・日本語

A zsh prompt that never makes you wait to type. capsule is written in Rust for macOS and Linux: each shell owns one background worker that gathers Git and tool information while zsh keeps accepting input.

capsule prompt demo

Why capsule

  • Input is never blocked. Prompts that compute everything in precmd make you wait for git status after every Enter. Capsule draws the prompt immediately, keeps the last confirmed information while the directory and environment are unchanged, and swaps in fresh results when they arrive.
  • No module zoo. There are no built-in modules for specific tools. Node, AWS, Kubernetes, and anything else are a few lines of configuration that read an environment variable, a file, or a command's output.
  • zsh only, on purpose. Supporting a single shell lets the integration rely on zsh's hooks and line editor instead of a lowest common denominator.
  • Prompt data stays data. Branch names, file contents, and command output are displayed literally. They are never expanded as prompt escapes or shell code (threat model).

Measured

Pressing Enter on an empty line in a large repository (50,000 tracked files, 200 modified, 200 untracked) right after the branch was switched from another terminal. Both tools use their default configuration. Values are p50 / p90 of 50 interleaved samples per tool on GitHub-hosted runners.

Bar chart of prompt latency on Linux and macOS runners: input blocked is about 1.5 ms for capsule versus 74 to 126 ms for starship; the fresh branch appears sooner with capsule as well.

Runner Tool Input blocked Fresh branch shown
ubuntu-latest (AMD EPYC, 4 vCPU) capsule 1.1.1 1.4 / 1.4 ms 53 / 58 ms
starship 1.26.0 73 / 79 ms 73 / 79 ms
macos-latest (Apple M1 VM, 3 vCPU) capsule 1.1.1 1.7 / 2.4 ms 82 / 111 ms
starship 1.26.0 126 / 247 ms 126 / 247 ms

Input blocked is the time until zsh accepts typing again; a plain zsh prompt takes 0.4 ms. Fresh branch shown is the time until the new branch name is on screen. The numbers compare tools on the same runner, not absolute performance. See the full results and the method; anyone can repeat it with the Prompt latency workflow.

Prompt

<directory> on <git branch> [indicators] via <custom value> took <duration>
<optional custom values> at <optional time> ❯

The two-line prompt shows the directory, Git, custom values, command duration, and optional time. The prompt character reflects the last command's status and changes to ❮ in vi command mode.

Installation

Requirements: macOS or Linux and zsh. Git information requires git on the shell's exported PATH.

brew install shuymn/tap/capsule
# or
mise use -g github:shuymn/capsule

Add this line to .zshrc:

eval "$(capsule init zsh)"

Upgrading from 0.x (shared daemon)? Complete the migration steps before replacing the binary.

Nix

nix run github:shuymn/capsule -- --version
nix profile install github:shuymn/capsule

The profile install provides the binary; add the .zshrc line yourself. Declarative modules install the binary and add that initialization automatically:

# Add inputs.capsule.url = "github:shuymn/capsule" to your flake.
{
  imports = [ inputs.capsule.homeManagerModules.default ];
  programs.capsule.enable = true;
}

Use inputs.capsule.nixosModules.default or inputs.capsule.darwinModules.default in the matching system configuration. Choose one integration owner. Set programs.capsule.enableZshIntegration = false to manage initialization yourself.

Configuration

Capsule works without a configuration. Run capsule preset to print editable examples, keep the modules you need, and save them to ~/.config/capsule/config.toml. This module shows the Node version only inside a project:

schema_version = 2

[[module]]
name = "node"
when.files = ["package.json"]
format = "v{version}"
connector = "via"

[module.values]
version = [{ command = ["node", "--version"], regex = 'v?(\d[\d.]*)' }]

See the configuration guide for value sources, conditions, formatting, styles, and reload behavior.

Scope

Capsule is kept small enough for one person to maintain. Tool-specific display is written as configuration rather than added as new modules, and shells other than zsh are out of scope.

Development

Use stable Rust and mise (mise install provides lefthook and uv); tests also require zsh and Git. Read architecture for runtime contracts, tooling for checks, benchmarks for measurements, and release procedures for publishing.

About

Rust prompt engine for zsh with per-session workers, async updates, and generic TOML modules.

Topics

Resources

Stars

9 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages

Generated from shuymn/rust-template