<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Toolian</title><link>https://toolian.metacog.co.kr/</link><description>Recent content on Toolian</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Wed, 19 Aug 2026 10:17:08 -0500</lastBuildDate><atom:link href="https://toolian.metacog.co.kr/index.xml" rel="self" type="application/rss+xml"/><item><title>Choosing a Tool</title><link>https://toolian.metacog.co.kr/docs/getting-started/choosing-tools/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/getting-started/choosing-tools/</guid><description>&lt;p&gt;Adding tools is not productivity by itself. Each one costs installation, configuration,
learning, and maintenance, and the more you have, the more you have to explain to your
team. Run through these six questions before adopting anything and you&amp;rsquo;ll avoid most
of the regret.&lt;/p&gt;
&lt;h2 id="six-questions"&gt;Six questions &lt;a href="#six-questions" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Question&lt;/th&gt;
 &lt;th&gt;Passing answer&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;How often do I do this?&lt;/td&gt;
 &lt;td&gt;At least three times a day, or 30+ minutes even once a week&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Can my current tools do it?&lt;/td&gt;
 &lt;td&gt;If an unused feature of something you already run covers it, start there&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;What&amp;rsquo;s the learning cost?&lt;/td&gt;
 &lt;td&gt;If you get a first win within 30 minutes, it passes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Is anyone else forced into it?&lt;/td&gt;
 &lt;td&gt;A tool only you use is far easier to adopt than a team standard&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Can I get back out?&lt;/td&gt;
 &lt;td&gt;Can the data be exported as text, Markdown, or JSON?&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Is the project alive?&lt;/td&gt;
 &lt;td&gt;A release in the last six months, and issues that get replies&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="suggested-order-of-adoption"&gt;Suggested order of adoption &lt;a href="#suggested-order-of-adoption" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Personal tools first.&lt;/strong&gt; Terminal, search, editor — things that start and end with
you. Cheap to reverse, and you feel the benefit daily.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Team tools next.&lt;/strong&gt; CI, linters, hooks — anything that affects other people. Prove
it as a personal tool before proposing it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platform tools last.&lt;/strong&gt; Orchestration and IaC carry the highest cost to undo.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="common-traps"&gt;Common traps &lt;a href="#common-traps" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Configuration perfectionism.&lt;/strong&gt; Instead of spending two hours on a prompt theme,
run the defaults for a week and fix only what actually annoyed you.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Leaving duplicates around.&lt;/strong&gt; Two tools doing the same job means you will never
remember which config you edited. Once a new one sticks, delete the old one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Undocumented aliases.&lt;/strong&gt; A pile of aliases only you know leaves you helpless on
anyone else&amp;rsquo;s machine. Scripts you share should use the real commands.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="next"&gt;Next &lt;a href="#next" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;With a bar in place, move on to
&lt;a data-bs-delay="{&amp;#34;hide&amp;#34;:300,&amp;#34;show&amp;#34;:550}" data-bs-html="true" data-bs-title="&lt;a href='https://toolian.metacog.co.kr/docs/getting-started/package-managers/'&gt;&lt;p&gt;GETTING STARTED&lt;/p&gt;</description></item><item><title>Package Managers</title><link>https://toolian.metacog.co.kr/docs/getting-started/package-managers/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/getting-started/package-managers/</guid><description>&lt;p&gt;Every install command in the rest of this site assumes a package manager. Downloading
installers from websites makes updates and removals awkward, and leaves you with no
record of what you installed.&lt;/p&gt;
&lt;h2 id="macos--homebrew"&gt;macOS — Homebrew &lt;a href="#macos--homebrew" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;One line to install:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="5329f6a" class="language-bash "&gt;
 &lt;code&gt;/bin/bash -c &amp;#34;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&amp;#34;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Goal&lt;/th&gt;
 &lt;th&gt;Command&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Install a CLI tool&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;brew install ripgrep&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Install a GUI app&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;brew install --cask visual-studio-code&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Search&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;brew search fzf&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Show details&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;brew info jq&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Update everything&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;brew update &amp;amp;&amp;amp; brew upgrade&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Remove&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;brew uninstall ripgrep&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;List installs&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;brew leaves&lt;/code&gt; (only what you asked for)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="windows--winget"&gt;Windows — winget &lt;a href="#windows--winget" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Bundled since Windows 10. If it&amp;rsquo;s missing, install &amp;ldquo;App Installer&amp;rdquo; from the Microsoft
Store.&lt;/p&gt;</description></item><item><title>Dotfiles</title><link>https://toolian.metacog.co.kr/docs/getting-started/dotfiles/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/getting-started/dotfiles/</guid><description>&lt;p&gt;Configuration files whose names start with a dot — &lt;code&gt;.zshrc&lt;/code&gt;, &lt;code&gt;.gitconfig&lt;/code&gt;, your editor
settings — are collectively called dotfiles. Gather them into one Git repository and
setting up a new machine takes minutes, and &amp;ldquo;the setup that used to work&amp;rdquo; is always
recoverable.&lt;/p&gt;
&lt;h2 id="the-simplest-approach-a-repo-plus-symlinks"&gt;The simplest approach: a repo plus symlinks &lt;a href="#the-simplest-approach-a-repo-plus-symlinks" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="a00fecc" class="language-bash "&gt;
 &lt;code&gt;mkdir -p ~/dotfiles &amp;amp;&amp;amp; cd ~/dotfiles
git init

# move the real file into the repo, leave a link where it was
mv ~/.zshrc ~/dotfiles/zshrc
ln -s ~/dotfiles/zshrc ~/.zshrc

mv ~/.gitconfig ~/dotfiles/gitconfig
ln -s ~/dotfiles/gitconfig ~/.gitconfig

git add -A &amp;amp;&amp;amp; git commit -m &amp;#34;Start dotfiles&amp;#34;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;On a new machine, clone and re-link:&lt;/p&gt;</description></item><item><title>Choosing a Terminal</title><link>https://toolian.metacog.co.kr/docs/terminal/terminal-apps/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/terminal/terminal-apps/</guid><description>&lt;p&gt;A terminal app is the window your shell lives in. A better window doesn&amp;rsquo;t make commands
run faster, but easier tabs, splits, search, and copy keep you from losing your thread.&lt;/p&gt;
&lt;h2 id="the-options"&gt;The options &lt;a href="#the-options" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;App&lt;/th&gt;
 &lt;th&gt;Platform&lt;/th&gt;
 &lt;th&gt;Character&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;iTerm2&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;macOS&lt;/td&gt;
 &lt;td&gt;The long-standing default. Splits, search, session restore, triggers — the most features&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Ghostty&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;macOS/Linux&lt;/td&gt;
 &lt;td&gt;GPU-accelerated and very fast. Configuration is a single text file&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Windows Terminal&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Windows&lt;/td&gt;
 &lt;td&gt;Tabs and splits, with WSL, PowerShell, and cmd in one window&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Warp&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;macOS/Linux/Windows&lt;/td&gt;
 &lt;td&gt;Block-based output and AI command suggestions. Requires an account&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Built-in terminal&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Everywhere&lt;/td&gt;
 &lt;td&gt;Light and always present. Splits and search are the weak points&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Starting out, iTerm2 or Ghostty on macOS and Windows Terminal on Windows are safe picks.&lt;/p&gt;</description></item><item><title>zsh and Starship</title><link>https://toolian.metacog.co.kr/docs/terminal/zsh-starship/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/terminal/zsh-starship/</guid><description>&lt;p&gt;Your prompt is a status bar answering &lt;em&gt;where am I and what am I doing?&lt;/em&gt; Being able to
see the current branch or Python virtualenv at a glance cuts out a lot of &lt;code&gt;git branch&lt;/code&gt;
and &lt;code&gt;which python&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="baseline-zsh-settings"&gt;Baseline zsh settings &lt;a href="#baseline-zsh-settings" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;zsh is the default shell on macOS. To switch on Linux:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="7031d87" class="language-bash "&gt;
 &lt;code&gt;sudo apt install zsh
chsh -s $(which zsh)&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;These lines in &lt;code&gt;~/.zshrc&lt;/code&gt; make the biggest difference:&lt;/p&gt;</description></item><item><title>tmux</title><link>https://toolian.metacog.co.kr/docs/terminal/tmux/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/terminal/tmux/</guid><description>&lt;p&gt;tmux is a window manager that runs inside your terminal. Its two biggest wins are that
&lt;strong&gt;work continues when your SSH connection drops&lt;/strong&gt; and that &lt;strong&gt;a whole set of tasks can be
saved and brought back&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="install-and-first-run"&gt;Install and first run &lt;a href="#install-and-first-run" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="d4ff30e" class="language-bash "&gt;
 &lt;code&gt;brew install tmux # macOS
