General Config Settings

Everything starts here

This section contains the bulk of my personal config. Settings get spun out into their own sections if I think they make this one unwieldy.


Maybe someday org will be my main task manager. Until then, I need to be sure Taskwarrior works.

# Files

Code Snippet 1: ~/.taskrc

Contexts -pay -finances -personal
context.focused=(priority:H or priority:M) -idea -shelved -finances urgency > 5.0 -idea -personal

Set verbosity

Use verbose=off to cut out any extra messaging.


Adjust urgency

I should blog about this.

Top tasks report

task top for a lightweight overview of what I consider my most important tasks.

# Almost-minimal view of tasks I want to work on most,priority,project,tags,description.count'Minimal details of tasks' (priority:H or priority:M),Pri,Project,Tags,Description,project-,description+

Points for tasks

A custom UDA. I wonder if I can validate this to require fibonacci values?


# Display pending tasks that have been pointed
report.pointed.description='Open tasks that have point estimates'
report.pointed.filter=status:pending points > 0

# Display pending tasks that have *not* been pointed
report.unpointed.description='Open tasks that have point estimates'
report.unpointed.filter=status:pending -idea points:

Sync settings

I use Freecinc as my task server. Don’t need to export this block. Instructions are on the site.


I copied these from the standard Taskwarrior shared files, because standard Taskwarrior shared files can be in different locations. Felt cute. Might delete later.

I decided not to export the source blocks for theme configuration. They’re handy for me to keep with my config, but add too much noise for others. You can find these themes with your Taskwarrior installation — /usr/share/task on Ubuntu.

task-counts to show task counts

Give me a quick summary of important tasks in Tmux and shell contexts.

  • tasks I’m working on this second (+ACTIVE)
  • tasks I want done soon (priority:H)
  • tasks I want to get to soon (priority:M)
  • tasks I need to triage (priority:)
  # I have started doing these tasks
  a_tasks=$(task rc.verbose:nothing status:pending +ACTIVE count)

  # I am — or want to be — doing these now
  h_tasks=$(task rc.verbose:nothing status:pending priority:H count)

  # I want to do these soon
  m_tasks=$(task rc.verbose:nothing status:pending priority:M count)

  # I haven't looked at these yet
  n_tasks=$(task rc.verbose:nothing status:pending priority: count)

  echo "A:${a_tasks} H:${h_tasks} M:${m_tasks} ?:${n_tasks}"

And what does that look like? As of 2020-06-03, it looks like this:

A:0 H:2 M:29 ?:0


set -g default-terminal "tmux-256color"
set-option -sa terminal-overrides ',xterm-256color:RGB'

# See /opt/local/share/doc/tmux-pasteboard/
#if-shell 'test "$(uname -s)" = Darwin' 'set-option -g default-command "exec reattach-to-user-namespace -l zsh"'
set -s escape-time 1
#set -g mouse on

# display

# via
set -g base-index 1          # window numbering
setw -g pane-base-index 1    # pane numbering
set -g renumber-windows on   # renumber when a window closed?
setw -g automatic-rename off # rename window to reflect current program?
set -g set-titles on         # set terminal title

set -g monitor-activity on
set -g visual-activity on

set-window-option -g xterm-keys on
set-window-option -g mode-keys vi

bind c new-window -c "#{pane_current_path}"
bind r source-file ~/.tmux.conf \; display "Reloaded!"

bind \\ split-window -h -c "#{pane_current_path}"
unbind %

bind - split-window -v -c "#{pane_current_path}"
unbind '"'

bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
bind H resize-pane -L 5
bind J resize-pane -D 5
bind K resize-pane -U 5
bind L resize-pane -R 5

# status bar
set -g status on
set -g status-interval 10    # redraw status line after n seconds
set-window-option -g status-position top

# widgets
# See also:
wg_date="#[$color_secondary]%Y-%m-%d %H:%M%z#[default]"
set -g status-right "#{prefix-highlight} #(task-counts) $wg_date"


Tmux colors

Solarized everywhere! Solarize all the things!

  # Solarized colors
  #  via

  # default statusbar colors
  set-option -g status-style "fg=colour136 bg=colour235"

  # default window title colors
  set-option -g window-style "fg=colour244 bg=default dim"

  # active window title colors
  set-option -g window-status-current-style "fg=colour166 bright"

  # pane border
  set-option -g pane-border-style fg=colour235
  set-option -g pane-active-border-style fg=colour240

  # message text
  set-option -g message-style "bg=colour166 fg=colour235"

  # pane number display
  set-option -g display-panes-active-colour colour33
  set-option -g display-panes-colour colour166

  # clock
  set-option -g clock-mode-colour colour64

  # bell
  set-option -g window-status-bell-style "fg=colour235,bg=colour160"


kitty is a nice lightweight terminal emulator that you can extend with Python.

