Skip to content

Commit 666792d

Browse files
committed
new post: habits in the shell
1 parent c8f4951 commit 666792d

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
Title: Habits in the Shell, shared
2+
Slug: habits-in-the-shell-shared
3+
Date: 2025-07-25T09:26:31.883943
4+
Tags: shell, chezmoi, habits, til
5+
Category: tools
6+
Author: Chris Rose
7+
Email: offline@offby1.net
8+
Status: published
9+
Summary: Summarize this
10+
11+
[A post I saw today](https://www.judy.co.uk/blog/using-fortune-to-reinforce-habits/) about "using `fortune` to remind me of the shell tools I have installed, instead of the old ones I use by reflex" got me really excited by the idea of the reminders.
12+
13+
I adopted the basic idea immediately -- putting the habits in `~/.local/share/habits/` and adding the fortune to my [fish shell](https://fishshell.com/) greeting. It was great!
14+
15+
But...
16+
17+
I wanted it to be shared between my machines, instead of being per-machine. That meant I needed to do some more work to tie it into [chezmoi](https://chezmoi.io/). This post covers that. I'll be using chezmoi's `run_onchange_` script support here, to adapt Judy's idea.
18+
19+
Here's what I have in chezmoi's `dot_local/share/habits/` directory:
20+
21+
```
22+
$ ll
23+
.rw-r--r--@ 670 offby1 25 Jul 08:37 0_habits
24+
.rw-r--r--@ 68 offby1 25 Jul 08:37 README.md
25+
.rw-r--r--@ 230 offby1 25 Jul 08:48 run_onchange_compile_habits.sh.tmpl
26+
```
27+
28+
The only interesting thing in there is the onchange script:
29+
30+
```{ .shell }
31+
#!/bin/bash
32+
set -eu -o pipefail
33+
34+
# Habits hash: {{ include "private_dot_local/share/habits/0_habits" | sha256sum }}
35+
36+
strfile 0_habits habits.dat
37+
# the habits file must be named "habits" for fortune to
38+
# find it
39+
mv 0_habits habits
40+
```
41+
42+
I had to work around chezmoi's ordering, which wouldn't write the `habits` file until after the on-change script was run. That meant that habits didn't update on change, only after the change. That's why `0_habits` instead of `habits`. Second, The file has to be moved into `habits` because the fortune index file needs the name to match.
43+
44+
I also added a script to add new habits, so I could do so easily; it renders as `,add-habit`[ref]Naturally, you also [start all of your commands with a comma](https://rhodesmill.org/brandon/2009/commands-with-comma/), right?[/ref] on my `PATH`:
45+
46+
```{ .shell }
47+
#!/bin/bash
48+
49+
HABIT_DIR=$HOME/.local/share/habits
50+
HABIT_FILE=$HABIT_DIR/0_habits
51+
52+
# we assume a habit file exists.
53+
54+
echo "%" >>$HABIT_FILE
55+
echo "$@" >>$HABIT_FILE
56+
57+
cd $HABIT_DIR
58+
just compile-habits
59+
```
60+
61+
<details>
62+
<summary>If you're curious, this is the full diff I applied to my dotfiles to enable this functionality, including the shell integrations[ref]and a bootstrap set of habits from Hynek. Thanks![/ref]:</summary>
63+
```{ .patch }
64+
diff --git a/dot_bashrc.tmpl b/dot_bashrc.tmpl
65+
index f6e9b806a2..c3d545c02d 100644
66+
--- a/dot_bashrc.tmpl
67+
+++ b/dot_bashrc.tmpl
68+
@@ -19,4 +19,7 @@
69+
[[ $(type -P atuin) ]] && eval "$(atuin init --disable-up-arrow bash)"
70+
71+
[[ $(type -P zoxide) ]] && eval "$(zoxide init bash)"
72+
+
73+
+fortune ~/.local/share/habits | lolcrab | boxes -d parchment
74+
+
75+
{{- end }}
76+
diff --git a/dot_config/private_fish/functions/fish_greeting.fish b/dot_config/private_fish/functions/fish_greeting.fish
77+
new file mode 100644
78+
index 0000000000..d536eff984
79+
--- /dev/null
80+
+++ b/dot_config/private_fish/functions/fish_greeting.fish
81+
@@ -0,0 +1,3 @@
82+
+function fish_greeting
83+
+ fortune ~/.local/share/habits | lolcrab | boxes -d parchment
84+
+end
85+
diff --git a/dot_zshrc.tmpl b/dot_zshrc.tmpl
86+
index 376afb6368..018de28db1 100644
87+
--- a/dot_zshrc.tmpl
88+
+++ b/dot_zshrc.tmpl
89+
@@ -50,3 +50,5 @@
90+
type -p atuin &>/dev/null && eval "$(atuin init --disable-up-arrow zsh)"
91+
92+
type -p zoxide &>/dev/null && eval "$(zoxide init zsh)"
93+
+
94+
+fortune ~/.local/share/habits | lolcrab | boxes -d parchment
95+
diff --git a/private_dot_local/bin/executable_,add-habit b/private_dot_local/bin/executable_,add-habit
96+
new file mode 100644
97+
index 0000000000..60c6165545
98+
--- /dev/null
99+
+++ b/private_dot_local/bin/executable_,add-habit
100+
@@ -0,0 +1,16 @@
101+
+#!/bin/bash
102+
+
103+
+HABIT_DIR=$HOME/.local/share/habits
104+
+HABIT_FILE=$HABIT_DIR/0_habits
105+
+
106+
+# we assume a habit file exists.
107+
+
108+
+echo "%" >>$HABIT_FILE
109+
+echo "$@" >>$HABIT_FILE
110+
+
111+
+cd $HABIT_DIR
112+
+
113+
+strfile 0_habits habits.dat
114+
+# the habits file must be named "habits" for fortune to
115+
+# find it
116+
+mv 0_habits habits
117+
diff --git a/private_dot_local/share/habits/0_habits b/private_dot_local/share/habits/0_habits
118+
new file mode 100644
119+
index 0000000000..7bb7c7b2b0
120+
--- /dev/null
121+
+++ b/private_dot_local/share/habits/0_habits
122+
@@ -0,0 +1,27 @@
123+
+make sure to add habits you like to ~/.local/share/chezmoi/private_dot_local/share/habits/habits.
124+
+%
125+
+Still using man? Try using `tldr` first!
126+
+%
127+
+Don't forget about `hexyl`! A handy binary file viewer.
128+
+%
129+
+`trippy` (started as `trip`) is the new mtr/traceroute.
130+
+%
131+
+`bandwhich` shows network usage.
132+
+%
133+
+`rlwrap` adds readline superpowers to commands that lack them.
134+
+%
135+
+`tre` is a nicer tree.
136+
+%
137+
+`dust` and `gdu-go` are nicer du replacements.
138+
+%
139+
+`hyperfine` for CLI benchmarking, `oha` for http.
140+
+%
141+
+`duf` instead of df (disk full, NOT disk usage).
142+
+%
143+
+`hurl` to stress/test HTTP.
144+
+%
145+
+`hwatch` to repeatedly run commands and compare output.
146+
+%
147+
+`dog` for better DNS.
148+
+%
149+
+`tokei` to count LoC.
150+
diff --git a/private_dot_local/share/habits/README.md b/private_dot_local/share/habits/README.md
151+
new file mode 100644
152+
index 0000000000..b06f2fcc8d
153+
--- /dev/null
154+
+++ b/private_dot_local/share/habits/README.md
155+
@@ -0,0 +1,1 @@
156+
+We use `0_habits` because chezmoi is ordering sensitive, damn it...
157+
diff --git a/private_dot_local/share/habits/run_onchange_compile_habits.sh.tmpl b/private_dot_local/share/habits/run_onchange_compile_habits.sh.tmpl
158+
new file mode 100644
159+
index 0000000000..4ad17ea927
160+
--- /dev/null
161+
+++ b/private_dot_local/share/habits/run_onchange_compile_habits.sh.tmpl
162+
@@ -0,0 +1,9 @@
163+
+#!/bin/bash
164+
+set -eu -o pipefail
165+
+
166+
+# Habits hash: {{ include "private_dot_local/share/habits/0_habits" | sha256sum }}
167+
+
168+
+strfile 0_habits habits.dat
169+
+# the habits file must be named "habits" for fortune to
170+
+# find it
171+
+mv 0_habits habits
172+
```
173+
</details>

0 commit comments

Comments
 (0)