sudo apt install tmux # Ubuntu/Debian

tmux new -s work # start a session named &amp;#34;work&amp;#34;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;To leave a session, press &lt;code&gt;Ctrl+B&lt;/code&gt; then &lt;code&gt;d&lt;/code&gt; (detach). Whatever was running on the
server keeps running. To come back:&lt;/p&gt;</description></item><item><title>fzf</title><link>https://toolian.metacog.co.kr/docs/terminal/fzf/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/terminal/fzf/</guid><description>&lt;p&gt;fzf takes a list and lets a human pick from it. Because it doesn&amp;rsquo;t care what the list
is, it attaches to history, files, Git branches, processes, Docker containers —
anything.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="8093c22" class="language-bash "&gt;
 &lt;code&gt;brew install fzf
$(brew --prefix)/opt/fzf/install # install the shell key bindings (answer y)&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="3de7756" class="language-bash "&gt;
 &lt;code&gt;sudo apt install fzf&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="three-keys-you-get-for-free"&gt;Three keys you get for free &lt;a href="#three-keys-you-get-for-free" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Key&lt;/th&gt;
 &lt;th&gt;Action&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+R&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Fuzzy-search command history (replaces the default reverse search)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+T&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Pick a file under the current directory and insert its path&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Alt+C&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Pick a subdirectory and &lt;code&gt;cd&lt;/code&gt; into it&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;Ctrl+R&lt;/code&gt; is the one you feel immediately. That long &lt;code&gt;docker run ...&lt;/code&gt; from last month
comes back with two words.&lt;/p&gt;</description></item><item><title>zoxide</title><link>https://toolian.metacog.co.kr/docs/terminal/zoxide/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/terminal/zoxide/</guid><description>&lt;p&gt;If you type &lt;code&gt;cd ~/work/projects/backend/services/auth&lt;/code&gt; several times a day, zoxide
shortens it to &lt;code&gt;z auth&lt;/code&gt;. It scores directories you&amp;rsquo;ve visited by frequency and recency
and sends you to the most plausible one.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="4d13ccf" class="language-bash "&gt;
 &lt;code&gt;brew install zoxide&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="738e93b" class="language-bash "&gt;
 &lt;code&gt;curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Hook it into your shell:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="a4b91b6" class="language-bash "&gt;
 &lt;code&gt;# ~/.zshrc
eval &amp;#34;$(zoxide init zsh)&amp;#34;

# bash
eval &amp;#34;$(zoxide init bash)&amp;#34;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;To replace &lt;code&gt;cd&lt;/code&gt; outright:&lt;/p&gt;</description></item><item><title>ripgrep</title><link>https://toolian.metacog.co.kr/docs/files/ripgrep/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/files/ripgrep/</guid><description>&lt;p&gt;&lt;code&gt;rg&lt;/code&gt; is the tool with the most sensible defaults for searching a whole project. It
skips &lt;code&gt;node_modules&lt;/code&gt; and &lt;code&gt;.git&lt;/code&gt; on its own and uses every core you have.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="62877c4" class="language-bash "&gt;
 &lt;code&gt;brew install ripgrep # macOS
sudo apt install ripgrep # Ubuntu 18.10&amp;#43;
winget install BurntSushi.ripgrep.MSVC&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="basics"&gt;Basics &lt;a href="#basics" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="4a63021" class="language-bash "&gt;
 &lt;code&gt;rg &amp;#34;createUser&amp;#34; # search the whole current directory
rg &amp;#34;createUser&amp;#34; src/ # limit to a directory
rg -i &amp;#34;createuser&amp;#34; # case insensitive
rg -w &amp;#34;id&amp;#34; # whole word (won&amp;#39;t match &amp;#34;identity&amp;#34;)
rg -F &amp;#34;a.b.c&amp;#34; # literal string, not a regex&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="options-worth-knowing"&gt;Options worth knowing &lt;a href="#options-worth-knowing" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Option&lt;/th&gt;
 &lt;th&gt;Meaning&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-t py&lt;/code&gt; / &lt;code&gt;-t js&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Only files of a language (&lt;code&gt;rg --type-list&lt;/code&gt; for the full set)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-T test&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Exclude a type&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-g '*.md'&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Include by glob&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-g '!dist/*'&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Exclude by glob&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-l&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Print filenames only&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-c&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Count matches per file&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-n&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Line numbers (on by default)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-A 3&lt;/code&gt; / &lt;code&gt;-B 3&lt;/code&gt; / &lt;code&gt;-C 3&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Context lines after / before / both&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--hidden&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Include hidden files&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-u&lt;/code&gt; / &lt;code&gt;-uu&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Relax / ignore the ignore rules&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="in-practice"&gt;In practice &lt;a href="#in-practice" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="adb7fc3" class="language-bash "&gt;
 &lt;code&gt;# rank files by how many TODOs they carry
rg -c &amp;#34;TODO&amp;#34; | sort -t: -k2 -rn | head

# find env var usage with context
rg -C 2 &amp;#34;process\.env\.&amp;#34; -t ts

# find declarations only
rg &amp;#34;^(export )?(async )?function \w&amp;#43;&amp;#34; -t ts