The Ubuntu / Pop!_os version of kitty is a little dated, so I did my own binary installation.

curl -L | sh /dev/stdin
mkdir -p ~/.terminfo/x
cp ~/.local/ ~/.terminfo/x/
allow_remote_control yes

font_family Fira Code
bold_font   auto
italic_font auto
font_size   12.0
shell       /usr/bin/zsh --login
Code Snippet 2: ~/.config/kitty/kitty.conf


The kitty-themes repo includes many plethoras of color schemes.

Grab it.

git clone --depth 1 ~/.config/kitty/kitty-themes

Then include an interesting theme in ~/.config/kitty/kitty.conf.

include     kitty-themes/themes/Solarized_Dark.conf

Shell integration

Add integration for Zsh.

First, make sure kitty itself is in my path.

addpath "$HOME/.local/"

Next, enable autocompletion.

autoload -Uz compinit

# Completion for kitty
kitty + complete setup zsh | source /dev/stdin



I’m using ripgrep quite a bit lately, but muscle memory and several scripts still expect ack.

# I never want to search pyc files


  # Reset to just use
  -pbp     # Start with Perl Best Practices
  -w       # Show all warnings
  -iob     # Ignore old breakpoints
  -l=80    # 80 characters per line
  -mbl=2   # No more than 2 blank lines
  -i=2     # Indentation is 2 columns
  -ci=2    # Continuation indentation is 2 columns
  -vt=0    # Less vertical tightness
  -pt=2    # High parenthesis tightness
  -bt=2    # High brace tightness
  -sbt=2   # High square bracket tightness
  -wn      # Weld nested containers
  -isbc    # Don't indent comments without leading space
  -nst     # Don't output to STDOUT


I bounce between Emacs, (neo)vim, and other editors constantly. I probably always will. Anyways, here’s what my Neovim settings look like. At least until I find a plugin to tangle VimWiki files or something.

This uses vim-plug for plugins.

curl -fLo ~/.vim/autoload/plug.vim --create-dirs \

" Plugins
call plug#begin()
Plug 'dhruvasagar/vim-table-mode'
Plug 'tbabej/taskwiki'
Plug 'vimwiki/vimwiki'
Plug 'liuchengxu/vim-which-key'
Plug 'tpope/vim-markdown'
call plug#end()

" More or less universal behaviors

filetype on
filetype plugin on
filetype indent on

set shiftwidth=2
set expandtab
set smarttab
set autoindent
set textwidth=100
set encoding=utf-8
set conceallevel=1
set timeoutlen=500
set cursorline
set number

set listchars=tab:»\ ,trail:✗,precedes:←,extends:→
set list

let g:mapleader=" "
let g:maplocalleader=','

" set hlsearch
nmap <silent> <BS> :nohlsearch<CR>

" Where should in-editor python evaluation happen?
let g:python3_host_prog = "~/.python-envs/neovim/bin/python"

" Cosmetic elements

colorscheme desert

inoremap <leader>iso :put =strftime('%FT%T%z')<CR>

" Plugin configuration

" vim-which-key
nnoremap <silent> <leader> :<c-u>WhichKey '<Space>'<CR>
nnoremap <silent> <localleader:<c-u>WhichKey ','<CR>

" Vimwiki configuration
let g:vimwiki_conceallevel=2

" Show me characters for inline formatting such as `code` and *bold*
let g:vimwiki_conceal_onechar_markers=0
let g:vimwiki_folding='expr' " fold sections and code blocks
let g:vimwiki_auto_header=1 " automatically generate level 1 header for new wiki pages

" Should we create temporary wikis not already in the wiki list? (no we should not)
let g:vimwiki_global_ext=0

let main_wiki={}
let main_wiki.path='$HOME/vimwiki'
let main_wiki.auto_toc=1
let main_wiki.diary_caption_level=1
let main_wiki.links_space_char='-'

let g:vimwiki_list=[main_wiki]

" Behaviors for specific filetypes

" set conventional Python spacing
autocmd FileType python setlocal shiftwidth=4

" disable automatic comment extension in new lines.
autocmd FileType * setlocal formatoptions-=cro

" Local tweaks

" Open help in a new tab
augroup HelpInTabs
	autocmd BufEnter *.txt call HelpInNewTab()
augroup END

function! HelpInNewTab()
  if &buftype == 'help'
    execute "normal \<C-W>T"


## Editor minimum window width (>= 400)
Width = 1000
## Editor minimum window height (>= 300)
Height = 1200

## Editor external font-family, font-size, and linespace.
## This is the font and linespace settings of the graphical UI as an nvim front end.
## For example, linespace affects the margins of the external completion popup menu UI.
## Font settings in nvim are set with well-known options, such as `:set guifont = hoge:h10`, `:set linespace=4`.
FontFamily = "Hack"
FontSize = 12

