A nice and icy ZSH prompt in Nim


A nice and icy ZSH prompt in Nim

Build Status



I’ve always wanted to minimize my reliance on frameworks like oh-my-zsh, so I figured, why not write my own ZSH prompt in my new favourite language? Turned out to be a really fun exercise.


  • Written in Nim 👑
  • Fast (in theory, since Nim compiles to C)
  • Pretty defaults.
  • Plugin-like system for prompt customization, in case you didn’t like the pretty defaults.
  • Fun, I guess.


Note: It’s probably a good idea to uninstall oh-my-zsh, or any other plugin framework you’re using altogether. It may cause conflicts.

$ nimble install nicy

Don’t know what that is? New to Nim? Check out the Nim docs. nimble is packaged with Nim by default.

Quick start

Add this to your ~/.zshrc. If you installed via nimble, set PROMPT to $(~/.nimble/bin/nicy).

autoload -Uz add-zsh-hook
_nicy_prompt() {
add-zsh-hook precmd _nicy_prompt

Make sure you disable all other themes.


If you want to configure nicy as it is, you’ll have to edit the src/nicy.nim file and recompile. Messy, I know.

Build your own prompt

Alternatively, you can just as easily write your own prompt in Nim using nicy’s built-in API. Refer to the Examples section for some insight.

Once you’re done, compile it and add a similar function to your .zshrc as above, replacing PROMPT with the path to your own binary.


# ‘user@host $’ prompt

import nicy, strformat

  user = color(user(), "green")
  host = color(host(), "red")
  prompt = color("$ ", "cyan")
  at = color("@", "yellow")

echo fmt"{user}{at}{host} {prompt}"
# fish’s default prompt '~>'

import nicy, strformat

  prompt = color("> ", "green")
  tilde = tilde(getCwd())

echo fmt"{tilde}{prompt}"
# pure by @sindresorhus (kinda)

import nicy, strformat

  prompt = color("❯ ", "magenta")
  tilde = color(tilde(getCwd()), "cyan")
  git = color(gitBranch() & gitStatus("*", ""), "red")
  nl = "\n"

echo fmt"{tilde}{git}{nl}{prompt}"
# switching by return code

import nicy, strformat

  prompt = returnCondition(ok = "👍", ng = "👎") & " "
  tilde = color(tilde(getCwd()), "cyan")
  git = color(gitBranch() & gitStatus("*", ""), "red")
  nl = "\n"

echo fmt"{tilde}{git}{nl}{prompt}"
# ~ master
# 👍 


zeroWidth(s: string): string
Returns the given string wrapped in zsh zero-width codes. Useful for prompt alignment and cursor positioning.
All procs below return strings wrapped by this.

foreground(s, color: string): string
Returns the given string, colorized.
Possible colors are "black", "red", "green" "blue", "cyan", "yellow", "magenta", "white".

background(s, color: string): string
Returns the given string with its background colorized.
Same possible colors as above.

bold(s: string): string
Makes the given string bold.

underline(s: string): string
Adds an underline to the given string.

italics(s: string): string
Italicizes the given text. May not work on all terminals!

reverse(s: string): string
Swaps the foreground/background colors for the given string.

reset(s: string): string
Resets all attributes. Useful for disabling all styling.

color(s: string, fg: string = "", bg: string = "", b: bool = false, u: bool = false, r = false): string
Convenience proc that sets all attributes to a given string.
fg: foreground, bg: background, b: bold, u: underline, r: reverse

horizontalRule(c: char): string
Returns a string of characters c, having the length of the current terminal width. Useful for positioning right-side prompts.

tilde(path: string): string
If path starts with /home/user, it is replaced by a ~/.

getCwd(): string
Returns the full path of the current working directory, or returns the string [not found] if current path doesn’t exist. (eg: rm -rf ../curpath)

virtualenv(): string
Returns the current virtualenv name if in one.

gitBranch(): string
Returns the current git branch, if in a git directory.

gitStatus(dirty, clean: string): string
Returns either dirty or clean if in a git repository. For example, return if clean and × if dirty.

user(): string
Returns the current username.

host(): string
Returns the current hostname.

returnCondition*(ok: string, ng: string, delimiter = "."): string
Returns ok string or ng string. if the return code is 0 then ok else ng.

returnCondition*(ok: proc(): string, ng: proc(): string, delimiter = "."): string
Returns result of ok proc or ng proc. if the return code is 0 then this proc calls ok proc else this proc calls ng proc.

echoc*(s: cstring) {.importc: "printf", header: "<stdio.h>".}
Fast, pure C alternative to echo. Uses cstring.


Bad code? New feature in mind? Open an issue. Better still, learn Nim and shoot a PR


MIT © Anirudh Oppiliappan

Need help? Read Nimble
Available versions:
License: MIT

Project website Hosted docs