# search, then replace across the matches (needs sd)
rg -l &amp;#34;oldName&amp;#34; | xargs sd &amp;#34;oldName&amp;#34; &amp;#34;newName&amp;#34;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="replacing-text"&gt;Replacing text &lt;a href="#replacing-text" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;ripgrep itself only previews replacements.&lt;/p&gt;</description></item><item><title>fd</title><link>https://toolian.metacog.co.kr/docs/files/fd/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/files/fd/</guid><description>&lt;p&gt;You don&amp;rsquo;t have to remember
&lt;code&gt;find . -name &amp;quot;*.log&amp;quot; -type f -not -path &amp;quot;*/node_modules/*&amp;quot;&lt;/code&gt;. In most cases &lt;code&gt;fd log&lt;/code&gt;
covers it.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="9d38f64" class="language-bash "&gt;
 &lt;code&gt;brew install fd
sudo apt install fd-find # the binary is called fdfind
winget install sharkdp.fd&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;On Ubuntu, alias it:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="9b7bd05" class="language-bash "&gt;
 &lt;code&gt;alias fd=fdfind&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="basics"&gt;Basics &lt;a href="#basics" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="d8ed588" class="language-bash "&gt;
 &lt;code&gt;fd config # anything with &amp;#34;config&amp;#34; in the name
fd -e md # files with the .md extension
fd -e md -e mdx docs/ # several extensions, in one directory
fd -H secret # include hidden files
fd -t d node_modules # directories only&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="options-worth-knowing"&gt;Options worth knowing &lt;a href="#options-worth-knowing" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Option&lt;/th&gt;
 &lt;th&gt;Meaning&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-e &amp;lt;ext&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Filter by extension&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-t f&lt;/code&gt; / &lt;code&gt;-t d&lt;/code&gt; / &lt;code&gt;-t l&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Files / directories / symlinks&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-H&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Include hidden files&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-I&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Ignore &lt;code&gt;.gitignore&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-d 2&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Limit search depth&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Case sensitive&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--changed-within 1d&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Modified in the last day&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-x &amp;lt;cmd&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Run a command per result&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-X &amp;lt;cmd&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Pass all results to one command&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="acting-on-what-you-find"&gt;Acting on what you find &lt;a href="#acting-on-what-you-find" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="4b8e0f6" class="language-bash "&gt;
 &lt;code&gt;# convert every png to webp
fd -e png -x cwebp {} -o {.}.webp

# delete logs older than 30 days (list them first!)
fd -e log --changed-before 30d
fd -e log --changed-before 30d -X rm

# locate every package.json
fd -H &amp;#39;^package\.json$&amp;#39; -t f&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;code&gt;{}&lt;/code&gt; is the path, &lt;code&gt;{.}&lt;/code&gt; is the path without its extension, and &lt;code&gt;{/}&lt;/code&gt; is the basename.&lt;/p&gt;</description></item><item><title>bat</title><link>https://toolian.metacog.co.kr/docs/files/bat/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/files/bat/</guid><description>&lt;p&gt;&lt;code&gt;cat&lt;/code&gt; on a 200-line config file dumps a monochrome wall of text. &lt;code&gt;bat&lt;/code&gt; shows the same
file with syntax highlighting, line numbers, and paging.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="3440a78" class="language-bash "&gt;
 &lt;code&gt;brew install bat
sudo apt install bat # the binary is called batcat
winget install sharkdp.bat&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="e0587f3" class="language-bash "&gt;
 &lt;code&gt;alias bat=batcat # Ubuntu&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="basics"&gt;Basics &lt;a href="#basics" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="90dff71" class="language-bash "&gt;
 &lt;code&gt;bat config.yaml # highlighting &amp;#43; line numbers &amp;#43; pager
bat -n script.sh # line numbers only, no header
bat -p log.txt # plain, no decorations
bat -r 40:80 main.go # only lines 40–80
bat -A data.txt # show spaces, tabs, and newlines&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="combining-with-other-commands"&gt;Combining with other commands &lt;a href="#combining-with-other-commands" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="3019efc" class="language-bash "&gt;
 &lt;code&gt;# read from a pipe and name the language
curl -s https://api.example.com/data | bat -l json

# colourise a list of changed files
git diff --name-only | xargs bat

# use it as your default pager
export PAGER=&amp;#34;bat -p&amp;#34;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;The most common pairing is as an &lt;code&gt;fzf&lt;/code&gt; preview:&lt;/p&gt;</description></item><item><title>eza</title><link>https://toolian.metacog.co.kr/docs/files/eza/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/files/eza/</guid><description>&lt;p&gt;&lt;code&gt;ls -alh&lt;/code&gt; gives you plenty of information and very little structure. &lt;code&gt;eza&lt;/code&gt; presents the
same data with colour and alignment, and adds tree view and Git status on top.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="1c7beaf" class="language-bash "&gt;
 &lt;code&gt;brew install eza
sudo apt install eza # Ubuntu 24.04&amp;#43;
cargo install eza # elsewhere&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="basics"&gt;Basics &lt;a href="#basics" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="861cf7f" class="language-bash "&gt;
 &lt;code&gt;eza # plain listing
eza -l # long form (permissions, size, mtime)
eza -la # include hidden files
eza -l --git # add a Git status column
eza --tree --level=2 # two levels of tree
eza -l --sort=modified --reverse # most recently changed first&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="options-worth-knowing"&gt;Options worth knowing &lt;a href="#options-worth-knowing" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Option&lt;/th&gt;
 &lt;th&gt;Meaning&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-l&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Long listing&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Include hidden files&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-T&lt;/code&gt; / &lt;code&gt;--tree&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Tree view&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--level=N&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Tree depth&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--git&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Git status column&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--icons&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;File-type icons (needs a Nerd Font)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--group-directories-first&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Directories on top&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-s size&lt;/code&gt; / &lt;code&gt;-s modified&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Sort key&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--total-size&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Compute real directory sizes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="suggested-aliases"&gt;Suggested aliases &lt;a href="#suggested-aliases" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="020309e" class="language-bash "&gt;
 &lt;code&gt;# ~/.zshrc
alias ls=&amp;#39;eza --group-directories-first&amp;#39;
alias ll=&amp;#39;eza -l --git --group-directories-first&amp;#39;
alias la=&amp;#39;eza -la --git --group-directories-first&amp;#39;
alias lt=&amp;#39;eza --tree --level=2 --group-directories-first&amp;#39;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;If overriding &lt;code&gt;ls&lt;/code&gt; makes you nervous, alias only &lt;code&gt;l&lt;/code&gt; and &lt;code&gt;ll&lt;/code&gt; and leave &lt;code&gt;ls&lt;/code&gt; alone —
scripts that parse &lt;code&gt;ls&lt;/code&gt; output can break.&lt;/p&gt;</description></item><item><title>jq</title><link>https://toolian.metacog.co.kr/docs/files/jq/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/files/jq/</guid><description>&lt;p&gt;If you have ever scanned an API response by eye and missed the field you needed, &lt;code&gt;jq&lt;/code&gt;
is the answer. It pretty-prints JSON, extracts the parts you want, and reshapes them.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="e815b60" class="language-bash "&gt;
 &lt;code&gt;brew install jq
sudo apt install jq
winget install jqlang.jq&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="basics"&gt;Basics &lt;a href="#basics" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="517dc36" class="language-bash "&gt;
 &lt;code&gt;# pretty-print
curl -s https://api.github.com/repos/jeonck/toolian | jq

# one field
jq &amp;#39;.name&amp;#39; repo.json

# a nested field
jq &amp;#39;.owner.login&amp;#39; repo.json

# iterate an array
jq &amp;#39;.[] | .name&amp;#39; repos.json

# build a new object
jq &amp;#39;.[] | {name, stars: .stargazers_count}&amp;#39; repos.json&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="filters-worth-knowing"&gt;Filters worth knowing &lt;a href="#filters-worth-knowing" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Filter&lt;/th&gt;
 &lt;th&gt;Meaning&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;The whole input&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.foo&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A field&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.foo?&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;null instead of an error when missing&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.[]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Iterate an array or object&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.[2:5]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Array slice&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;|&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Pipe one filter into the next&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;select(cond)&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Keep matching items&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;map(expr)&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Apply to each array element&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;length&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Length&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;keys&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Key list&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;sort_by(.field)&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Sort&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;group_by(.field)&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Group&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-r&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Raw output, no quotes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="in-practice"&gt;In practice &lt;a href="#in-practice" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="6486e7e" class="language-bash "&gt;
 &lt;code&gt;# names of repos with more than 100 stars
jq -r &amp;#39;.[] | select(.stargazers_count &amp;gt; 100) | .name&amp;#39; repos.json

# array to CSV
jq -r &amp;#39;.[] | [.name, .language, .stargazers_count] | @csv&amp;#39; repos.json

# count by status code
jq -r &amp;#39;.[].status&amp;#39; logs.json | sort | uniq -c | sort -rn

# edit a value into a new file
jq &amp;#39;.version = &amp;#34;2.0.0&amp;#34;&amp;#39; package.json &amp;gt; tmp &amp;amp;&amp;amp; mv tmp package.json

# merge two files
jq -s &amp;#39;.[0] * .[1]&amp;#39; base.json override.json&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="using-it-safely"&gt;Using it safely &lt;a href="#using-it-safely" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Never overwrite in place&lt;/strong&gt;: &lt;code&gt;jq ... file.json &amp;gt; file.json&lt;/code&gt; truncates the file. Use
a temp file, or &lt;code&gt;sponge&lt;/code&gt; from moreutils.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Missing keys&lt;/strong&gt;: &lt;code&gt;.a.b&lt;/code&gt; errors when &lt;code&gt;a&lt;/code&gt; is absent. Guard with &lt;code&gt;.a?.b?&lt;/code&gt; or
&lt;code&gt;// &amp;quot;default&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Debugging&lt;/strong&gt;: for a long filter, run it one pipe stage at a time — you&amp;rsquo;ll find the
culprit much faster.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="for-yaml-too"&gt;For YAML too &lt;a href="#for-yaml-too" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="ccf5c2d" class="language-bash "&gt;
 &lt;code&gt;brew install yq
yq &amp;#39;.services.web.image&amp;#39; docker-compose.yml
yq -o=json &amp;#39;.&amp;#39; config.yaml | jq&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="next"&gt;Next &lt;a href="#next" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;With files under control, on to where you write the code →
&lt;a data-bs-delay="{&amp;#34;hide&amp;#34;:300,&amp;#34;show&amp;#34;:550}" data-bs-html="true" data-bs-title="&lt;a href='https://toolian.metacog.co.kr/docs/editor/'&gt;&lt;p&gt;OVERVIEW&lt;/p&gt;</description></item><item><title>VS Code</title><link>https://toolian.metacog.co.kr/docs/editor/vscode/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/editor/vscode/</guid><description>&lt;p&gt;VS Code is language-agnostic and filled in with extensions. Settings are easy to share
with a team, and most tutorials are written against it, which makes it a good first
editor.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="93722ca" class="language-bash "&gt;
 &lt;code&gt;brew install --cask visual-studio-code
winget install Microsoft.VisualStudioCode&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;To use &lt;code&gt;code .&lt;/code&gt; from a terminal, run
&lt;code&gt;Shell Command: Install 'code' command in PATH&lt;/code&gt; from the command palette
(&lt;code&gt;⌘⇧P&lt;/code&gt; / &lt;code&gt;Ctrl+Shift+P&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id="six-shortcuts-to-learn-first"&gt;Six shortcuts to learn first &lt;a href="#six-shortcuts-to-learn-first" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Action&lt;/th&gt;
 &lt;th&gt;macOS&lt;/th&gt;
 &lt;th&gt;Windows/Linux&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Command palette&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘⇧P&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+Shift+P&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Quick open a file&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘P&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+P&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Go to symbol&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘⇧O&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+Shift+O&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Search everywhere&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘⇧F&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+Shift+F&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Multi-cursor (same word)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘D&lt;/code&gt; repeatedly&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+D&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Move a line&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌥↑&lt;/code&gt; / &lt;code&gt;⌥↓&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Alt+↑&lt;/code&gt; / &lt;code&gt;Alt+↓&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Knowing the command palette alone lets you find everything else by name.&lt;/p&gt;</description></item><item><title>Neovim</title><link>https://toolian.metacog.co.kr/docs/editor/neovim/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/editor/neovim/</guid><description>&lt;p&gt;The real advantage of Neovim isn&amp;rsquo;t raw speed — it&amp;rsquo;s that &lt;strong&gt;it exists on every server
and your hands never leave the home row&lt;/strong&gt;. If you edit files over SSH regularly, the
basics alone pay for themselves.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="7ce6f48" class="language-bash "&gt;
 &lt;code&gt;brew install neovim
sudo apt install neovim
winget install Neovim.Neovim&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="survival-commands"&gt;Survival commands &lt;a href="#survival-commands" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;First, remove the possibility of being trapped in it.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Command&lt;/th&gt;
 &lt;th&gt;Action&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Esc&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Back to normal mode (when in doubt, start here)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;i&lt;/code&gt; / &lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Insert before / after the cursor&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;:w&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Save&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;:q&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Quit&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;:wq&lt;/code&gt; or &lt;code&gt;ZZ&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Save and quit&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;:q!&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Quit, discarding changes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="moving-and-editing"&gt;Moving and editing &lt;a href="#moving-and-editing" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Key&lt;/th&gt;
 &lt;th&gt;Action&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;h j k l&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Left, down, up, right&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;w&lt;/code&gt; / &lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Next / previous word&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;0&lt;/code&gt; / &lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Start / end of line&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;gg&lt;/code&gt; / &lt;code&gt;G&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Start / end of file&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;{n}G&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Go to line n&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;dd&lt;/code&gt; / &lt;code&gt;yy&lt;/code&gt; / &lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Delete / yank / paste a line&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;u&lt;/code&gt; / &lt;code&gt;Ctrl+r&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Undo / redo&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;/text&lt;/code&gt; then &lt;code&gt;n&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Search, then next match&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;:%s/old/new/g&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Replace throughout the file&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Vim&amp;rsquo;s grammar is &lt;strong&gt;verb + object&lt;/strong&gt;. &lt;code&gt;d&lt;/code&gt; (delete) + &lt;code&gt;w&lt;/code&gt; (word) is &lt;code&gt;dw&lt;/code&gt;; &lt;code&gt;c&lt;/code&gt; (change) +
&lt;code&gt;i&amp;quot;&lt;/code&gt; (inside quotes) is &lt;code&gt;ci&amp;quot;&lt;/code&gt;. Once that composition clicks, there is far less to
memorise.&lt;/p&gt;</description></item><item><title>JetBrains IDEs</title><link>https://toolian.metacog.co.kr/docs/editor/jetbrains/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/editor/jetbrains/</guid><description>&lt;p&gt;JetBrains IDEs understand code as &lt;strong&gt;structure&lt;/strong&gt;, not text. That makes renaming,
extracting methods, and tracing usages exact. The advantage is largest on big projects
and statically typed languages.&lt;/p&gt;
&lt;h2 id="picking-a-product"&gt;Picking a product &lt;a href="#picking-a-product" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Product&lt;/th&gt;
 &lt;th&gt;Primary language&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;IntelliJ IDEA&lt;/td&gt;
 &lt;td&gt;Java, Kotlin, Scala&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;PyCharm&lt;/td&gt;
 &lt;td&gt;Python&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;GoLand&lt;/td&gt;
 &lt;td&gt;Go&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;WebStorm&lt;/td&gt;
 &lt;td&gt;JavaScript, TypeScript&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;DataGrip&lt;/td&gt;
 &lt;td&gt;SQL, databases&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Rider&lt;/td&gt;
 &lt;td&gt;.NET, C#&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If you move between many languages, IntelliJ IDEA Ultimate plus plugins covers most of
it. Install and manage versions through &lt;strong&gt;JetBrains Toolbox&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>Editing Skills</title><link>https://toolian.metacog.co.kr/docs/editor/editing-skills/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/editor/editing-skills/</guid><description>&lt;p&gt;You change editors every few years; these techniques come with you. They have the most
reliable return on investment of anything here.&lt;/p&gt;
&lt;h2 id="multi-cursor"&gt;Multi-cursor &lt;a href="#multi-cursor" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;For repeating the same edit across several lines.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Action&lt;/th&gt;
 &lt;th&gt;VS Code&lt;/th&gt;
 &lt;th&gt;JetBrains&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Add next occurrence&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘D&lt;/code&gt; / &lt;code&gt;Ctrl+D&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌃G&lt;/code&gt; / &lt;code&gt;Alt+J&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Select all occurrences&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘⇧L&lt;/code&gt; / &lt;code&gt;Ctrl+Shift+L&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌃⌘G&lt;/code&gt; / &lt;code&gt;Ctrl+Alt+Shift+J&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Add cursor above/below&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌥⌘↑↓&lt;/code&gt; / &lt;code&gt;Ctrl+Alt+↑↓&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌥⌥↑↓&lt;/code&gt; (Alt twice)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Add cursor anywhere&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌥click&lt;/code&gt; / &lt;code&gt;Alt+click&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Same&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Typical uses: quoting ten list items at once, or fixing several import statements
simultaneously.&lt;/p&gt;</description></item><item><title>Claude Code</title><link>https://toolian.metacog.co.kr/docs/ai/claude-code/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/ai/claude-code/</guid><description>&lt;p&gt;Claude Code is not autocomplete — it&amp;rsquo;s something you &lt;strong&gt;hand a task to&lt;/strong&gt;. &amp;ldquo;Find and fix
the cause of this bug&amp;rdquo;, &amp;ldquo;add tests for this folder&amp;rdquo;: work that spans several files, it
explores and edits on its own.&lt;/p&gt;
&lt;h2 id="install-and-run"&gt;Install and run &lt;a href="#install-and-run" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="fb72fea" class="language-bash "&gt;
 &lt;code&gt;npm install -g @anthropic-ai/claude-code
cd ~/projects/my-app
claude&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Besides the terminal, it&amp;rsquo;s available as a desktop app (Mac/Windows), on the web
(claude.ai/code), and as VS Code and JetBrains extensions.&lt;/p&gt;</description></item><item><title>GitHub Copilot</title><link>https://toolian.metacog.co.kr/docs/ai/copilot/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/ai/copilot/</guid><description>&lt;p&gt;Copilot greys in the code it thinks follows your cursor. It doesn&amp;rsquo;t roam a project the
way an agent does, but by &lt;strong&gt;sheer frequency of small time savings&lt;/strong&gt; it&amp;rsquo;s the form of
assistance that helps most often.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Install the &lt;code&gt;GitHub Copilot&lt;/code&gt; extension from the VS Code marketplace and sign in with
your GitHub account. Plugins exist for JetBrains, Neovim, and Visual Studio too.&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="00abf30" class="language-bash "&gt;
 &lt;code&gt;# Neovim
git clone https://github.com/github/copilot.vim \
 ~/.config/nvim/pack/github/start/copilot.vim
# then run :Copilot setup&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="basic-controls"&gt;Basic controls &lt;a href="#basic-controls" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Action&lt;/th&gt;
 &lt;th&gt;Key&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Accept the suggestion&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Tab&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Dismiss it&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Esc&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Next / previous suggestion&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌥]&lt;/code&gt; / &lt;code&gt;⌥[&lt;/code&gt; (Alt)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Open several in a panel&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌃⏎&lt;/code&gt; (Ctrl+Enter)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Inline chat&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘I&lt;/code&gt; / &lt;code&gt;Ctrl+I&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="getting-better-suggestions"&gt;Getting better suggestions &lt;a href="#getting-better-suggestions" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Copilot predicts from &lt;strong&gt;surrounding context&lt;/strong&gt;, so the clearer that is, the more accurate
it gets.&lt;/p&gt;</description></item><item><title>Cursor</title><link>https://toolian.metacog.co.kr/docs/ai/cursor/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/ai/cursor/</guid><description>&lt;p&gt;Cursor forks VS Code and promotes AI features into the core workflow. Because it keeps
most VS Code extensions, keymaps, and settings, the cost of switching is low.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="51e6da1" class="language-bash "&gt;
 &lt;code&gt;brew install --cask cursor&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;On first launch it offers to import your VS Code setup — extensions, theme, and key
bindings come across.&lt;/p&gt;
&lt;h2 id="three-features-that-matter"&gt;Three features that matter &lt;a href="#three-features-that-matter" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Feature&lt;/th&gt;
 &lt;th&gt;Key&lt;/th&gt;
 &lt;th&gt;Purpose&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Inline edit&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘K&lt;/code&gt; / &lt;code&gt;Ctrl+K&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Change the selection from a plain-language instruction&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Chat&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;⌘L&lt;/code&gt; / &lt;code&gt;Ctrl+L&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Ask questions about the code&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Agent mode&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Toggle in the chat panel&lt;/td&gt;
 &lt;td&gt;Make changes across several files&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="inline-edit-is-the-one-youll-use-most"&gt;Inline edit is the one you&amp;rsquo;ll use most &lt;a href="#inline-edit-is-the-one-youll-use-most" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Select the code, press &lt;code&gt;⌘K&lt;/code&gt;, and say &amp;ldquo;turn this loop into a map and add a null check.&amp;rdquo;
The change appears as a diff for you to accept or reject.&lt;/p&gt;</description></item><item><title>Ollama</title><link>https://toolian.metacog.co.kr/docs/ai/ollama/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/ai/ollama/</guid><description>&lt;p&gt;When policy forbids sending code outside, when things must work offline, or when the
cost of high-volume requests matters, a local model becomes an option. Ollama reduces
that to roughly the effort of &lt;code&gt;docker run&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="6c48b6a" class="language-bash "&gt;
 &lt;code&gt;brew install ollama
ollama serve # start the background service&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="8a1b8df" class="language-bash "&gt;
 &lt;code&gt;curl -fsSL https://ollama.com/install.sh | sh&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Windows uses the official installer.&lt;/p&gt;
&lt;h2 id="running-a-model"&gt;Running a model &lt;a href="#running-a-model" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="2a741d6" class="language-bash "&gt;
 &lt;code&gt;ollama pull llama3.2 # download
ollama run llama3.2 # interactive
ollama list # installed models
ollama rm llama3.2 # remove&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;You can also pipe a prompt in:&lt;/p&gt;</description></item><item><title>The Daily Git Workflow</title><link>https://toolian.metacog.co.kr/docs/git/git-workflow/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/git/git-workflow/</guid><description>&lt;p&gt;Git has hundreds of commands; you use about ten of them daily. Here are those ten, plus
how to get out of trouble.&lt;/p&gt;
&lt;h2 id="a-days-shape"&gt;A day&amp;rsquo;s shape &lt;a href="#a-days-shape" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="ea13134" class="language-bash "&gt;
 &lt;code&gt;git switch main &amp;amp;&amp;amp; git pull --rebase # get current
git switch -c feat/login-rate-limit # branch off
# ... work ...
git add -p # stage hunk by hunk, reviewing as you go
git commit -m &amp;#34;Limit login attempts to five per minute&amp;#34;
git push -u origin feat/login-rate-limit&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;code&gt;git add -p&lt;/code&gt; walks you through each hunk and asks whether to include it. It prevents
most stray-&lt;code&gt;print&lt;/code&gt;-statement accidents on its own.&lt;/p&gt;</description></item><item><title>GitHub CLI (gh)</title><link>https://toolian.metacog.co.kr/docs/git/github-cli/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/git/github-cli/</guid><description>&lt;p&gt;&lt;code&gt;gh&lt;/code&gt; moves most of what you do on github.com into the terminal. The biggest gain is
losing the open-a-browser, find-the-tab, click-the-button loop.&lt;/p&gt;
&lt;h2 id="install-and-authenticate"&gt;Install and authenticate &lt;a href="#install-and-authenticate" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="039deb2" class="language-bash "&gt;
 &lt;code&gt;brew install gh
sudo apt install gh
winget install GitHub.cli

gh auth login # browser flow
gh auth status # check who you are&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="pull-requests"&gt;Pull requests &lt;a href="#pull-requests" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="feeb4f2" class="language-bash "&gt;
 &lt;code&gt;gh pr create --fill # title and body from your commits
gh pr create --draft --title &amp;#34;WIP: auth refactor&amp;#34;

gh pr list # open PRs
gh pr list --author &amp;#34;@me&amp;#34; # just yours
gh pr status # everything relevant to you

gh pr checkout 42 # switch to a PR branch to review it
gh pr diff 42 # see the changes
gh pr review 42 --approve
gh pr review 42 --request-changes -b &amp;#34;Could you add a test for this?&amp;#34;
gh pr merge 42 --squash --delete-branch&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;code&gt;gh pr checkout&lt;/code&gt; is especially good when reviewing: you don&amp;rsquo;t need to know the remote
branch name, just the number.&lt;/p&gt;</description></item><item><title>lazygit</title><link>https://toolian.metacog.co.kr/docs/git/lazygit/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/git/lazygit/</guid><description>&lt;p&gt;lazygit combines &lt;code&gt;git status&lt;/code&gt;, &lt;code&gt;git add -p&lt;/code&gt;, &lt;code&gt;git log&lt;/code&gt;, and &lt;code&gt;git rebase -i&lt;/code&gt; into one
screen. It speeds up &lt;strong&gt;partial staging and interactive rebase&lt;/strong&gt; in particular.&lt;/p&gt;
&lt;h2 id="install-and-run"&gt;Install and run &lt;a href="#install-and-run" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="40ac19b" class="language-bash "&gt;
 &lt;code&gt;brew install lazygit
sudo apt install lazygit
winget install JesseDuffield.lazygit

cd ~/projects/my-app
lazygit # or alias lg=&amp;#39;lazygit&amp;#39;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="layout"&gt;Layout &lt;a href="#layout" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Five panels run down the left; move between them with &lt;code&gt;1&lt;/code&gt;–&lt;code&gt;5&lt;/code&gt; or &lt;code&gt;Tab&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Number&lt;/th&gt;
 &lt;th&gt;Panel&lt;/th&gt;
 &lt;th&gt;Purpose&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;1&lt;/td&gt;
 &lt;td&gt;Status&lt;/td&gt;
 &lt;td&gt;Repository state and settings&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;Files&lt;/td&gt;
 &lt;td&gt;Changed files, staging&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;td&gt;Branches&lt;/td&gt;
 &lt;td&gt;Switching and merging&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;4&lt;/td&gt;
 &lt;td&gt;Commits&lt;/td&gt;
 &lt;td&gt;History and rebasing&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;5&lt;/td&gt;
 &lt;td&gt;Stash&lt;/td&gt;
 &lt;td&gt;Temporary storage&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="essential-keys"&gt;Essential keys &lt;a href="#essential-keys" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Key&lt;/th&gt;
 &lt;th&gt;Action&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Space&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Toggle staging for a file or hunk&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Enter&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Enter a file for line-level staging&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Commit&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;A&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Amend the previous commit&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Pull&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;P&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Push&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Delete / discard&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;?&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Help for the current panel&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;q&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Quit&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;You don&amp;rsquo;t have to memorise anything — &lt;code&gt;?&lt;/code&gt; lists the keys in place.&lt;/p&gt;</description></item><item><title>delta</title><link>https://toolian.metacog.co.kr/docs/git/delta/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/git/delta/</guid><description>&lt;p&gt;Plain &lt;code&gt;git diff&lt;/code&gt; colours whole lines red and green. Change one word and the entire line
lights up, leaving you to hunt for the difference by eye. &lt;code&gt;delta&lt;/code&gt; &lt;strong&gt;highlights only
what changed&lt;/strong&gt; and adds syntax colouring on top.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="aa651c8" class="language-bash "&gt;
 &lt;code&gt;brew install git-delta
sudo apt install git-delta
winget install dandavison.delta&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;The package is &lt;code&gt;git-delta&lt;/code&gt;; the binary is &lt;code&gt;delta&lt;/code&gt;. Take care not to confuse it with
other packages named &lt;code&gt;delta&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>pre-commit Hooks</title><link>https://toolian.metacog.co.kr/docs/git/pre-commit/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/git/pre-commit/</guid><description>&lt;p&gt;&amp;ldquo;Formatting is off here&amp;rdquo; and &amp;ldquo;there&amp;rsquo;s a leftover console log&amp;rdquo; are review comments a
machine should be making, not a person. pre-commit runs a fixed set of checks every
time you commit.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="9ba45ff" class="language-bash "&gt;
 &lt;code&gt;brew install pre-commit
pip install pre-commit&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Install the hooks from the project root:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="b6fc731" class="language-bash "&gt;
 &lt;code&gt;pre-commit install&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;They now run on every &lt;code&gt;git commit&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="the-config-file"&gt;The config file &lt;a href="#the-config-file" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;.pre-commit-config.yaml&lt;/code&gt; at the project root:&lt;/p&gt;</description></item><item><title>curl</title><link>https://toolian.metacog.co.kr/docs/network/curl/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/network/curl/</guid><description>&lt;p&gt;&lt;code&gt;curl&lt;/code&gt; is already installed on virtually every server, which makes it the first thing
you reach for when confirming &amp;ldquo;it works on my laptop but not on the box.&amp;rdquo;&lt;/p&gt;
&lt;h2 id="basics"&gt;Basics &lt;a href="#basics" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="1304116" class="language-bash "&gt;
 &lt;code&gt;curl https://api.example.com/users # GET, body only
curl -i https://api.example.com/users # include response headers
curl -I https://api.example.com/users # headers only (HEAD)
curl -s https://api.example.com/users | jq # quiet, piped into jq
curl -o users.json https://api.example.com/users # save to a file&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="flags-worth-knowing"&gt;Flags worth knowing &lt;a href="#flags-worth-knowing" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Flag&lt;/th&gt;
 &lt;th&gt;Meaning&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-X POST&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Set the method&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-H &amp;quot;Key: value&amp;quot;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Add a header (repeatable)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-d '{&amp;quot;a&amp;quot;:1}'&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Send a body (implies POST)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--data-urlencode&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;URL-encode a form value&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-F file=@a.png&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Multipart file upload&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-u user:pass&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Basic auth&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-L&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Follow redirects&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-s&lt;/code&gt; / &lt;code&gt;-S&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Hide progress / still show errors&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-f&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Fail the exit code on HTTP errors (essential in scripts)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-k&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Skip certificate verification (debugging only)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--max-time 10&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Overall timeout in seconds&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-v&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Print the whole request and response exchange&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="calling-a-json-api"&gt;Calling a JSON API &lt;a href="#calling-a-json-api" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="25fd094" class="language-bash "&gt;
 &lt;code&gt;curl -sS -X POST https://api.example.com/users \
 -H &amp;#34;Content-Type: application/json&amp;#34; \
 -H &amp;#34;Authorization: Bearer $TOKEN&amp;#34; \
 -d &amp;#39;{&amp;#34;name&amp;#34;:&amp;#34;Alex Kim&amp;#34;,&amp;#34;email&amp;#34;:&amp;#34;alex@example.com&amp;#34;}&amp;#39; | jq&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;A long body reads better from a file:&lt;/p&gt;</description></item><item><title>HTTPie</title><link>https://toolian.metacog.co.kr/docs/network/httpie/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/network/httpie/</guid><description>&lt;p&gt;HTTPie does the same job as curl with shorter syntax and output that is coloured and
formatted automatically. Poking at a JSON API by hand takes less than half the typing.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="8245e98" class="language-bash "&gt;
 &lt;code&gt;brew install httpie
pip install httpie
sudo apt install httpie&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="basics"&gt;Basics &lt;a href="#basics" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="15f0f53" class="language-bash "&gt;
 &lt;code&gt;http GET https://api.example.com/users
http https://api.example.com/users # GET is the default
https example.com/users # shorthand for the https scheme&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Responses are syntax-highlighted and JSON is formatted, so you can read them without
piping through &lt;code&gt;jq&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Bruno and Postman</title><link>https://toolian.metacog.co.kr/docs/network/bruno-postman/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/network/bruno-postman/</guid><description>&lt;p&gt;Once you&amp;rsquo;ve outgrown pasting curl commands into Slack, you need somewhere to keep a set
of requests and swap environments. There are two broad choices.&lt;/p&gt;
&lt;h2 id="what-differs"&gt;What differs &lt;a href="#what-differs" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;th&gt;Bruno&lt;/th&gt;
 &lt;th&gt;Postman&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Storage&lt;/td&gt;
 &lt;td&gt;Files (.bru) managed in Git&lt;/td&gt;
 &lt;td&gt;Cloud workspace&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Account&lt;/td&gt;
 &lt;td&gt;Not required&lt;/td&gt;
 &lt;td&gt;Required for collaboration&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Collaboration&lt;/td&gt;
 &lt;td&gt;Branches and PRs as usual&lt;/td&gt;
 &lt;td&gt;Web-based sharing and permissions&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Breadth&lt;/td&gt;
 &lt;td&gt;Focused on the core&lt;/td&gt;
 &lt;td&gt;Monitors, mock servers, documentation&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Best when&lt;/td&gt;
 &lt;td&gt;Requests live beside the code&lt;/td&gt;
 &lt;td&gt;A whole organisation, including non-engineers&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Choose Bruno if you want requests committed alongside the code, Postman if you need an
API portal for the wider company.&lt;/p&gt;</description></item><item><title>Exposing a Local Server</title><link>https://toolian.metacog.co.kr/docs/network/tunneling/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/network/tunneling/</guid><description>&lt;p&gt;Sometimes you need to receive a payment provider&amp;rsquo;s webhook, or look at the screen you&amp;rsquo;re
building on an actual phone. These tools open &lt;code&gt;localhost:3000&lt;/code&gt; to the world for a while
without deploying anything.&lt;/p&gt;
&lt;h2 id="ngrok"&gt;ngrok &lt;a href="#ngrok" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The most widely used. Needs an account and an auth token.&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="81f71ab" class="language-bash "&gt;
 &lt;code&gt;brew install ngrok
ngrok config add-authtoken &amp;lt;token&amp;gt;
ngrok http 3000&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;It prints a URL like &lt;code&gt;https://xxxx.ngrok-free.app&lt;/code&gt;. Put that in your webhook settings.&lt;/p&gt;</description></item><item><title>Docker</title><link>https://toolian.metacog.co.kr/docs/devops/docker/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/devops/docker/</guid><description>&lt;p&gt;Docker&amp;rsquo;s value is less about virtualisation and more about &lt;strong&gt;writing an environment
down as code&lt;/strong&gt;. Half a day of local setup for a new teammate becomes one line:
&lt;code&gt;docker compose up&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="88a463b" class="language-bash "&gt;
 &lt;code&gt;brew install --cask docker # Docker Desktop
brew install --cask orbstack # a lighter alternative on macOS&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;On Linux, follow your distribution&amp;rsquo;s official &lt;code&gt;docker-ce&lt;/code&gt; instructions.&lt;/p&gt;
&lt;h2 id="three-concepts"&gt;Three concepts &lt;a href="#three-concepts" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Concept&lt;/th&gt;
 &lt;th&gt;Meaning&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Image&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;A read-only snapshot of an environment&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Container&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;A running instance of an image&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Volume&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Storage that survives the container&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="basic-commands"&gt;Basic commands &lt;a href="#basic-commands" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="10e5ae1" class="language-bash "&gt;
 &lt;code&gt;docker run -d --name pg -p 5432:5432 \
 -e POSTGRES_PASSWORD=secret postgres:16

docker ps # running containers
docker ps -a # including stopped ones
docker logs -f pg # follow the logs
docker exec -it pg psql -U postgres # run a command inside
docker stop pg &amp;amp;&amp;amp; docker rm pg&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Flag&lt;/th&gt;
 &lt;th&gt;Meaning&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-d&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Run in the background&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-p host:container&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Publish a port&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-e KEY=VALUE&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Environment variable&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-v hostpath:containerpath&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Mount a volume&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--rm&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Delete on exit&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-it&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Interactive terminal&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="writing-a-dockerfile"&gt;Writing a Dockerfile &lt;a href="#writing-a-dockerfile" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="65fcda5" class="language-dockerfile "&gt;
 &lt;code&gt;# stage 1: build
FROM node:22-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# stage 2: run, without the build tooling
FROM node:22-slim
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
USER node
EXPOSE 3000
CMD [&amp;#34;node&amp;#34;, &amp;#34;dist/main.js&amp;#34;]&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Two things carry most of the benefit:&lt;/p&gt;</description></item><item><title>Docker Compose</title><link>https://toolian.metacog.co.kr/docs/devops/docker-compose/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/devops/docker-compose/</guid><description>&lt;p&gt;Real projects don&amp;rsquo;t stop at one container — the app, a database, a cache, and a queue
all need to be up. Compose describes that in a single YAML file and starts it with
&lt;code&gt;docker compose up&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="composeyaml"&gt;compose.yaml &lt;a href="#composeyaml" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="12a1f6a" class="language-yaml "&gt;
 &lt;code&gt;services:
 app:
 build: .
 ports:
 - &amp;#34;3000:3000&amp;#34;
 environment:
 DATABASE_URL: postgres://postgres:secret@db:5432/app
 REDIS_URL: redis://cache:6379
 volumes:
 - .:/app
 - /app/node_modules # protect it from being shadowed by the host
 depends_on:
 db:
 condition: service_healthy

 db:
 image: postgres:16
 environment:
 POSTGRES_PASSWORD: secret
 POSTGRES_DB: app
 ports:
 - &amp;#34;5432:5432&amp;#34;
 volumes:
 - pgdata:/var/lib/postgresql/data
 healthcheck:
 test: [&amp;#34;CMD-SHELL&amp;#34;, &amp;#34;pg_isready -U postgres&amp;#34;]
 interval: 5s
 retries: 5

 cache:
 image: redis:7-alpine

volumes:
 pgdata:&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Containers &lt;strong&gt;find each other by service name&lt;/strong&gt;. That&amp;rsquo;s why the app above connects to
&lt;code&gt;db&lt;/code&gt; rather than &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>kubectl and k9s</title><link>https://toolian.metacog.co.kr/docs/devops/kubernetes/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/devops/kubernetes/</guid><description>&lt;p&gt;Even if you don&amp;rsquo;t operate Kubernetes yourself, you will end up reading logs from a
deployed service or working out why a pod won&amp;rsquo;t start. This page concentrates on
&lt;strong&gt;reading and debugging&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="40383c3" class="language-bash "&gt;
 &lt;code&gt;brew install kubectl k9s
brew install kubectx # context and namespace switching&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="check-your-context-first"&gt;Check your context first &lt;a href="#check-your-context-first" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="fc06e81" class="language-bash "&gt;
 &lt;code&gt;kubectl config get-contexts
kubectl config current-context
kubectx staging # switch context
kubens my-namespace # switch namespace&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Running a command against production without realising you were pointed at it&lt;/strong&gt; is
the most common accident here. Putting the current context in your prompt prevents it
(Starship&amp;rsquo;s &lt;code&gt;kubernetes&lt;/code&gt; module does this).&lt;/p&gt;</description></item><item><title>GitHub Actions</title><link>https://toolian.metacog.co.kr/docs/devops/github-actions/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/devops/github-actions/</guid><description>&lt;p&gt;Actions is CI/CD that runs whenever you put a workflow YAML file in your repository.
There&amp;rsquo;s no server to stand up, so it&amp;rsquo;s painless even for personal projects.&lt;/p&gt;
&lt;h2 id="a-first-workflow"&gt;A first workflow &lt;a href="#a-first-workflow" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;.github/workflows/ci.yml&lt;/code&gt;:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="a43d01c" class="language-yaml "&gt;
 &lt;code&gt;name: CI

on:
 push:
 branches: [main]
 pull_request:

jobs:
 test:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v4

 - uses: actions/setup-node@v4
 with:
 node-version: 22
 cache: npm

 - run: npm ci
 - run: npm run lint
 - run: npm test&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Push and it runs. Follow along from the terminal with &lt;code&gt;gh run watch&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Terraform</title><link>https://toolian.metacog.co.kr/docs/devops/terraform/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/devops/terraform/</guid><description>&lt;p&gt;Infrastructure clicked together in a console is infrastructure nobody can explain six
months later. Terraform states the desired shape as code, works out the difference from
reality, and applies it.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="fe6a88e" class="language-bash "&gt;
 &lt;code&gt;brew install terraform
brew install opentofu # the open-source fork; the command is tofu&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="the-loop"&gt;The loop &lt;a href="#the-loop" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="7877f67" class="language-bash "&gt;
 &lt;code&gt;terraform init # download providers, configure the backend
terraform fmt # format
terraform validate # check syntax
terraform plan # preview what will change
terraform apply # apply it
terraform destroy # tear everything down (careful)&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Never &lt;code&gt;apply&lt;/code&gt; without reading a &lt;code&gt;plan&lt;/code&gt;.&lt;/strong&gt; That single habit prevents most incidents.&lt;/p&gt;</description></item><item><title>Raycast (macOS)</title><link>https://toolian.metacog.co.kr/docs/automation/raycast/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/automation/raycast/</guid><description>&lt;p&gt;Raycast opens with &lt;code&gt;⌘Space&lt;/code&gt; and runs whatever you want after a few keystrokes. It does
more than launch apps — it &lt;strong&gt;removes most of the reasons your hand reaches for the
mouse&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="113a936" class="language-bash "&gt;
 &lt;code&gt;brew install --cask raycast&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;After installing, unbind &lt;code&gt;⌘Space&lt;/code&gt; from Spotlight (System Settings → Keyboard →
Keyboard Shortcuts → Spotlight) and give it to Raycast.&lt;/p&gt;
&lt;h2 id="four-things-to-turn-on-immediately"&gt;Four things to turn on immediately &lt;a href="#four-things-to-turn-on-immediately" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Feature&lt;/th&gt;
 &lt;th&gt;Why&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Clipboard History&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Go back and retrieve something you copied. The biggest single win&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Window Management&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Halve and quarter windows without a separate app&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Snippets&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Expand a short keyword into a phrase or address you type constantly&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Quicklinks&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Frequently opened URLs, with parameters&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Give Clipboard History its own shortcut, something like &lt;code&gt;⌥⌘C&lt;/code&gt;, and it&amp;rsquo;s ready to use.&lt;/p&gt;</description></item><item><title>PowerToys (Windows)</title><link>https://toolian.metacog.co.kr/docs/automation/powertoys/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/automation/powertoys/</guid><description>&lt;p&gt;PowerToys is an open-source collection of small utilities in one app. Turn on only the
modules you need.&lt;/p&gt;
&lt;h2 id="install"&gt;Install &lt;a href="#install" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="43189f2" class="language-powershell "&gt;
 &lt;code&gt;winget install Microsoft.PowerToys&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="modules-worth-enabling"&gt;Modules worth enabling &lt;a href="#modules-worth-enabling" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Module&lt;/th&gt;
 &lt;th&gt;What it does&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;FancyZones&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Split the screen into a grid and snap windows into it&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;PowerToys Run&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;An &lt;code&gt;Alt+Space&lt;/code&gt; launcher for apps, files, calculations, commands&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Keyboard Manager&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Remap keys and shortcuts&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Text Extractor&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;OCR text from anywhere on screen (&lt;code&gt;Win+Shift+T&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;PowerRename&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Bulk rename with regular expressions&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Always On Top&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Pin a window (&lt;code&gt;Win+Ctrl+T&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Color Picker&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Sample a colour (&lt;code&gt;Win+Shift+C&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Awake&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Temporarily prevent sleep&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="fancyzones"&gt;FancyZones &lt;a href="#fancyzones" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Open the editor with &lt;code&gt;Win+Shift+\``, build a layout, then hold &lt;/code&gt;Shift` while dragging a
window to snap it into a zone. Fixing three windows at a 3:5:4 ratio on a wide monitor
removes dragging-to-resize from your day entirely.&lt;/p&gt;</description></item><item><title>Make and Makefiles</title><link>https://toolian.metacog.co.kr/docs/automation/make/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/automation/make/</guid><description>&lt;p&gt;If you copy long commands out of a README every time, a single Makefile tidies that up.
Make exists on every Unix-like system and doesn&amp;rsquo;t care what language you write in.&lt;/p&gt;
&lt;h2 id="a-minimal-makefile"&gt;A minimal Makefile &lt;a href="#a-minimal-makefile" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Makefile&lt;/code&gt; at the project root (tab indentation is mandatory):&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="d844f8b" class="language-makefile "&gt;
 &lt;code&gt;.PHONY: help install dev test lint build clean

help: ## Show the available commands
	@grep -E &amp;#39;^[a-zA-Z_-]&amp;#43;:.*?## .*$$&amp;#39; $(MAKEFILE_LIST) | \
	 awk &amp;#39;BEGIN {FS = &amp;#34;:.*?## &amp;#34;}; {printf &amp;#34; \033[36m%-12s\033[0m %s\n&amp;#34;, $$1, $$2}&amp;#39;

install: ## Install dependencies
	npm ci

dev: ## Run the development server
	docker compose up -d
	npm run dev

test: ## Run the tests
	npm test

lint: ## Lint and check formatting
	npm run lint
	npm run format:check

build: ## Production build
	npm run build

clean: ## Remove build output
	rm -rf dist node_modules/.cache
	docker compose down&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;code&gt;make&lt;/code&gt; or &lt;code&gt;make help&lt;/code&gt; prints the commands with their descriptions, so a new teammate can
see what&amp;rsquo;s possible without reading the README.&lt;/p&gt;</description></item><item><title>cron and launchd</title><link>https://toolian.metacog.co.kr/docs/automation/schedulers/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/automation/schedulers/</guid><description>&lt;p&gt;Backups, log rotation, report generation — anything that runs at the same time daily
belongs to a scheduler. The catch is that most scheduled jobs &lt;strong&gt;fail silently&lt;/strong&gt;, so this
page covers that too.&lt;/p&gt;
&lt;h2 id="cron-linux-macos"&gt;cron (Linux, macOS) &lt;a href="#cron-linux-macos" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="974f9db" class="language-bash "&gt;
 &lt;code&gt;crontab -e # edit
crontab -l # list
crontab -r # delete everything (careful)&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;The format is five fields:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="d92716c" class="language- "&gt;
 &lt;code&gt;min hour day month weekday command
 * * * * *&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Expression&lt;/th&gt;
 &lt;th&gt;Meaning&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;0 3 * * *&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Daily at 03:00&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;*/15 * * * *&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Every 15 minutes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;0 9 * * 1-5&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Weekdays at 09:00&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;0 0 1 * *&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Midnight on the first of the month&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;@reboot&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;At boot&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For example:&lt;/p&gt;</description></item><item><title>n8n</title><link>https://toolian.metacog.co.kr/docs/automation/n8n/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/automation/n8n/</guid><description>&lt;p&gt;&amp;ldquo;When a GitHub issue opens, post to Slack and add a row in Notion&amp;rdquo; — n8n builds that
