markdown · 8242 bytes Raw Blame History

shtick

shell-agnostic-shell-configuration-generation

(noun) : something cl[ever]
(see also) : pedantic

what is this?

this is a tool I use to manage groups of shell configurations (aliases, env vars, functions). It started out written in C for a presentation on unix shells to a group of TAs. I asked an LLM to help me port it to python because I got sick of remembering about memory and waking up in cold sweats over a presentation to a bunch of 20 y/o's, and chap and I got carried away. That's the disclaimer - AI helped. But this tool is for me and I use it actively, if you think it could help you too, continue on.

It's useful if you use multiple shells regularly and would like a single source of truth for your shell ..config (...within reason).

  • Define aliases, env vars, and shell functions in one place (~/.config/shtick/config.toml)
  • Manage persistent aliases, env vars, shell functions
  • Define toggleable groups of aliases, e.g. dev, personal
  • Create, rename, and remove groups
  • Backup and restore configurations
  • Configurable behavior through settings

Shell Integration

Shtick generates shell-specific files in ~/.config/shtick/. To make them available in new shell sessions, add this to your shell config:

# ~/.bashrc or ~/.zshrc
source ~/.config/shtick/load_active.bash

# ~/.config/fish/config.fish or whatever shell you use
source ~/.config/shtick/load_active.fish

Supported Shells

bash, zsh, fish, ksh, mksh, yash, dash, csh, tcsh, xonsh, elvish, nushell, powershell, rc, es, oil

  • Run shtick shells to see the complete list.

Installation

If you decide you want to use this yourself, do all the usual cloning, then from your local clone run make install and the shtick package will be installed in your environment.

Commands reference

Core

# Add persistent items (always active)
shtick alias <key>=<value>           # Add persistent alias
shtick env <key>=<value>             # Add persistent env var
shtick function <key>=<value>        # Add persistent function

# Add to specific groups
shtick add <type> <group> <key>=<value>    # Add to specific group
shtick remove <type> <group> <key>         # Remove from group

# Group activation
shtick activate <group>              # Activate group
shtick deactivate <group>           # Deactivate group

# Information
shtick status                       # Show status
shtick list [-l]                    # List items (use -l for detailed view)
shtick shells [-l]                  # List supported shells

Group management

# Create, rename, and remove groups
shtick group create <name> [-d <description>]    # Create new group
shtick group rename <old> <new>                  # Rename group
shtick group remove <name> [-f]                  # Remove group (-f to skip confirmation)

Backup & restore

# Backup management
shtick backup create [-n <name>]     # Create backup (optional custom name)
shtick backup list                   # List available backups
shtick backup restore <name>         # Restore from backup

Settings management

# Configure shtick behavior
shtick settings init                 # Create default settings file
shtick settings show                 # Show current settings
shtick settings set <key> <value>    # Change a setting

# Available settings:
# generation.shells = []             # List of shells to generate for (empty = auto-detect)
# generation.parallel = false        # Enable parallel generation
# behavior.auto_source_prompt = true # Prompt to source after changes
# behavior.check_conflicts = true    # Warn about conflicts
# behavior.backup_on_save = false    # Auto-backup before saving

Other commands

shtick generate [--terse]           # Regenerate shell files
shtick source [--shell <shell>]     # Output source command for eval

Usage Examples

Basic Workflow

# Add some aliases
shtick alias ll='ls -la'
shtick alias gs='git status'
shtick alias gd='git diff'

Add environment variables

shtick env EDITOR='vim'
shtick env PAGER='less'

Add functions

shtick function mkcd='mkdir -p "$1" && cd "$1"'
shtick function backup='cp "$1" "$1.backup.$(date +%Y%m%d)"'

Load changes in current shell

eval "$(shtick source)"

Working with Groups

Create a work group

shtick group create work -d "Work-related configurations"

Add items to the work group

shtick add alias work deploy='./scripts/deploy.sh'
shtick add env work NODE_ENV='development'
shtick add function work vpn='sudo openvpn /etc/vpn/work.conf'

Create a personal group

shtick group create personal

Add items to personal group

shtick add alias personal myip='curl ifconfig.me'
shtick add function personal note='echo "$(date): $*" >> $HOME/notes.txt'

Activate work group

shtick activate work

Switch to personal

shtick deactivate work
shtick activate personal

Or have both active

shtick activate work
shtick activate personal
Backup and Restore  