Zsh config

Zsh is my main shell. It’s sufficiently compatible with bash that I have yet to do anything interesting with it.


Loaded for all sessions.




  • Support functions

    Mostly path manipulation functions, at least until I find the inevitable zsh plugin.

      # Remove $2 from path with name $1, e.g.
      #   remove_from_path PATH ~/bin
      #   remove_from_path PYTHONPATH ~/lib/python2.7/site-packages
      function remove_from_path() {
        local a
        local p
        local s
        local r
        eval "p=\$$1"  # get value of specified path
        a=( ${(s/:/)p} )  # turn it into an array
        # return if $2 isn't in path
        if [[ ${a[(i)${2}]} -gt ${#a} ]] && return
        # rebuild path from elements not matching $2
        for s in $a; do
          if [[ ! $s == $2 ]]; then
            [[ -z "$r" ]] && r=$s || r="$r:$s"
        eval $1="$r"
      # Add path to start of named path, removing any occurences
      # already in it, e.g.
      #   prepend_path PATH ~/bin
      #   prepend_path PYTHONPATH ~/my-py-stuff
      function prepend_path() {
        # Exit if directory doesn't exit
        [[ ! -d "$2" ]] && return
        local p
        remove_from_path "$1" "$2"
        eval "p=\$$1"
        eval export $1="$2:$p"
      # As above, but add to end of path
      function append_path() {
        # Exit if directory doesn't exit
        [[ ! -d "$2" ]] && return
        local p
        remove_from_path "$1" "$2"
        eval "p=\$$1"
        eval export $1="$p:$2"
      function addpath() {
        prepend_path PATH $1
    file_info () {
        # file_info: function to display file information
        if [[ -e $1 ]]; then
            echo -e "\nFile Type:"
            file $1
            echo -e "\nFile Status:"
            gstat $1
            echo "$FUNCNAME: usage $FUNCNAME file" >&2
            return 1
  • Base environment variables

    • Set base path

      Been burned so many times — not being able to find a thing after I installed it — that I started setting $PATH myself a while back.

    • Define editor

      Still mostly Neovim for quick edits.

      export EDITOR="nvim"
    • clicolor

      I like pretty colors.

      export CLICOLOR=1
          base00=bright_yellow, on_base00=on_bright_yellow,\
          base01=bright_green,  on_base01=on_bright_green, \
          base02=black,         on_base02=on_black,        \
          base03=bright_black,  on_base03=on_bright_black, \
          base0=bright_blue,    on_base0=on_bright_blue,   \
          base1=bright_cyan,    on_base1=on_bright_cyan,   \
          base2=white,          on_base2=on_white,         \
          base3=bright_white,   on_base3=on_bright_white,  \
          orange=bright_red,    on_orange=on_bright_red,   \
    • Add home bin

      Set $PATH so it includes my home bin if it exists

      if [ -d "$HOME/bin" ] ; then
          addpath "$HOME/bin"
  • Early local shell initialization

    For stuff specific to a particular work environment. For defining variables and functions that may be needed by later processes.

    if [ -f "$HOME/.zshenv_local_before" ]; then
        source "$HOME/.zshenv_local_before"
  • Homebrew

    Homebrew works well enough on macOS and Linux that it’s become my default package manager. Of course, Arch has AUR, so there’s not as much need there.

      if [ -d "/home/linuxbrew" ] ; then
          # For Homebrew on Linux
          # Output to `/home/linuxbrew/.linuxbrew/bin/brew shellenv`
          eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
      if which brew &> /dev/null; then
          export BREW_PREFIX=`brew --prefix`
          if [ -f "$BREW_PREFIX/etc/bash_completion" ]; then
          . "$BREW_PREFIX/etc/bash_completion.d/git-completion.bash"
          . "$BREW_PREFIX/etc/bash_completion.d/"
          . "$BREW_PREFIX/etc/bash_completion"
          if [ -f "$BREW_PYTHON" ]; then
              addpath "$BREW_PYTHON/bin"
              export LDFLAGS="-L$BREW_PYTHON/lib"
              export CPPFLAGS="-I$BREW_PYTHON/include"
              export PKG_CONFIG_PATH="$BREW_PYTHON/lib/pkgconfig"
          export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)"
  • Programming environments and language managers

    plenv, pyenv, and friends. I have issues.

    • Enable go dev

      I don’t need a go version manager, but a little environment and path manipulation is nice when it’s needed.

        export GOPATH="$HOME/go"
        if [ -d "/usr/local/go" ]; then
            addpath "/usr/local/go/bin"
        if [ -d "$GOPATH" ]; then
            addpath "$GOPATH/bin"
    • Enable pyenv

      Pyenv is all sorts of headache really, but it’s the easiest way to get a fresh python.

      I usually end up installing a few pyenv-specific packages before it all starts to make sense.

      $ brew install pyenv pyenv-virtualenv pyenv-which-ext

      Anyways here’s the shell initialization code.

        if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi
    • Enable plenv

      Plenv for managing Perl installations.

      export PLENV_HOME="$HOME/.plenv"
      if [ -d "$PLENV_HOME" ] ; then addpath "$PLENV_HOME/bin"; fi
      if which plenv > /dev/null; then eval "$(plenv init -)"; fi
    • Enable rakubrew

      Rakubrew manages installed versions of Raku. I generally find its versions fresher than what apt offers and its ability to hand me a functioning build more consistent than Homebrew.

        export RAKUBREW_HOME="$HOME/.rakubrew"
        if [ -d "$RAKUBREW_HOME" ]; then addpath "$RAKUBREW_HOME/bin"; fi
        if which rakubrew > /dev/null; then eval "$(rakubrew init Zsh)"; fi
        if [ -d "$HOME/.perl6/bin" ] ; then
            addpath "$HOME/.perl6/bin"
    • Enable deno dev

      Deno sure looks interesting.

        export DENO_INSTALL="$HOME/.deno"
        if [ -d "$DENO_INSTALL" ] ; then addpath "$DENO_INSTALL/bin"; fi
    • Enable rust dev

      if [ -f "$HOME/.cargo/bin" ] ; then addpath "$HOME/.cargo/bin"; fi
  • Load aliases

    Should aliases get loaded for all sessions, or only the interactive ones? No idea yet. I’ll put it here for now.

      source "$HOME/.aliases"
  • Configure nnn

    nnn is a terminal-based file browser that I forgot all about until I was cleaning up this config.

    export NNN_FALLBACK_OPENER=xdg-open
  • Configure bat

    bat is my preferred terminal file viewer. Syntax highlighting, line numbers, git info in the gutter.

    if which bat &> /dev/null; then
       # TODO: Set up dotfiles/config/bat/config
       export BAT_THEME="TwoDark"
       export PAGER='bat'
       export MANPAGER="sh -c 'col -bx | bat -l man -p'"
  • Late local shell initialization

    Again, environment-specific stuff. Assumes everything else has been defined. A good spot for starting services.

    if [ -f "$HOME/.zshenv_local_after" ]; then
        source "$HOME/.zshenv_local_after"


Loaded for interactive sessions.

  • Set umask

    umask 002
  • Antigen bundles

    Whole lot of debate out there on the right way to extend the shell. I arbitrarily chose Antigen, but still lean on Oh My Zsh. I don’t know enough Zsh to really care about the right approach to plugins.

      source ~/antigen.zsh
      antigen use oh-my-zsh
      antigen bundle git
      antigen bundle rbenv
      antigen bundle taskwarrior
      antigen bundle tmux
      # Bundles found in the wild.
      export NVM_COMPLETION=true
      antigen bundle lukechilds/zsh-nvm
      # aesthetic bundles and theme
      antigen bundle zsh-users/zsh-syntax-highlighting
      antigen theme gozilla
      antigen apply
      # The antigen plugin seems to miss PATH_add?
      eval "$(direnv hook zsh)"
  • WSL/specific stuff

    I like to have an Xorg layer for my WSL experience.

      if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null; then
          export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0.0
          export LIBGL_ALWAYS_INDIRECT=1
  • Configure broot

    broot is another console-based file explorer. And like nnn, I don’t spend nearly enough time figuring out how to use it.

    if [ -f "$BROOT_LAUNCHER" ]; then
        source "$BROOT_LAUNCHER"
  • Start keychain

    Keychain manages SSH & GPG keys for shell sessions, so you only need to enter your managed keys once per session. Handy in both awesomewm and WSL.

    if which keychain > /dev/null; then eval `keychain --eval --agents ssh id_rsa randomgeek_rsa`; fi


Originally just .bash_aliases, but I figure I can use the same file for Zsh. Right? God I hope so.

  alias ackpy='ack --type=python'
  alias bbd='brew bundle dump --force --describe --global'
  alias be='bundle exec'
  alias dnuke='docker kill $(docker ps -q);docker system prune --all --volumes -f'
  alias e='emacs -nw'
  alias kexp='mplayer'
  alias ls='ls -hF'
  alias ll='ls -lhF'
  alias l='ls -lAhF'
  alias pr='poetry run'
  alias pri='poetry run invoke'
  alias ta='task add'
  alias tad='task add due:eod'
  alias taw='task add due:eow'
  alias tam='task add due:eom'
  alias tn='task-note'
  alias tickets='task +ticket'
  alias unflicker='xrandr --output DisplayPort-2 --mode 2560x1440 --rate 59.95'
  alias work='task +work'
  alias ymd='date +"%Y%m%d"'
Got a comment? A question? More of a comment than a question? Talk to me about this config!

Back to the config section