kind of glue without code. It resembles Zapier and Make, with the difference that
&lt;strong&gt;you can host it yourself so the data never leaves.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="run-it-with-docker"&gt;Run it with Docker &lt;a href="#run-it-with-docker" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="0ac9257" class="language-bash "&gt;
 &lt;code&gt;docker run -d --name n8n \
 -p 5678:5678 \
 -v n8n_data:/home/node/.n8n \
 -e GENERIC_TIMEZONE=&amp;#34;Asia/Seoul&amp;#34; \
 -e TZ=&amp;#34;Asia/Seoul&amp;#34; \
 docker.n8n.io/n8nio/n8n&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Create an account at &lt;code&gt;http://localhost:5678&lt;/code&gt; and start building.&lt;/p&gt;</description></item><item><title>Obsidian</title><link>https://toolian.metacog.co.kr/docs/writing/obsidian/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/writing/obsidian/</guid><description>&lt;p&gt;The heart of Obsidian is that &lt;strong&gt;a note is just a &lt;code&gt;.md&lt;/code&gt; file in a folder&lt;/strong&gt;. If the
service disappears the files remain, and version-controlling them or moving them to
another tool is easy.&lt;/p&gt;
&lt;h2 id="install-and-first-setup"&gt;Install and first setup &lt;a href="#install-and-first-setup" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="1e45a41" class="language-bash "&gt;
 &lt;code&gt;brew install --cask obsidian&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;vault&lt;/strong&gt; is the folder holding your notes. Make one at something like &lt;code&gt;~/notes&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Under Settings → Files &amp;amp; Links, point &amp;ldquo;Default location for new attachments&amp;rdquo; at an