# Create a backup before major changes
shtick backup create -n "before_refactor"

Make your changes...

shtick group remove old_stuff -f

Oops, need to restore

shtick backup restore before_refactor

Settings Customization

Initialize settings file

shtick settings init

Disable auto-source prompt

shtick settings set behavior.auto_source_prompt false

Generate for specific shells only

shtick settings set generation.shells '["bash", "zsh"]'

Enable auto-backup

shtick settings set behavior.backup_on_save true

Sample Configuration

Shtick looks for ~/.config/shtick/config.toml. Here's a sample. See also sample

# Persistent items - always active in every shell session
[persistent.aliases]
pls = "sudo !!"
bk = "- || cd -"
wttr = "curl wttr.in"
refresh = "source ${HOME}/.zshrc"
goclass = "cd ${HOME}/Documents/Class/"
goproj = "cd ${HOME}/Documents/Project/"
goorg = "cd ${HOME}/Documents/GithubOrgs/"
gad = "git add"
gall = "git add --all"
gputt = "git push origin trunk"
gcamm = "git commit --all --message"
glogg = "git log --oneline --graph --decorate --all"

[persistent.env_vars] 
PAGER = "less"
EDITOR = "micro"
BROWSER = "firefox"

[persistent.functions]
backup = "cp \"$1\" \"$1.backup.$(date +%Y%m%d_%H%M%S)\""

# Development group
[dev.aliases]
mk = "make"
mkr = "make run"
mki = "make install"
gfort = "gfortran"
ni = "npm install"
serve = "python manage.py runserver"
pyserve = "python3 -m http.server 8000"
brewup = "brew update && brew upgrade && brew cleanup"

[dev.env_vars]
DEBUG = "1"
NODE_ENV = "development"

[dev.functions]
newproject = "mkdir -p \"$HOME/projects/$1\" && cd \"$HOME/projects/$1\" && git init"

# Personal group
[personal.aliases]
myip = "curl ifconfig.me"

[personal.env_vars]
PERSONAL_NOTES = "$HOME/Documents/notes"

[personal.functions]
note = "echo \"$(date): $*\" >> $HOME/notes.txt"
todo = "echo \"[ ] $*\" >> $HOME/todo.txt"

# Work group (activate during work hours)
[work.aliases]
deploy = "./scripts/deploy.sh"
staging = "ssh staging.company.com"
prod = "ssh prod.company.com"

[work.env_vars]
AWS_PROFILE = "work"
KUBECONFIG = "$HOME/.kube/work-config"

[work.functions]
vpn = "sudo openvpn /etc/vpn/work.conf"
standup = "open https://meet.company.com/daily-standup"

Tips n. Trinkets

"Instant" sourcing alias: Add this for convenience:

shtick alias ss='eval "$(shtick source)"'
# Now you can just run 'ss' after any shtick command

Check for conflicts: Shtick warns you about duplicate items across groups:

$ shtick add alias dev ll='ls -la'
Warning: Item 'll' exists in groups: ['persistent']

Fuzzy removal: Remove items with partial matching:

shtick remove alias persistent brew  # Matches 'brewup' and offers selection

Quick status check: See what's active at a glance:

Persistent (always active): 15 items
Available Groups:
  dev: 8 items (ACTIVE)
  personal: 5 items (inactive)
  work: 12 items (ACTIVE)

Backup before removing groups:

shtick backup create -n "safe_point" && shtick group remove old_configs -f
View source
1 # shtick
2 #### shell-agnostic-shell-configuration-generation
3 (noun) : something cl[ever]
4 (see also) : pedantic
5
6 ### what is this?
7 this is a tool I use to manage groups of shell configurations (aliases, env vars, functions). It started out written in C for a presentation on unix shells to a group of TAs. I asked an LLM to help me port it to python because I got sick of remembering about memory and waking up in cold sweats over a presentation to a bunch of 20 y/o's, and chap and I got carried away. That's the disclaimer - AI helped. But this tool is for me and I use it actively, if you think it could help you too, continue on.
8
9 It's useful if you use multiple shells regularly and would like a single source of truth for your shell ..config (...within reason).
10
11 - Define aliases, env vars, and shell functions in one place (~/.config/shtick/config.toml)
12 - Manage persistent aliases, env vars, shell functions
13 - Define toggleable groups of aliases, e.g. dev, personal
14 - Create, rename, and remove groups
15 - Backup and restore configurations
16 - Configurable behavior through settings
17
18 ### Shell Integration
19 Shtick generates shell-specific files in `~/.config/shtick/`. To make them available in new shell sessions, add this to your shell config:
20
21 ```
22 # ~/.bashrc or ~/.zshrc
23 source ~/.config/shtick/load_active.bash
24
25 # ~/.config/fish/config.fish or whatever shell you use
26 source ~/.config/shtick/load_active.fish
27 ```
28
29 ### Supported Shells
30 `bash`, `zsh`, `fish`, `ksh`, `mksh`, `yash`, `dash`, `csh`, `tcsh`, `xonsh`, `elvish`, `nushell`, `powershell`, `rc`, `es`, `oil`
31 - Run `shtick shells` to see the complete list.
32
33 ### Installation
34
35 If you decide you want to use this yourself, do all the usual cloning, then from your local clone run `make install` and the `shtick` package will be installed in your environment.
36
37 ## Commands reference
38
39 #### Core
40 ```
41 # Add persistent items (always active)
42 shtick alias <key>=<value> # Add persistent alias
43 shtick env <key>=<value> # Add persistent env var
44 shtick function <key>=<value> # Add persistent function
45
46 # Add to specific groups
47 shtick add <type> <group> <key>=<value> # Add to specific group
48 shtick remove <type> <group> <key> # Remove from group
49
50 # Group activation
51 shtick activate <group> # Activate group
52 shtick deactivate <group> # Deactivate group
53
54 # Information
55 shtick status # Show status
56 shtick list [-l] # List items (use -l for detailed view)
57 shtick shells [-l] # List supported shells
58 ```
59
60 #### Group management
61 ```
62 # Create, rename, and remove groups
63 shtick group create <name> [-d <description>] # Create new group
64 shtick group rename <old> <new> # Rename group
65 shtick group remove <name> [-f] # Remove group (-f to skip confirmation)
66 ```
67
68 #### Backup & restore
69 ```
70 # Backup management
71 shtick backup create [-n <name>] # Create backup (optional custom name)
72 shtick backup list # List available backups
73 shtick backup restore <name> # Restore from backup
74 ```
75
76 #### Settings management
77 ```
78 # Configure shtick behavior
79 shtick settings init # Create default settings file
80 shtick settings show # Show current settings
81 shtick settings set <key> <value> # Change a setting
82
83 # Available settings:
84 # generation.shells = [] # List of shells to generate for (empty = auto-detect)
85 # generation.parallel = false # Enable parallel generation
86 # behavior.auto_source_prompt = true # Prompt to source after changes
87 # behavior.check_conflicts = true # Warn about conflicts
88 # behavior.backup_on_save = false # Auto-backup before saving
89 ```
90
91 #### Other commands
92 ```
93 shtick generate [--terse] # Regenerate shell files
94 shtick source [--shell <shell>] # Output source command for eval
95 ```
96
97
98 ### Usage Examples
99 #### Basic Workflow
100 ```
101 # Add some aliases
102 shtick alias ll='ls -la'
103 shtick alias gs='git status'
104 shtick alias gd='git diff'
105 ```
106
107 #### Add environment variables
108 ```
109 shtick env EDITOR='vim'
110 shtick env PAGER='less'
111 ```
112
113 #### Add functions
114 ```
115 shtick function mkcd='mkdir -p "$1" && cd "$1"'
116 shtick function backup='cp "$1" "$1.backup.$(date +%Y%m%d)"'
117 ```
118
119 #### Load changes in current shell
120 `eval "$(shtick source)"`
121
122 ### Working with Groups
123 #### Create a work group
124 `shtick group create work -d "Work-related configurations"`
125
126 #### Add items to the work group
127 ```
128 shtick add alias work deploy='./scripts/deploy.sh'
129 shtick add env work NODE_ENV='development'
130 shtick add function work vpn='sudo openvpn /etc/vpn/work.conf'
131 ```
132
133 #### Create a personal group
134 `shtick group create personal`
135
136 #### Add items to personal group
137 ```
138 shtick add alias personal myip='curl ifconfig.me'
139 shtick add function personal note='echo "$(date): $*" >> $HOME/notes.txt'
140 ```
141
142 #### Activate work group
143 `shtick activate work`
144
145 #### Switch to personal
146 ```
147 shtick deactivate work
148 shtick activate personal
149 ```
150
151 #### Or have both active
152 ```
153 shtick activate work
154 shtick activate personal
155 Backup and Restore
156
157 # Create a backup before major changes
158 shtick backup create -n "before_refactor"
159 ```
160
161 #### Make your changes...
162 `shtick group remove old_stuff -f`
163
164 #### Oops, need to restore
165 `shtick backup restore before_refactor`
166
167 ### Settings Customization
168 #### Initialize settings file
169 `shtick settings init`
170
171 #### Disable auto-source prompt
172 `shtick settings set behavior.auto_source_prompt false`
173
174 #### Generate for specific shells only
175 `shtick settings set generation.shells '["bash", "zsh"]'`
176
177 #### Enable auto-backup
178 `shtick settings set behavior.backup_on_save true`
179
180 ## Sample Configuration
181 Shtick looks for `~/.config/shtick/config.toml`. Here's a sample. See also [sample](/config.sample.toml)
182
183 ```
184 # Persistent items - always active in every shell session
185 [persistent.aliases]
186 pls = "sudo !!"
187 bk = "- || cd -"
188 wttr = "curl wttr.in"
189 refresh = "source ${HOME}/.zshrc"
190 goclass = "cd ${HOME}/Documents/Class/"
191 goproj = "cd ${HOME}/Documents/Project/"
192 goorg = "cd ${HOME}/Documents/GithubOrgs/"
193 gad = "git add"
194 gall = "git add --all"
195 gputt = "git push origin trunk"
196 gcamm = "git commit --all --message"
197 glogg = "git log --oneline --graph --decorate --all"
198
199 [persistent.env_vars]
200 PAGER = "less"
201 EDITOR = "micro"
202 BROWSER = "firefox"
203
204 [persistent.functions]
205 backup = "cp \"$1\" \"$1.backup.$(date +%Y%m%d_%H%M%S)\""
206
207 # Development group
208 [dev.aliases]
209 mk = "make"
210 mkr = "make run"
211 mki = "make install"
212 gfort = "gfortran"
213 ni = "npm install"
214 serve = "python manage.py runserver"
215 pyserve = "python3 -m http.server 8000"
216 brewup = "brew update && brew upgrade && brew cleanup"
217
218 [dev.env_vars]
219 DEBUG = "1"
220 NODE_ENV = "development"
221
222 [dev.functions]
223 newproject = "mkdir -p \"$HOME/projects/$1\" && cd \"$HOME/projects/$1\" && git init"
224
225 # Personal group
226 [personal.aliases]
227 myip = "curl ifconfig.me"
228
229 [personal.env_vars]
230 PERSONAL_NOTES = "$HOME/Documents/notes"
231
232 [personal.functions]
233 note = "echo \"$(date): $*\" >> $HOME/notes.txt"
234 todo = "echo \"[ ] $*\" >> $HOME/todo.txt"
235
236 # Work group (activate during work hours)
237 [work.aliases]
238 deploy = "./scripts/deploy.sh"
239 staging = "ssh staging.company.com"
240 prod = "ssh prod.company.com"
241
242 [work.env_vars]
243 AWS_PROFILE = "work"
244 KUBECONFIG = "$HOME/.kube/work-config"
245
246 [work.functions]
247 vpn = "sudo openvpn /etc/vpn/work.conf"
248 standup = "open https://meet.company.com/daily-standup"
249 ```
250
251 ### Tips n. Trinkets
252
253
254 #### "Instant" sourcing alias: Add this for convenience:
255 ```
256 shtick alias ss='eval "$(shtick source)"'
257 # Now you can just run 'ss' after any shtick command
258 ```
259
260 #### Check for conflicts: Shtick warns you about duplicate items across groups:
261 ```
262 $ shtick add alias dev ll='ls -la'
263 Warning: Item 'll' exists in groups: ['persistent']
264 ```
265
266 #### Fuzzy removal: Remove items with partial matching:
267 ```
268 shtick remove alias persistent brew # Matches 'brewup' and offers selection
269 ```
270
271 #### Quick status check: See what's active at a glance:
272 ```$ shtick status
273 Persistent (always active): 15 items
274 Available Groups:
275 dev: 8 items (ACTIVE)
276 personal: 5 items (inactive)
277 work: 12 items (ACTIVE)
278 ```
279 #### Backup before removing groups:
280 ```
281 shtick backup create -n "safe_point" && shtick group remove old_configs -f
282 ```