&lt;code&gt;attachments&lt;/code&gt; folder so images don&amp;rsquo;t scatter.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="folder-structure"&gt;Folder structure &lt;a href="#folder-structure" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A deep folder tree makes you deliberate about where things go, and then you stop writing
them down. Staying shallow and linking instead lasts longer.&lt;/p&gt;</description></item><item><title>Markdown</title><link>https://toolian.metacog.co.kr/docs/writing/markdown/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/writing/markdown/</guid><description>&lt;p&gt;Markdown is the common language of GitHub, Slack, Notion, and every static site
generator. Thirty minutes to learn, and you use it for the rest of your career.&lt;/p&gt;
&lt;h2 id="the-basics"&gt;The basics &lt;a href="#the-basics" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="4ba90aa" class="language-markdown "&gt;
 &lt;code&gt;# Heading 1
## Heading 2
### Heading 3

**bold** *italic* ~~strikethrough~~ `inline code`

- a list
- of items
 - nested (two or more spaces)

1. numbered
2. list

&amp;gt; a block quote

[link text](https://example.com)
![alt text](./image.png)

---&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="code-blocks"&gt;Code blocks &lt;a href="#code-blocks" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Naming the language turns on syntax highlighting.&lt;/p&gt;</description></item><item><title>Mermaid</title><link>https://toolian.metacog.co.kr/docs/writing/mermaid/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/writing/mermaid/</guid><description>&lt;p&gt;A diagram exported as an image means hunting for the source file every time it changes,
and a diff that shows nothing. Mermaid is text, so &lt;strong&gt;the change is legible right in the
pull request.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GitHub, GitLab, Notion, Obsidian, and most documentation tools — this site included —
support it out of the box.&lt;/p&gt;
&lt;h2 id="flowcharts"&gt;Flowcharts &lt;a href="#flowcharts" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="3b9fd58" class="language-markdown "&gt;
 &lt;code&gt;```mermaid
flowchart TD
 A[Request received] --&amp;gt; B{Has an auth token?}
 B --&amp;gt;|No| C[Return 401]
 B --&amp;gt;|Yes| D{Token valid?}
 D --&amp;gt;|No| C
 D --&amp;gt;|Yes| E[Run the handler]
 E --&amp;gt; F[Return the response]
```&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 A[Request received] --&amp;gt; B{Has an auth token?}
 B --&amp;gt;|No| C[Return 401]
 B --&amp;gt;|Yes| D{Token valid?}
 D --&amp;gt;|No| C
 D --&amp;gt;|Yes| E[Run the handler]
 E --&amp;gt; F[Return the response]
&lt;/pre&gt;
&lt;p&gt;Pick a direction from &lt;code&gt;TD&lt;/code&gt; (top-down), &lt;code&gt;LR&lt;/code&gt; (left-right), &lt;code&gt;BT&lt;/code&gt;, or &lt;code&gt;RL&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Excalidraw</title><link>https://toolian.metacog.co.kr/docs/writing/excalidraw/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0000</pubDate><guid>https://toolian.metacog.co.kr/docs/writing/excalidraw/</guid><description>&lt;p&gt;Mermaid is strong on formalised diagrams, but it&amp;rsquo;s the wrong tool for an architecture
sketch that needs free placement, or for drawing live in a meeting. Excalidraw fills
that gap, and its hand-drawn style sends a useful signal: &lt;strong&gt;this isn&amp;rsquo;t settled yet.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="getting-started"&gt;Getting started &lt;a href="#getting-started" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Open &lt;a href="https://excalidraw.com" rel="external" target="_blank"&gt;excalidraw.com&lt;svg width="16" height="16" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path fill="currentColor" d="M14 5c-.552 0-1-.448-1-1s.448-1 1-1h6c.552 0 1 .448 1 1v6c0 .552-.448 1-1 1s-1-.448-1-1v-3.586l-7.293 7.293c-.391.39-1.024.39-1.414 0-.391-.391-.391-1.024 0-1.414l7.293-7.293h-3.586zm-9 2c-.552 0-1 .448-1 1v11c0 .552.448 1 1 1h11c.552 0 1-.448 1-1v-4.563c0-.552.448-1 1-1s1 .448 1 1v4.563c0 1.657-1.343 3-3 3h-11c-1.657 0-3-1.343-3-3v-11c0-1.657 1.343-3 3-3h4.563c.552 0 1 .448 1 1s-.448 1-1 1h-4.563z"/&gt;&lt;/svg&gt;&lt;/a&gt; and draw. No account, no install.&lt;/p&gt;</description></item></channel></rss>