mirror of
https://github.com/jbranchaud/til
synced 2026-11-01 16:43:36 +00:00
Compare commits
3
Commits
master
..
c525d217eb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c525d217eb | ||
|
|
5615da920f | ||
|
|
c60c63f554 |
@@ -1,5 +0,0 @@
|
|||||||
[submodule "notes"]
|
|
||||||
path = notes
|
|
||||||
url = git@github.com:jbranchaud/til-notes-private.git
|
|
||||||
branch = main
|
|
||||||
ignore = all
|
|
||||||
@@ -6,16 +6,13 @@ A collection of concise write-ups on small things I learn day to day across a
|
|||||||
variety of languages and technologies. These are things that don't really
|
variety of languages and technologies. These are things that don't really
|
||||||
warrant a full blog post. These are things I've picked up by [Learning In
|
warrant a full blog post. These are things I've picked up by [Learning In
|
||||||
Public™](https://dev.to/jbranchaud/how-i-built-a-learning-machine-45k9) and
|
Public™](https://dev.to/jbranchaud/how-i-built-a-learning-machine-45k9) and
|
||||||
working across different projects via [VisualMode](https://www.visualmode.dev/).
|
pairing with smart people at Hashrocket.
|
||||||
|
|
||||||
For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter).
|
For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
|
||||||
|
|
||||||
_1895 TILs and counting..._
|
_1635 TILs and counting..._
|
||||||
|
|
||||||
See some of the other learning resources I work on:
|
See some of the other learning resources I work on:
|
||||||
|
|
||||||
- [The VisualMode Blog](https://visualmode.dev/blog)
|
|
||||||
- [Get Started with Vimium](https://egghead.io/courses/get-started-with-vimium~3t5f7)
|
|
||||||
- [Ruby Operator Lookup](https://www.visualmode.dev/ruby-operators)
|
- [Ruby Operator Lookup](https://www.visualmode.dev/ruby-operators)
|
||||||
- [Vim Un-Alphabet](https://www.youtube.com/playlist?list=PL46-cKSxMYYCMpzXo6p0Cof8hJInYgohU)
|
- [Vim Un-Alphabet](https://www.youtube.com/playlist?list=PL46-cKSxMYYCMpzXo6p0Cof8hJInYgohU)
|
||||||
|
|
||||||
@@ -30,10 +27,8 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
* [Ansible](#ansible)
|
* [Ansible](#ansible)
|
||||||
* [Astro](#astro)
|
* [Astro](#astro)
|
||||||
* [AWS](#aws)
|
* [AWS](#aws)
|
||||||
* [Bash](#bash)
|
|
||||||
* [Brew](#brew)
|
* [Brew](#brew)
|
||||||
* [Chrome](#chrome)
|
* [Chrome](#chrome)
|
||||||
* [Claude Code](#claude-code)
|
|
||||||
* [Clojure](#clojure)
|
* [Clojure](#clojure)
|
||||||
* [CSS](#css)
|
* [CSS](#css)
|
||||||
* [Deno](#deno)
|
* [Deno](#deno)
|
||||||
@@ -43,7 +38,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
* [Elixir](#elixir)
|
* [Elixir](#elixir)
|
||||||
* [Gatsby](#gatsby)
|
* [Gatsby](#gatsby)
|
||||||
* [Git](#git)
|
* [Git](#git)
|
||||||
* [GitHub](#github)
|
|
||||||
* [GitHub Actions](#github-actions)
|
* [GitHub Actions](#github-actions)
|
||||||
* [Go](#go)
|
* [Go](#go)
|
||||||
* [GROQ](#groq)
|
* [GROQ](#groq)
|
||||||
@@ -59,9 +53,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
* [Kitty](#kitty)
|
* [Kitty](#kitty)
|
||||||
* [Linux](#linux)
|
* [Linux](#linux)
|
||||||
* [LLM](#llm)
|
* [LLM](#llm)
|
||||||
* [Logseq](#logseq)
|
|
||||||
* [Mac](#mac)
|
* [Mac](#mac)
|
||||||
* [Math](#math)
|
|
||||||
* [Mise](#mise)
|
* [Mise](#mise)
|
||||||
* [MongoDB](#mongodb)
|
* [MongoDB](#mongodb)
|
||||||
* [MySQL](#mysql)
|
* [MySQL](#mysql)
|
||||||
@@ -88,7 +80,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
* [SQLite](#sqlite)
|
* [SQLite](#sqlite)
|
||||||
* [Streaming](#streaming)
|
* [Streaming](#streaming)
|
||||||
* [Tailwind CSS](#tailwind-css)
|
* [Tailwind CSS](#tailwind-css)
|
||||||
* [Taskfile](#taskfile)
|
|
||||||
* [tmux](#tmux)
|
* [tmux](#tmux)
|
||||||
* [TypeScript](#typescript)
|
* [TypeScript](#typescript)
|
||||||
* [Unix](#unix)
|
* [Unix](#unix)
|
||||||
@@ -99,7 +90,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
* [Workflow](#workflow)
|
* [Workflow](#workflow)
|
||||||
* [XState](#xstate)
|
* [XState](#xstate)
|
||||||
* [YAML](#yaml)
|
* [YAML](#yaml)
|
||||||
* [Zed](#zed)
|
|
||||||
* [Zod](#zod)
|
* [Zod](#zod)
|
||||||
* [Zsh](#zsh)
|
* [Zsh](#zsh)
|
||||||
|
|
||||||
@@ -131,17 +121,10 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Turn Off Output Pager For A Command](aws/turn-off-output-pager-for-a-command.md)
|
- [Turn Off Output Pager For A Command](aws/turn-off-output-pager-for-a-command.md)
|
||||||
- [Use Specific AWS Profile With CLI](aws/use-specific-aws-profile-with-cli.md)
|
- [Use Specific AWS Profile With CLI](aws/use-specific-aws-profile-with-cli.md)
|
||||||
|
|
||||||
### Bash
|
|
||||||
|
|
||||||
- [Edit The Current Command Prompt](bash/edit-the-current-command-prompt.md)
|
|
||||||
|
|
||||||
### Brew
|
### Brew
|
||||||
|
|
||||||
- [Clean Up Your Brew Installations](brew/clean-up-your-brew-installations.md)
|
|
||||||
- [Configure Brew Environment Variables](brew/configure-brew-environment-variables.md)
|
- [Configure Brew Environment Variables](brew/configure-brew-environment-variables.md)
|
||||||
- [Export List Of Everything Installed By Brew](brew/export-list-of-everything-installed-by-brew.md)
|
- [Export List Of Everything Installed By Brew](brew/export-list-of-everything-installed-by-brew.md)
|
||||||
- [Install From Nonstandard Brewfile](brew/install-from-nonstandard-brewfile.md)
|
|
||||||
- [Install Go Packages In Brewfile](brew/install-go-packages-in-brewfile.md)
|
|
||||||
- [List All Services Managed By Brew](brew/list-all-services-managed-by-brew.md)
|
- [List All Services Managed By Brew](brew/list-all-services-managed-by-brew.md)
|
||||||
|
|
||||||
### Chrome
|
### Chrome
|
||||||
@@ -149,7 +132,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Access A Value Logged To The Console](chrome/access-a-value-logged-to-the-console.md)
|
- [Access A Value Logged To The Console](chrome/access-a-value-logged-to-the-console.md)
|
||||||
- [Chrome Supports Many Unix Keyboard Shortcuts](chrome/chrome-supports-many-unix-keyboard-shortcuts.md)
|
- [Chrome Supports Many Unix Keyboard Shortcuts](chrome/chrome-supports-many-unix-keyboard-shortcuts.md)
|
||||||
- [Copy Some Data From The Console](chrome/copy-some-data-from-the-console.md)
|
- [Copy Some Data From The Console](chrome/copy-some-data-from-the-console.md)
|
||||||
- [Duplicate Current Browser Tab](chrome/duplicate-current-browser-tab.md)
|
|
||||||
- [Duplicate The Current Tab](chrome/duplicate-the-current-tab.md)
|
- [Duplicate The Current Tab](chrome/duplicate-the-current-tab.md)
|
||||||
- [Easier Access To Network Throttling Controls](chrome/easier-access-to-network-throttling-controls.md)
|
- [Easier Access To Network Throttling Controls](chrome/easier-access-to-network-throttling-controls.md)
|
||||||
- [Keybinding To Focus The Address Bar](chrome/keybinding-to-focus-the-address-bar.md)
|
- [Keybinding To Focus The Address Bar](chrome/keybinding-to-focus-the-address-bar.md)
|
||||||
@@ -166,20 +148,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Trigger Commands From The Devtools Command Palette](chrome/trigger-commands-from-the-devtools-command-palette.md)
|
- [Trigger Commands From The Devtools Command Palette](chrome/trigger-commands-from-the-devtools-command-palette.md)
|
||||||
- [View Network Traffic For New Tabs](chrome/view-network-traffic-for-new-tabs.md)
|
- [View Network Traffic For New Tabs](chrome/view-network-traffic-for-new-tabs.md)
|
||||||
|
|
||||||
### Claude Code
|
|
||||||
|
|
||||||
- [Allow Edits From The Start](claude-code/allow-edits-from-the-start.md)
|
|
||||||
- [Ask An Agent To Fix Merge Conflicts](claude-code/ask-an-agent-to-fix-merge-conflicts.md)
|
|
||||||
- [Build From My Phone In Cloud Environments](claude-code/build-from-my-phone-in-cloud-environments.md)
|
|
||||||
- [Distinguish Sessions With Different Colors](claude-code/distinguish-sessions-with-different-colors.md)
|
|
||||||
- [Monitor Usage Limits From CLI](claude-code/monitor-usage-limits-from-cli.md)
|
|
||||||
- [Open Current Prompt In Default Editor](claude-code/open-current-prompt-in-default-editor.md)
|
|
||||||
- [Pick Up Session Locally That Started In Cloud](claude-code/pick-up-session-locally-that-started-in-cloud.md)
|
|
||||||
- [Resume Specific Session](claude-code/resume-specific-session.md)
|
|
||||||
- [Set Permission Mode When Starting Session](claude-code/set-permission-mode-when-starting-session.md)
|
|
||||||
- [Stash The Current Prompt To Send Another First](claude-code/stash-the-current-prompt-to-send-another-first.md)
|
|
||||||
- [Use Claude Code From Multiple Accounts](claude-code/use-claude-code-from-multiple-accounts.md)
|
|
||||||
|
|
||||||
### Clojure
|
### Clojure
|
||||||
|
|
||||||
- [Aggregation Using merge-with](clojure/aggregation-using-merge-with.md)
|
- [Aggregation Using merge-with](clojure/aggregation-using-merge-with.md)
|
||||||
@@ -230,14 +198,9 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Parameterized SCSS Mixins](css/parameterized-scss-mixins.md)
|
- [Parameterized SCSS Mixins](css/parameterized-scss-mixins.md)
|
||||||
- [Prevent Invisible Elements From Being Clicked](css/prevent-invisible-elements-from-being-clicked.md)
|
- [Prevent Invisible Elements From Being Clicked](css/prevent-invisible-elements-from-being-clicked.md)
|
||||||
- [:root Has Higher Specificity Than html](css/root-has-higher-specificity-than-html.md)
|
- [:root Has Higher Specificity Than html](css/root-has-higher-specificity-than-html.md)
|
||||||
- [Show Full URLs With Print Styles](css/show-full-urls-with-print-styles.md)
|
|
||||||
- [Style A Background With A Linear Gradient](css/style-a-background-with-a-linear-gradient.md)
|
- [Style A Background With A Linear Gradient](css/style-a-background-with-a-linear-gradient.md)
|
||||||
- [Using Maps In SCSS](css/using-maps-in-scss.md)
|
- [Using Maps In SCSS](css/using-maps-in-scss.md)
|
||||||
|
|
||||||
### Cursor
|
|
||||||
|
|
||||||
- [Allow Cursor To Be Launched From CLI](cursor/allow-cursor-to-be-launched-from-cli.md)
|
|
||||||
|
|
||||||
### Deno
|
### Deno
|
||||||
|
|
||||||
- [Read In The Contents Of A File](deno/read-in-the-contents-of-a-file.md)
|
- [Read In The Contents Of A File](deno/read-in-the-contents-of-a-file.md)
|
||||||
@@ -247,10 +210,9 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Aliasing An Ansible Host](devops/aliasing-an-ansible-host.md)
|
- [Aliasing An Ansible Host](devops/aliasing-an-ansible-host.md)
|
||||||
- [Allow Cross-Origin Requests To Include Cookies](devops/allow-cross-origin-requests-to-include-cookies.md)
|
- [Allow Cross-Origin Requests To Include Cookies](devops/allow-cross-origin-requests-to-include-cookies.md)
|
||||||
- [Allow HTTPS Through Your UFW Firewall](devops/allow-https-through-your-ufw-firewall.md)
|
- [Allow HTTPS Through Your UFW Firewall](devops/allow-https-through-your-ufw-firewall.md)
|
||||||
- [Check For Cached Site Assocation File For iOS](devops/check-for-cached-site-association-file-for-ios.md)
|
- [Check For Cached Site Association File For iOS](devops/check-for-cached-site-association-file-for-ios.md)
|
||||||
- [Check The Status of All Services](devops/check-the-status-of-all-services.md)
|
- [Check The Status of All Services](devops/check-the-status-of-all-services.md)
|
||||||
- [Check The Syntax Of nginx Files](devops/check-the-syntax-of-nginx-files.md)
|
- [Check The Syntax Of nginx Files](devops/check-the-syntax-of-nginx-files.md)
|
||||||
- [Cloudflare Allows CNAME For Apex Domain](devops/cloudflare-allows-cname-for-apex-domain.md)
|
|
||||||
- [Connect To An RDS PostgreSQL Database](devops/connect-to-an-rds-postgresql-database.md)
|
- [Connect To An RDS PostgreSQL Database](devops/connect-to-an-rds-postgresql-database.md)
|
||||||
- [Default Rails Deploy Script On Hatchbox](devops/default-rails-deploy-script-on-hatchbox.md)
|
- [Default Rails Deploy Script On Hatchbox](devops/default-rails-deploy-script-on-hatchbox.md)
|
||||||
- [Determine The IP Address Of A Domain](devops/determine-the-ip-address-of-a-domain.md)
|
- [Determine The IP Address Of A Domain](devops/determine-the-ip-address-of-a-domain.md)
|
||||||
@@ -260,7 +222,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Reload The nginx Configuration](devops/reload-the-nginx-configuration.md)
|
- [Reload The nginx Configuration](devops/reload-the-nginx-configuration.md)
|
||||||
- [Resolve The Public IP Of A URL](devops/resolve-the-public-ip-of-a-url.md)
|
- [Resolve The Public IP Of A URL](devops/resolve-the-public-ip-of-a-url.md)
|
||||||
- [Running Out Of inode Space](devops/running-out-of-inode-space.md)
|
- [Running Out Of inode Space](devops/running-out-of-inode-space.md)
|
||||||
- [Set, Get, And Unset Env Vars With Dokku](devops/set-get-and-unset-env-vars-with-dokku.md)
|
|
||||||
- [Set Up Domain For Hatchbox Rails App](devops/set-up-domain-for-hatchbox-rails-app.md)
|
- [Set Up Domain For Hatchbox Rails App](devops/set-up-domain-for-hatchbox-rails-app.md)
|
||||||
- [SSH Into A Docker Container](devops/ssh-into-a-docker-container.md)
|
- [SSH Into A Docker Container](devops/ssh-into-a-docker-container.md)
|
||||||
- [SSL Certificates Can Cover Multiple Domains](devops/ssl-certificates-can-cover-multiple-domains.md)
|
- [SSL Certificates Can Cover Multiple Domains](devops/ssl-certificates-can-cover-multiple-domains.md)
|
||||||
@@ -351,18 +312,13 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Caching Credentials](git/caching-credentials.md)
|
- [Caching Credentials](git/caching-credentials.md)
|
||||||
- [Change The Start Point Of A Branch](git/change-the-start-point-of-a-branch.md)
|
- [Change The Start Point Of A Branch](git/change-the-start-point-of-a-branch.md)
|
||||||
- [Check How A File Is Being Ignored](git/check-how-a-file-is-being-ignored.md)
|
- [Check How A File Is Being Ignored](git/check-how-a-file-is-being-ignored.md)
|
||||||
- [Check If A File Has Changed In A Script](git/check-if-a-file-has-changed-in-a-script.md)
|
|
||||||
- [Check If A File Is Under Version Control](git/check-if-a-file-is-under-version-control.md)
|
|
||||||
- [Check What Branches Contain A Specific Commit](git/check-what-branches-contain-a-specific-commit.md)
|
|
||||||
- [Checking Commit Ancestry](git/checking-commit-ancestry.md)
|
- [Checking Commit Ancestry](git/checking-commit-ancestry.md)
|
||||||
- [Checkout Old Version Of A File](git/checkout-old-version-of-a-file.md)
|
- [Checkout Old Version Of A File](git/checkout-old-version-of-a-file.md)
|
||||||
- [Checkout Previous Branch](git/checkout-previous-branch.md)
|
- [Checkout Previous Branch](git/checkout-previous-branch.md)
|
||||||
- [Cherry Pick A Range Of Commits](git/cherry-pick-a-range-of-commits.md)
|
- [Cherry Pick A Range Of Commits](git/cherry-pick-a-range-of-commits.md)
|
||||||
- [Cherry Pick Multiple Commits At Once](git/cherry-pick-multiple-commits-at-once.md)
|
|
||||||
- [Clean Out All Local Branches](git/clean-out-all-local-branches.md)
|
- [Clean Out All Local Branches](git/clean-out-all-local-branches.md)
|
||||||
- [Clean Out Working Copy With Patched Restore](git/clean-out-working-copy-with-patched-restore.md)
|
- [Clean Out Working Copy With Patched Restore](git/clean-out-working-copy-with-patched-restore.md)
|
||||||
- [Clean Up Old Remote Tracking References](git/clean-up-old-remote-tracking-references.md)
|
- [Clean Up Old Remote Tracking References](git/clean-up-old-remote-tracking-references.md)
|
||||||
- [Clear Entries From Git Stash](git/clear-entries-from-git-stash.md)
|
|
||||||
- [Clone A Repo Just For The Files, Without History](git/clone-a-repo-just-for-the-files-without-history.md)
|
- [Clone A Repo Just For The Files, Without History](git/clone-a-repo-just-for-the-files-without-history.md)
|
||||||
- [Clone A Repo Locally From .git](git/clone-a-repo-locally-from-git.md)
|
- [Clone A Repo Locally From .git](git/clone-a-repo-locally-from-git.md)
|
||||||
- [Configure Global gitignore File](git/configure-global-gitignore-file.md)
|
- [Configure Global gitignore File](git/configure-global-gitignore-file.md)
|
||||||
@@ -372,14 +328,11 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Count Number Of Commits On A Branch](git/count-number-of-commits-on-a-branch.md)
|
- [Count Number Of Commits On A Branch](git/count-number-of-commits-on-a-branch.md)
|
||||||
- [Create A New Branch With Git Switch](git/create-a-new-branch-with-git-switch.md)
|
- [Create A New Branch With Git Switch](git/create-a-new-branch-with-git-switch.md)
|
||||||
- [Delete All Untracked Files](git/delete-all-untracked-files.md)
|
- [Delete All Untracked Files](git/delete-all-untracked-files.md)
|
||||||
- [Determine Absolute Path Of Top-Level Project Directory](git/determine-absolute-path-of-top-level-project-directory.md)
|
|
||||||
- [Determine The Hash Id For A Blob](git/determine-the-hash-id-for-a-blob.md)
|
- [Determine The Hash Id For A Blob](git/determine-the-hash-id-for-a-blob.md)
|
||||||
- [Diffing With Patience](git/diffing-with-patience.md)
|
- [Diffing With Patience](git/diffing-with-patience.md)
|
||||||
- [Display All Git Log Entries In My Local Timezone](git/display-all-git-log-entries-in-my-local-timezone.md)
|
|
||||||
- [Dropping Commits With Git Rebase](git/dropping-commits-with-git-rebase.md)
|
- [Dropping Commits With Git Rebase](git/dropping-commits-with-git-rebase.md)
|
||||||
- [Dry Runs in Git](git/dry-runs-in-git.md)
|
- [Dry Runs in Git](git/dry-runs-in-git.md)
|
||||||
- [Exclude A File From A Diff Output](git/exclude-a-file-from-a-diff-output.md)
|
- [Exclude A File From A Diff Output](git/exclude-a-file-from-a-diff-output.md)
|
||||||
- [Exclude A Directory During A Command](git/exclude-a-directory-during-a-command.md)
|
|
||||||
- [Excluding Files Locally](git/excluding-files-locally.md)
|
- [Excluding Files Locally](git/excluding-files-locally.md)
|
||||||
- [Extend Git With Custom Commands](git/extend-git-with-custom-commands.md)
|
- [Extend Git With Custom Commands](git/extend-git-with-custom-commands.md)
|
||||||
- [Files With Local Changes Cannot Be Removed](git/files-with-local-changes-cannot-be-removed.md)
|
- [Files With Local Changes Cannot Be Removed](git/files-with-local-changes-cannot-be-removed.md)
|
||||||
@@ -394,7 +347,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Grep For A Pattern On Another Branch](git/grep-for-a-pattern-on-another-branch.md)
|
- [Grep For A Pattern On Another Branch](git/grep-for-a-pattern-on-another-branch.md)
|
||||||
- [Grep Over Commit Messages](git/grep-over-commit-messages.md)
|
- [Grep Over Commit Messages](git/grep-over-commit-messages.md)
|
||||||
- [Highlight Extra Whitespace In Diff Output](git/highlight-extra-whitespace-in-diff-output.md)
|
- [Highlight Extra Whitespace In Diff Output](git/highlight-extra-whitespace-in-diff-output.md)
|
||||||
- [Highlight Small Change On Single Line](git/highlight-small-change-on-single-line.md)
|
|
||||||
- [Ignore Changes To A Tracked File](git/ignore-changes-to-a-tracked-file.md)
|
- [Ignore Changes To A Tracked File](git/ignore-changes-to-a-tracked-file.md)
|
||||||
- [Ignore Files Specific To Your Workflow](git/ignore-files-specific-to-your-workflow.md)
|
- [Ignore Files Specific To Your Workflow](git/ignore-files-specific-to-your-workflow.md)
|
||||||
- [Include A Message With Your Stashed Changes](git/include-a-message-with-your-stashed-changes.md)
|
- [Include A Message With Your Stashed Changes](git/include-a-message-with-your-stashed-changes.md)
|
||||||
@@ -405,12 +357,8 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Interactively Unstage Changes](git/interactively-unstage-changes.md)
|
- [Interactively Unstage Changes](git/interactively-unstage-changes.md)
|
||||||
- [Keep File Locally With `git rm`](git/keep-file-locally-with-git-rm.md)
|
- [Keep File Locally With `git rm`](git/keep-file-locally-with-git-rm.md)
|
||||||
- [Last Commit A File Appeared In](git/last-commit-a-file-appeared-in.md)
|
- [Last Commit A File Appeared In](git/last-commit-a-file-appeared-in.md)
|
||||||
- [List All Authors On Git Repository](git/list-all-authors-on-git-repository.md)
|
|
||||||
- [List All Commits Where File Was Added Or Deleted](git/list-all-commits-where-file-was-added-or-deleted.md)
|
|
||||||
- [List All Files Added During Span Of Time](git/list-all-files-added-during-span-of-time.md)
|
- [List All Files Added During Span Of Time](git/list-all-files-added-during-span-of-time.md)
|
||||||
- [List All Files Changed Between Two Branches](git/list-all-files-changed-between-two-branches.md)
|
- [List All Files Changed Between Two Branches](git/list-all-files-changed-between-two-branches.md)
|
||||||
- [List All Git Aliases From gitconfig](git/list-all-git-aliases-from-gitconfig.md)
|
|
||||||
- [List And Count All Posts In TIL Repo](git/list-and-count-all-posts-in-til-repo.md)
|
|
||||||
- [List Branches That Contain A Commit](git/list-branches-that-contain-a-commit.md)
|
- [List Branches That Contain A Commit](git/list-branches-that-contain-a-commit.md)
|
||||||
- [List Commits On A Branch](git/list-commits-on-a-branch.md)
|
- [List Commits On A Branch](git/list-commits-on-a-branch.md)
|
||||||
- [List Different Commits Between Two Branches](git/list-different-commits-between-two-branches.md)
|
- [List Different Commits Between Two Branches](git/list-different-commits-between-two-branches.md)
|
||||||
@@ -419,11 +367,9 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [List Most Git Commands](git/list-most-git-commands.md)
|
- [List Most Git Commands](git/list-most-git-commands.md)
|
||||||
- [List Untracked Files](git/list-untracked-files.md)
|
- [List Untracked Files](git/list-untracked-files.md)
|
||||||
- [List Untracked Files For Scripting](git/list-untracked-files-for-scripting.md)
|
- [List Untracked Files For Scripting](git/list-untracked-files-for-scripting.md)
|
||||||
- [Mark A Release With An Annotated Tag](git/mark-a-release-with-an-annotated-tag.md)
|
|
||||||
- [Move The Latest Commit To A New Branch](git/move-the-latest-commit-to-a-new-branch.md)
|
- [Move The Latest Commit To A New Branch](git/move-the-latest-commit-to-a-new-branch.md)
|
||||||
- [Override The Global Git Ignore File](git/override-the-global-git-ignore-file.md)
|
- [Override The Global Git Ignore File](git/override-the-global-git-ignore-file.md)
|
||||||
- [Pick Specific Changes To Stash](git/pick-specific-changes-to-stash.md)
|
- [Pick Specific Changes To Stash](git/pick-specific-changes-to-stash.md)
|
||||||
- [Programmatically Grab SHA For Head Commit](git/programmatically-grab-sha-for-head-commit.md)
|
|
||||||
- [Pulling In Changes During An Interactive Rebase](git/pulling-in-changes-during-an-interactive-rebase.md)
|
- [Pulling In Changes During An Interactive Rebase](git/pulling-in-changes-during-an-interactive-rebase.md)
|
||||||
- [Push To A Branch On Another Remote](git/push-to-a-branch-on-another-remote.md)
|
- [Push To A Branch On Another Remote](git/push-to-a-branch-on-another-remote.md)
|
||||||
- [Quicker Commit Fixes With The Fixup Flag](git/quicker-commit-fixes-with-the-fixup-flag.md)
|
- [Quicker Commit Fixes With The Fixup Flag](git/quicker-commit-fixes-with-the-fixup-flag.md)
|
||||||
@@ -435,12 +381,10 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Renaming A Branch](git/renaming-a-branch.md)
|
- [Renaming A Branch](git/renaming-a-branch.md)
|
||||||
- [Resetting A Reset](git/resetting-a-reset.md)
|
- [Resetting A Reset](git/resetting-a-reset.md)
|
||||||
- [Resolve A Merge Conflict From Stash Pop](git/resolve-a-merge-conflict-from-stash-pop.md)
|
- [Resolve A Merge Conflict From Stash Pop](git/resolve-a-merge-conflict-from-stash-pop.md)
|
||||||
- [Restore File From One Branch To The Current](git/restore-file-from-one-branch-to-the-current.md)
|
|
||||||
- [Review Commits From Before A Certain Date](git/review-commits-from-before-a-certain-date.md)
|
- [Review Commits From Before A Certain Date](git/review-commits-from-before-a-certain-date.md)
|
||||||
- [Run A Git Command From Outside The Repo](git/run-a-git-command-from-outside-the-repo.md)
|
- [Run A Git Command From Outside The Repo](git/run-a-git-command-from-outside-the-repo.md)
|
||||||
- [Set A Custom Pager For A Specific Command](git/set-a-custom-pager-for-a-specific-command.md)
|
- [Set A Custom Pager For A Specific Command](git/set-a-custom-pager-for-a-specific-command.md)
|
||||||
- [Set Default Branch Name For New Repos](git/set-default-branch-name-for-new-repos.md)
|
- [Set Default Branch Name For New Repos](git/set-default-branch-name-for-new-repos.md)
|
||||||
- [Set Up GPG Signing Key](git/set-up-gpg-signing-key.md)
|
|
||||||
- [Shorthand To Force Push A Branch](git/shorthand-to-force-push-a-branch.md)
|
- [Shorthand To Force Push A Branch](git/shorthand-to-force-push-a-branch.md)
|
||||||
- [Show All Commits For A File Beyond Renaming](git/show-all-commits-for-a-file-beyond-renaming.md)
|
- [Show All Commits For A File Beyond Renaming](git/show-all-commits-for-a-file-beyond-renaming.md)
|
||||||
- [Show Changes For Files That Match A Pattern](git/show-changes-for-files-that-match-a-pattern.md)
|
- [Show Changes For Files That Match A Pattern](git/show-changes-for-files-that-match-a-pattern.md)
|
||||||
@@ -448,13 +392,11 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Show File Diffs When Viewing Git Log](git/show-file-diffs-when-viewing-git-log.md)
|
- [Show File Diffs When Viewing Git Log](git/show-file-diffs-when-viewing-git-log.md)
|
||||||
- [Show List Of Most Recently Committed Branches](git/show-list-of-most-recently-committed-branches.md)
|
- [Show List Of Most Recently Committed Branches](git/show-list-of-most-recently-committed-branches.md)
|
||||||
- [Show Only Commits That Touch Specific Lines](git/show-only-commits-that-touch-specific-lines.md)
|
- [Show Only Commits That Touch Specific Lines](git/show-only-commits-that-touch-specific-lines.md)
|
||||||
- [Show Summary Stats For Current Branch](git/show-summary-stats-for-current-branch.md)
|
|
||||||
- [Show The diffstat Summary Of A Commit](git/show-the-diffstat-summary-of-a-commit.md)
|
- [Show The diffstat Summary Of A Commit](git/show-the-diffstat-summary-of-a-commit.md)
|
||||||
- [Show The Good And The Bad With Git Bisect](git/show-the-good-and-the-bad-with-git-bisect.md)
|
- [Show The Good And The Bad With Git Bisect](git/show-the-good-and-the-bad-with-git-bisect.md)
|
||||||
- [Show What Is In A Stash](git/show-what-is-in-a-stash.md)
|
- [Show What Is In A Stash](git/show-what-is-in-a-stash.md)
|
||||||
- [Single Key Presses in Interactive Mode](git/single-key-presses-in-interactive-mode.md)
|
- [Single Key Presses in Interactive Mode](git/single-key-presses-in-interactive-mode.md)
|
||||||
- [Skip A Bad Commit When Bisecting](git/skip-a-bad-commit-when-bisecting.md)
|
- [Skip A Bad Commit When Bisecting](git/skip-a-bad-commit-when-bisecting.md)
|
||||||
- [Skip Git Hooks As Needed](git/skip-git-hooks-as-needed.md)
|
|
||||||
- [Skip Pre-Commit Hooks](git/skip-pre-commit-hooks.md)
|
- [Skip Pre-Commit Hooks](git/skip-pre-commit-hooks.md)
|
||||||
- [Staging Changes Within Vim](git/staging-changes-within-vim.md)
|
- [Staging Changes Within Vim](git/staging-changes-within-vim.md)
|
||||||
- [Staging Stashes Interactively](git/staging-stashes-interactively.md)
|
- [Staging Stashes Interactively](git/staging-stashes-interactively.md)
|
||||||
@@ -462,12 +404,10 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Stash Everything](git/stash-everything.md)
|
- [Stash Everything](git/stash-everything.md)
|
||||||
- [Stashing Only Unstaged Changes](git/stashing-only-unstaged-changes.md)
|
- [Stashing Only Unstaged Changes](git/stashing-only-unstaged-changes.md)
|
||||||
- [Stashing Untracked Files](git/stashing-untracked-files.md)
|
- [Stashing Untracked Files](git/stashing-untracked-files.md)
|
||||||
- [Summarize Amount Of Change For Specific Commit](git/summarize-amount-of-change-for-specific-commit.md)
|
|
||||||
- [Switch To A Recent Branch With FZF](git/switch-to-a-recent-branch-with-fzf.md)
|
- [Switch To A Recent Branch With FZF](git/switch-to-a-recent-branch-with-fzf.md)
|
||||||
- [Transition A Branch From One Base To Another](git/transition-a-branch-from-one-base-to-another.md)
|
- [Transition A Branch From One Base To Another](git/transition-a-branch-from-one-base-to-another.md)
|
||||||
- [Turn Off The Output Pager For One Command](git/turn-off-the-output-pager-for-one-command.md)
|
- [Turn Off The Output Pager For One Command](git/turn-off-the-output-pager-for-one-command.md)
|
||||||
- [Two Kinds Of Dotted Range Notation](git/two-kinds-of-dotted-range-notation.md)
|
- [Two Kinds Of Dotted Range Notation](git/two-kinds-of-dotted-range-notation.md)
|
||||||
- [Undo Latest Changes Committed To Specific File](git/undo-latest-changes-committed-to-specific-file.md)
|
|
||||||
- [Unstage Changes Wih Git Restore](git/unstage-changes-with-git-restore.md)
|
- [Unstage Changes Wih Git Restore](git/unstage-changes-with-git-restore.md)
|
||||||
- [Untrack A Directory Of Files Without Deleting](git/untrack-a-directory-of-files-without-deleting.md)
|
- [Untrack A Directory Of Files Without Deleting](git/untrack-a-directory-of-files-without-deleting.md)
|
||||||
- [Untrack A File Without Deleting It](git/untrack-a-file-without-deleting-it.md)
|
- [Untrack A File Without Deleting It](git/untrack-a-file-without-deleting-it.md)
|
||||||
@@ -480,27 +420,12 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [What Is The Current Branch?](git/what-is-the-current-branch.md)
|
- [What Is The Current Branch?](git/what-is-the-current-branch.md)
|
||||||
- [Whitespace Warnings](git/whitespace-warnings.md)
|
- [Whitespace Warnings](git/whitespace-warnings.md)
|
||||||
|
|
||||||
### GitHub
|
|
||||||
|
|
||||||
- [Access Your GitHub Profile Photo](github/access-your-github-profile-photo.md)
|
|
||||||
- [Create A Private Repo From The CLI](github/create-a-private-repo-from-the-cli.md)
|
|
||||||
- [Create And Push To New Repo From CLI](github/create-and-push-to-new-repo-from-cli.md)
|
|
||||||
- [List PRs Awaiting Your Review](github/list-prs-awaiting-your-review.md)
|
|
||||||
- [Open A PR To An Unforked Repo](github/open-a-pr-to-an-unforked-repo.md)
|
|
||||||
- [Open File To Specific Line In Browser](github/open-file-to-specific-line-in-browser.md)
|
|
||||||
- [Process JSON Output From gh With jq](github/process-json-output-from-gh-with-jq.md)
|
|
||||||
- [Rerun Failed Jobs For Current Branch](github/rerun-failed-jobs-for-current-branch.md)
|
|
||||||
- [Target Another Repo When Creating A PR](github/target-another-repo-when-creating-a-pr.md)
|
|
||||||
- [Tell gh What The Default Repo Is](github/tell-gh-what-the-default-repo-is.md)
|
|
||||||
|
|
||||||
### GitHub Actions
|
### GitHub Actions
|
||||||
|
|
||||||
- [Cache Playwright Dependencies Across Workflows](github-actions/cache-playwright-dependencies-across-workflows.md)
|
- [Cache Playwright Dependencies Across Workflows](github-actions/cache-playwright-dependencies-across-workflows.md)
|
||||||
- [Capture An Output Value For Use In A Later Step](github-actions/capture-an-output-value-for-use-in-a-later-step.md)
|
- [Capture An Output Value For Use In A Later Step](github-actions/capture-an-output-value-for-use-in-a-later-step.md)
|
||||||
- [Disable A Workflow With The gh CLI](github-actions/disable-a-workflow-with-the-gh-cli.md)
|
- [Disable A Workflow With The gh CLI](github-actions/disable-a-workflow-with-the-gh-cli.md)
|
||||||
- [Reference An Encrypted Secret In An Action](github-actions/reference-an-encrypted-secret-in-an-action.md)
|
- [Reference An Encrypted Secret In An Action](github-actions/reference-an-encrypted-secret-in-an-action.md)
|
||||||
- [Run Schedule Action To Commit Regular Updates](github-actions/run-scheduled-action-to-commit-regular-updates.md)
|
|
||||||
- [Set Repository Secret From CLI](github-actions/set-repository-secret-from-cli.md)
|
|
||||||
- [Trigger A Workflow Via An API Call](github-actions/trigger-a-workflow-via-an-api-call.md)
|
- [Trigger A Workflow Via An API Call](github-actions/trigger-a-workflow-via-an-api-call.md)
|
||||||
- [Use Labels To Block PR Merge](github-actions/use-labels-to-block-pr-merge.md)
|
- [Use Labels To Block PR Merge](github-actions/use-labels-to-block-pr-merge.md)
|
||||||
|
|
||||||
@@ -542,20 +467,17 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
|
|
||||||
### Heroku
|
### Heroku
|
||||||
|
|
||||||
- [Check Ruby Version For Production App](heroku/check-ruby-version-for-production-app.md)
|
|
||||||
- [Connect To A Database By Color](heroku/connect-to-a-database-by-color.md)
|
- [Connect To A Database By Color](heroku/connect-to-a-database-by-color.md)
|
||||||
- [Deploy A Review App To A Different Stack](heroku/deploy-a-review-app-to-a-different-stack.md)
|
- [Deploy A Review App To A Different Stack](heroku/deploy-a-review-app-to-a-different-stack.md)
|
||||||
- [Diagnose Problems In A Heroku Postgres Database](heroku/diagnose-problems-in-a-heroku-postgres-database.md)
|
- [Diagnose Problems In A Heroku Postgres Database](heroku/diagnose-problems-in-a-heroku-postgres-database.md)
|
||||||
- [Open Dashboard For Specific Add-On](heroku/open-dashboard-for-specific-add-on.md)
|
- [Open Dashboard For Specific Add-On](heroku/open-dashboard-for-specific-add-on.md)
|
||||||
- [Run SQL Against Remote Postgres Database](heroku/run-sql-against-remote-postgres-database.md)
|
- [Run SQL Against Remote Postgres Database](heroku/run-sql-against-remote-postgres-database.md)
|
||||||
- [Set And Show Heroku Env Variables](heroku/set-and-show-heroku-env-variables.md)
|
- [Set And Show Heroku Env Variables](heroku/set-and-show-heroku-env-variables.md)
|
||||||
- [Specify Default Team And App For Project](heroku/specify-default-team-and-app-for-project.md)
|
|
||||||
- [SSH Into Heroku Server Hosting App](heroku/ssh-into-heroku-server-hosting-app.md)
|
- [SSH Into Heroku Server Hosting App](heroku/ssh-into-heroku-server-hosting-app.md)
|
||||||
|
|
||||||
### HTML
|
### HTML
|
||||||
|
|
||||||
- [Adding Alt Text To An Image](html/adding-alt-text-to-an-image.md)
|
- [Adding Alt Text To An Image](html/adding-alt-text-to-an-image.md)
|
||||||
- [Allow Number Input To Accept Decimal Values](html/allow-number-input-to-accept-decimal-values.md)
|
|
||||||
- [Determine Which Button Submitted The Form](html/determine-which-button-submitted-the-form.md)
|
- [Determine Which Button Submitted The Form](html/determine-which-button-submitted-the-form.md)
|
||||||
- [Disable Auto-Completion For A Form Input](html/disable-auto-completion-for-a-form-input.md)
|
- [Disable Auto-Completion For A Form Input](html/disable-auto-completion-for-a-form-input.md)
|
||||||
- [Disclose Additional Details](html/disclose-additional-details.md)
|
- [Disclose Additional Details](html/disclose-additional-details.md)
|
||||||
@@ -588,7 +510,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Focus The URL Bar](internet/focus-the-url-bar.md)
|
- [Focus The URL Bar](internet/focus-the-url-bar.md)
|
||||||
- [Get Random Images From Unsplash](internet/get-random-images-from-unsplash.md)
|
- [Get Random Images From Unsplash](internet/get-random-images-from-unsplash.md)
|
||||||
- [Grab The RSS Feed For A Substack Blog](internet/grab-the-rss-feed-for-a-substack-blog.md)
|
- [Grab The RSS Feed For A Substack Blog](internet/grab-the-rss-feed-for-a-substack-blog.md)
|
||||||
- [Hide Overflowing Text For Google Sheets Column](internet/hide-overflowing-text-for-google-sheets-column.md)
|
|
||||||
- [Search Tweets By Author](internet/search-tweets-by-author.md)
|
- [Search Tweets By Author](internet/search-tweets-by-author.md)
|
||||||
- [Show All Pivotal Stories With Blockers](internet/show-all-pivotal-stories-with-blockers.md)
|
- [Show All Pivotal Stories With Blockers](internet/show-all-pivotal-stories-with-blockers.md)
|
||||||
- [Verify Site Ownership With DNS Record](internet/verify-site-ownership-with-dns-record.md)
|
- [Verify Site Ownership With DNS Record](internet/verify-site-ownership-with-dns-record.md)
|
||||||
@@ -631,12 +552,10 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Easy Date Comparison With DayJS](javascript/easy-date-comparison-with-dayjs.md)
|
- [Easy Date Comparison With DayJS](javascript/easy-date-comparison-with-dayjs.md)
|
||||||
- [Expand Emojis With The Spread Operator](javascript/expand-emojis-with-the-spread-operator.md)
|
- [Expand Emojis With The Spread Operator](javascript/expand-emojis-with-the-spread-operator.md)
|
||||||
- [Fill An Input With A Ton Of Text](javascript/fill-an-input-with-a-ton-of-text.md)
|
- [Fill An Input With A Ton Of Text](javascript/fill-an-input-with-a-ton-of-text.md)
|
||||||
- [Filter By Truthy Values With Boolean Function](javascript/filter-by-truthy-values-with-boolean-function.md)
|
|
||||||
- [Find The Version Of An Installed Dependency](javascript/find-the-version-of-an-installed-dependency.md)
|
- [Find The Version Of An Installed Dependency](javascript/find-the-version-of-an-installed-dependency.md)
|
||||||
- [Find Where Yarn Is Installing Binaries](javascript/find-where-yarn-is-installing-binaries.md)
|
- [Find Where Yarn Is Installing Binaries](javascript/find-where-yarn-is-installing-binaries.md)
|
||||||
- [for...in Iterates Over Object Properties](javascript/for-in-iterates-over-object-properties.md)
|
- [for...in Iterates Over Object Properties](javascript/for-in-iterates-over-object-properties.md)
|
||||||
- [Format A Decimal To A Fixed Number Of Digits](javascript/format-a-decimal-to-a-fixed-number-of-digits.md)
|
- [Format A Decimal To A Fixed Number Of Digits](javascript/format-a-decimal-to-a-fixed-number-of-digits.md)
|
||||||
- [Format A List Of Items By Locale](javascript/format-a-list-of-items-by-locale.md)
|
|
||||||
- [Format Time Zone Identifier](javascript/format-time-zone-identifier.md)
|
- [Format Time Zone Identifier](javascript/format-time-zone-identifier.md)
|
||||||
- [Formatting Values With Units For Display](javascript/formatting-values-with-units-for-display.md)
|
- [Formatting Values With Units For Display](javascript/formatting-values-with-units-for-display.md)
|
||||||
- [Freeze An Object, Sorta](javascript/freeze-an-object-sorta.md)
|
- [Freeze An Object, Sorta](javascript/freeze-an-object-sorta.md)
|
||||||
@@ -646,7 +565,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Get The Response Status From An Axios Error](javascript/get-the-response-status-from-an-axios-error.md)
|
- [Get The Response Status From An Axios Error](javascript/get-the-response-status-from-an-axios-error.md)
|
||||||
- [Get The Time Components Of A Date](javascript/get-the-time-components-of-a-date.md)
|
- [Get The Time Components Of A Date](javascript/get-the-time-components-of-a-date.md)
|
||||||
- [Get The Time Zone Of The Client Computer](javascript/get-the-time-zone-of-the-client-computer.md)
|
- [Get The Time Zone Of The Client Computer](javascript/get-the-time-zone-of-the-client-computer.md)
|
||||||
- [Get User's Preferred Language From Browser](javascript/get-users-preferred-language-from-browser.md)
|
|
||||||
- [Globally Install A Package With Yarn](javascript/globally-install-a-package-with-yarn.md)
|
- [Globally Install A Package With Yarn](javascript/globally-install-a-package-with-yarn.md)
|
||||||
- [Globally Install Specific Version Of PNPM](javascript/globally-install-specific-version-of-pnpm.md)
|
- [Globally Install Specific Version Of PNPM](javascript/globally-install-specific-version-of-pnpm.md)
|
||||||
- [Immutable Remove With The Spread Operator](javascript/immutable-remove-with-the-spread-operator.md)
|
- [Immutable Remove With The Spread Operator](javascript/immutable-remove-with-the-spread-operator.md)
|
||||||
@@ -663,7 +581,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Matching Multiple Values In A Switch Statement](javascript/matching-multiple-values-in-a-switch-statement.md)
|
- [Matching Multiple Values In A Switch Statement](javascript/matching-multiple-values-in-a-switch-statement.md)
|
||||||
- [Mock A Function With Return Values Using Jest](javascript/mock-a-function-with-return-values-using-jest.md)
|
- [Mock A Function With Return Values Using Jest](javascript/mock-a-function-with-return-values-using-jest.md)
|
||||||
- [New Dates Can Take Out Of Bounds Values](javascript/new-dates-can-take-out-of-bounds-values.md)
|
- [New Dates Can Take Out Of Bounds Values](javascript/new-dates-can-take-out-of-bounds-values.md)
|
||||||
- [`npm run` Has Some Typo Aliases](javascript/npm-run-has-some-typo-aliases.md)
|
|
||||||
- [Numbers Are Empty](javascript/numbers-are-empty.md)
|
- [Numbers Are Empty](javascript/numbers-are-empty.md)
|
||||||
- [Object Initialization With Shorthand Property Names](javascript/object-initialization-with-shorthand-property-names.md)
|
- [Object Initialization With Shorthand Property Names](javascript/object-initialization-with-shorthand-property-names.md)
|
||||||
- [Obtain Undefined Value With The Void Operator](javascript/obtain-undefined-value-with-the-void-operator.md)
|
- [Obtain Undefined Value With The Void Operator](javascript/obtain-undefined-value-with-the-void-operator.md)
|
||||||
@@ -712,9 +629,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
### jj
|
### jj
|
||||||
|
|
||||||
- [Colocate jj And git Directories For Project](jj/colocate-jj-and-git-directories-for-project.md)
|
- [Colocate jj And git Directories For Project](jj/colocate-jj-and-git-directories-for-project.md)
|
||||||
- [Describe Current Changes And Create New Change](jj/describe-current-changes-and-create-new-change.md)
|
|
||||||
- [Find System-wide Config File For User](jj/find-system-wide-config-file-for-user.md)
|
- [Find System-wide Config File For User](jj/find-system-wide-config-file-for-user.md)
|
||||||
- [Squash Changes Into Parent Commit Interactively](jj/squash-changes-into-parent-commit-interactively.md)
|
|
||||||
|
|
||||||
### jq
|
### jq
|
||||||
|
|
||||||
@@ -748,53 +663,33 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
|
|
||||||
### LLM
|
### LLM
|
||||||
|
|
||||||
- [Count Number Of Tokens In A File](llm/count-number-of-tokens-in-a-file.md)
|
|
||||||
- [Generate Image Alt Text Across Claude Models](llm/generate-image-alt-text-across-claude-models.md)
|
|
||||||
- [Include A File With Message To `ant`](llm/include-a-file-with-message-to-ant.md)
|
|
||||||
- [Send cURL To Claude Text Completion API](llm/send-curl-to-claude-text-completion-api.md)
|
- [Send cURL To Claude Text Completion API](llm/send-curl-to-claude-text-completion-api.md)
|
||||||
- [Translate To Canonical Tags With Small Model](llm/translate-to-canonical-tags-with-small-model.md)
|
|
||||||
- [Use The llm CLI With Claude Models](llm/use-the-llm-cli-with-claude-models.md)
|
- [Use The llm CLI With Claude Models](llm/use-the-llm-cli-with-claude-models.md)
|
||||||
|
|
||||||
### Logseq
|
|
||||||
|
|
||||||
- [Access Daily Journal From CLI With HTTP Server](logseq/access-daily-journal-from-cli-with-http-server.md)
|
|
||||||
|
|
||||||
### Mac
|
### Mac
|
||||||
|
|
||||||
- [Access All Screen And Video Capture Options](mac/access-all-screen-and-video-capture-options.md)
|
- [Access All Screen And Video Capture Options](mac/access-all-screen-and-video-capture-options.md)
|
||||||
- [Access CoreUtils That Conflict With Unix Utilities](mac/access-coreutils-that-conflict-with-unix-utilities.md)
|
|
||||||
- [Access System Information On OS X](mac/access-system-information-on-osx.md)
|
- [Access System Information On OS X](mac/access-system-information-on-osx.md)
|
||||||
- [Access Unsupported Screen Resolutions With RDM](mac/access-unsupported-screen-resolutions-with-rdm.md)
|
- [Access Unsupported Screen Resolutions With RDM](mac/access-unsupported-screen-resolutions-with-rdm.md)
|
||||||
- [Add A Bunch Of CLI Utilities With coreutils](mac/add-a-bunch-of-cli-utilities-with-coreutils.md)
|
|
||||||
- [Capture Screenshot To Clipboard From CLI](mac/capture-screenshot-to-clipboard-from-cli.md)
|
|
||||||
- [Check Network Quality Stats From The Command Line](mac/check-network-quality-stats-from-the-command-line.md)
|
- [Check Network Quality Stats From The Command Line](mac/check-network-quality-stats-from-the-command-line.md)
|
||||||
- [Clean Up Item Layout In Finder Window](mac/clean-up-item-layout-in-finder-window.md)
|
|
||||||
- [Clean Up Old Homebrew Files](mac/clean-up-old-homebrew-files.md)
|
- [Clean Up Old Homebrew Files](mac/clean-up-old-homebrew-files.md)
|
||||||
- [Control Which Monitor App Switcher Appears On](mac/control-which-monitor-app-switcher-appears-on.md)
|
|
||||||
- [Convert An HEIC Image File To JPG](mac/convert-an-heic-image-file-to-jpg.md)
|
- [Convert An HEIC Image File To JPG](mac/convert-an-heic-image-file-to-jpg.md)
|
||||||
- [Default Screenshot Location](mac/default-screenshot-location.md)
|
- [Default Screenshot Location](mac/default-screenshot-location.md)
|
||||||
- [Detect How Long A User Has Been Idle](mac/detect-how-long-a-user-has-been-idle.md)
|
|
||||||
- [Disable Swipe Navigation For A Specific App](mac/disable-swipe-navigation-for-a-specific-app.md)
|
- [Disable Swipe Navigation For A Specific App](mac/disable-swipe-navigation-for-a-specific-app.md)
|
||||||
- [Display A Message With Alfred](mac/display-a-message-with-alfred.md)
|
- [Display A Message With Alfred](mac/display-a-message-with-alfred.md)
|
||||||
- [Find The Process Using A Specific Port](mac/find-the-process-using-a-specific-port.md)
|
- [Find The Process Using A Specific Port](mac/find-the-process-using-a-specific-port.md)
|
||||||
- [Gesture For Viewing All Windows Of Current App](mac/gesture-for-viewing-all-windows-of-current-app.md)
|
- [Gesture For Viewing All Windows Of Current App](mac/gesture-for-viewing-all-windows-of-current-app.md)
|
||||||
- [Insert A Non-Breaking Space Character](mac/insert-a-non-breaking-space-character.md)
|
- [Insert A Non-Breaking Space Character](mac/insert-a-non-breaking-space-character.md)
|
||||||
- [Inspect Assertions Preventing Sleep](mac/inspect-assertions-preventing-sleep.md)
|
|
||||||
- [Keyboard Shortcuts For Interesting With Text Areas](mac/keyboard-shortcuts-for-interacting-with-text-areas.md)
|
- [Keyboard Shortcuts For Interesting With Text Areas](mac/keyboard-shortcuts-for-interacting-with-text-areas.md)
|
||||||
- [Launch Some Confetti](mac/launch-some-confetti.md)
|
|
||||||
- [List All The Say Voices](mac/list-all-the-say-voices.md)
|
- [List All The Say Voices](mac/list-all-the-say-voices.md)
|
||||||
- [Open Finder.app To Specific Directory](mac/open-finder-app-to-specific-directory.md)
|
- [Open Finder.app To Specific Directory](mac/open-finder-app-to-specific-directory.md)
|
||||||
- [Prevent Sleep With The Caffeinate Command](mac/prevent-sleep-with-the-caffeinate-command.md)
|
|
||||||
- [Quickly Type En Dashes And Em Dashes](mac/quickly-type-en-dashes-and-em-dashes.md)
|
- [Quickly Type En Dashes And Em Dashes](mac/quickly-type-en-dashes-and-em-dashes.md)
|
||||||
- [Read The Lid Angle Sensor For A MacBook](mac/read-the-lid-angle-sensor-for-a-macbook.md)
|
|
||||||
- [Require Additional JS Libraries In Postman](mac/require-additional-js-libraries-in-postman.md)
|
- [Require Additional JS Libraries In Postman](mac/require-additional-js-libraries-in-postman.md)
|
||||||
- [Resize App Windows With AppleScript](mac/resize-app-windows-with-applescript.md)
|
- [Resize App Windows With AppleScript](mac/resize-app-windows-with-applescript.md)
|
||||||
- [Resizing Both Corners Of A Window](mac/resizing-both-corners-of-a-window.md)
|
- [Resizing Both Corners Of A Window](mac/resizing-both-corners-of-a-window.md)
|
||||||
- [Reveal Location Of File In Finder.app](mac/reveal-location-of-file-in-finder-app.md)
|
|
||||||
- [Run A Hardware Check](mac/run-a-hardware-check.md)
|
- [Run A Hardware Check](mac/run-a-hardware-check.md)
|
||||||
- [Run AppleScript Commands Inline In The Terminal](mac/run-applescript-commands-inline-in-the-terminal.md)
|
- [Run AppleScript Commands Inline In The Terminal](mac/run-applescript-commands-inline-in-the-terminal.md)
|
||||||
- [Set A Window To Its Default Zoom Level](mac/set-a-window-to-its-default-zoom-level.md)
|
- [Set A Window To Its Default Zoom Level](mac/set-a-window-to-its-default-zoom-level.md)
|
||||||
- [Set Default Search Directory For Finder](mac/set-default-search-directory-for-finder.md)
|
|
||||||
- [Specify App When Opening From Command Line](mac/specify-app-when-opening-from-command-line.md)
|
- [Specify App When Opening From Command Line](mac/specify-app-when-opening-from-command-line.md)
|
||||||
- [Start Amphetamine Session With AppleScript](mac/start-amphetamine-session-with-applescript.md)
|
- [Start Amphetamine Session With AppleScript](mac/start-amphetamine-session-with-applescript.md)
|
||||||
- [Uninstall LogiTech G Hub From Mac](mac/uninstall-logitech-g-hub-from-mac.md)
|
- [Uninstall LogiTech G Hub From Mac](mac/uninstall-logitech-g-hub-from-mac.md)
|
||||||
@@ -803,22 +698,13 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [View All Windows Of The Current App](mac/view-all-windows-of-the-current-app.md)
|
- [View All Windows Of The Current App](mac/view-all-windows-of-the-current-app.md)
|
||||||
- [Write System Clipboard To A File](mac/write-system-clipboard-to-a-file.md)
|
- [Write System Clipboard To A File](mac/write-system-clipboard-to-a-file.md)
|
||||||
|
|
||||||
### Math
|
|
||||||
|
|
||||||
- [Convert Arbitrary Number To Probability With Sigmoid](math/convert-arbitrary-number-to-probability-with-sigmoid.md)
|
|
||||||
- [Generate Permutations Of All Valid 9-ball Racks](math/generate-permutations-of-all-valid-9-ball-racks.md)
|
|
||||||
|
|
||||||
### Mise
|
### Mise
|
||||||
|
|
||||||
- [Create Umbrella Task For All Test Tasks](mise/create-umbrella-task-for-all-test-tasks.md)
|
- [Create Umbrella Task For All Test Tasks](mise/create-umbrella-task-for-all-test-tasks.md)
|
||||||
- [List The Files Being Loaded By Mise](mise/list-the-files-being-loaded-by-mise.md)
|
- [List The Files Being Loaded By Mise](mise/list-the-files-being-loaded-by-mise.md)
|
||||||
- [Look In Ruby Version Dotfile](mise/look-in-ruby-version-dotfile.md)
|
|
||||||
- [Override Your Project Mise File](mise/override-your-project-mise-file.md)
|
|
||||||
- [Pick From Tasks Using Interactive Picker](mise/pick-from-tasks-using-interactive-picker.md)
|
|
||||||
- [Preserve Color Output For Task Command](mise/preserve-color-output-for-task-command.md)
|
- [Preserve Color Output For Task Command](mise/preserve-color-output-for-task-command.md)
|
||||||
- [Read Existing Dot Env File Into Env Vars](mise/read-existing-dot-env-file-into-env-vars.md)
|
- [Read Existing Dot Env File Into Env Vars](mise/read-existing-dot-env-file-into-env-vars.md)
|
||||||
- [Run A Command With Specific Tool Version](mise/run-a-command-with-specific-tool-version.md)
|
- [Run A Command With Specific Tool Version](mise/run-a-command-with-specific-tool-version.md)
|
||||||
- [Search Through Bin Paths For Tool Locations](mise/search-through-bin-paths-for-tool-locations.md)
|
|
||||||
|
|
||||||
### MongoDB
|
### MongoDB
|
||||||
|
|
||||||
@@ -837,7 +723,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Doing Date Math](mysql/doing-date-math.md)
|
- [Doing Date Math](mysql/doing-date-math.md)
|
||||||
- [Dump A Database To A File](mysql/dump-a-database-to-a-file.md)
|
- [Dump A Database To A File](mysql/dump-a-database-to-a-file.md)
|
||||||
- [Echo A Message From A SQL File](mysql/echo-a-message-from-a-sql-file.md)
|
- [Echo A Message From A SQL File](mysql/echo-a-message-from-a-sql-file.md)
|
||||||
- [Get Idea Of What Is In A JSON Column](mysql/get-idea-of-what-is-in-a-json-column.md)
|
|
||||||
- [Ignore Duplicates When Inserting Records](mysql/ignore-duplicates-when-inserting-records.md)
|
- [Ignore Duplicates When Inserting Records](mysql/ignore-duplicates-when-inserting-records.md)
|
||||||
- [List Databases And Tables](mysql/list-databases-and-tables.md)
|
- [List Databases And Tables](mysql/list-databases-and-tables.md)
|
||||||
- [Run Statements In A Transaction](mysql/run-statements-in-a-transaction.md)
|
- [Run Statements In A Transaction](mysql/run-statements-in-a-transaction.md)
|
||||||
@@ -851,9 +736,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
|
|
||||||
- [Allow Neovim To Copy/Paste With System Clipboard](neovim/allow-neovim-to-copy-paste-with-system-clipboard.md)
|
- [Allow Neovim To Copy/Paste With System Clipboard](neovim/allow-neovim-to-copy-paste-with-system-clipboard.md)
|
||||||
- [Create User Command To Open Init Config](neovim/create-user-command-to-open-init-config.md)
|
- [Create User Command To Open Init Config](neovim/create-user-command-to-open-init-config.md)
|
||||||
- [Jump Between Changes In Current File](neovim/jump-between-changes-in-current-file.md)
|
|
||||||
- [Run A Lua Statement From The Command Prompt](neovim/run-a-lua-statement-from-the-command-prompt.md)
|
- [Run A Lua Statement From The Command Prompt](neovim/run-a-lua-statement-from-the-command-prompt.md)
|
||||||
- [Run nvim With Factory Defaults](neovim/run-nvim-with-factory-defaults.md)
|
|
||||||
- [Set Up Vim-Plug With Neovim](neovim/set-up-vim-plug-with-neovim.md)
|
- [Set Up Vim-Plug With Neovim](neovim/set-up-vim-plug-with-neovim.md)
|
||||||
|
|
||||||
### Netlify
|
### Netlify
|
||||||
@@ -891,12 +774,10 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
|
|
||||||
### Planetscale
|
### Planetscale
|
||||||
|
|
||||||
- [See What Databases You Have Access To](planetscale/see-what-databases-you-have-access-to.md)
|
|
||||||
- [Seed Production Data Into Another Branch](planetscale/seed-production-data-into-another-branch.md)
|
- [Seed Production Data Into Another Branch](planetscale/seed-production-data-into-another-branch.md)
|
||||||
|
|
||||||
### pnpm
|
### pnpm
|
||||||
|
|
||||||
- [Avoid Vulnerabilities In New Package Versions](pnpm/avoid-vulnerabilities-in-new-package-versions.md)
|
|
||||||
- [Execute A Command From The Workspace Root](pnpm/execute-a-command-from-the-workspace-root.md)
|
- [Execute A Command From The Workspace Root](pnpm/execute-a-command-from-the-workspace-root.md)
|
||||||
- [Install Command Runs For Entire Workspace](pnpm/install-command-runs-for-entire-workspace.md)
|
- [Install Command Runs For Entire Workspace](pnpm/install-command-runs-for-entire-workspace.md)
|
||||||
- [List The Installed Version Of A Specific Package](pnpm/list-the-installed-version-of-a-specific-package.md)
|
- [List The Installed Version Of A Specific Package](pnpm/list-the-installed-version-of-a-specific-package.md)
|
||||||
@@ -918,14 +799,12 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Check If Clusters Are Upgrade Compatible](postgres/check-if-clusters-are-upgrade-compatible.md)
|
- [Check If Clusters Are Upgrade Compatible](postgres/check-if-clusters-are-upgrade-compatible.md)
|
||||||
- [Check If The Local Server Is Running](postgres/check-if-the-local-server-is-running.md)
|
- [Check If The Local Server Is Running](postgres/check-if-the-local-server-is-running.md)
|
||||||
- [Check If User Role Exists For Database](postgres/check-if-user-role-exists-for-database.md)
|
- [Check If User Role Exists For Database](postgres/check-if-user-role-exists-for-database.md)
|
||||||
- [Check Table For Any Oprhaned Records](postgres/check-table-for-any-orphaned-records.md)
|
- [Check Table For Any Orphaned Records](postgres/check-table-for-any-orphaned-records.md)
|
||||||
- [Check The Size Of Databases In A Cluster](postgres/check-the-size-of-databases-in-a-cluster.md)
|
|
||||||
- [Checking Inequality](postgres/checking-inequality.md)
|
- [Checking Inequality](postgres/checking-inequality.md)
|
||||||
- [Checking The Type Of A Value](postgres/checking-the-type-of-a-value.md)
|
- [Checking The Type Of A Value](postgres/checking-the-type-of-a-value.md)
|
||||||
- [Clear The Screen In psql](postgres/clear-the-screen-in-psql.md)
|
- [Clear The Screen In psql](postgres/clear-the-screen-in-psql.md)
|
||||||
- [Clear The Screen In psql (2)](postgres/clear-the-screen-in-psql-2.md)
|
- [Clear The Screen In psql (2)](postgres/clear-the-screen-in-psql-2.md)
|
||||||
- [Compute Hashes With pgcrypto](postgres/compute-hashes-with-pgcrypto.md)
|
- [Compute Hashes With pgcrypto](postgres/compute-hashes-with-pgcrypto.md)
|
||||||
- [Compute Median Instead Of Average](postgres/compute-median-instead-of-average.md)
|
|
||||||
- [Compute The Levenshtein Distance Of Two Strings](postgres/compute-the-levenshtein-distance-of-two-strings.md)
|
- [Compute The Levenshtein Distance Of Two Strings](postgres/compute-the-levenshtein-distance-of-two-strings.md)
|
||||||
- [Compute The md5 Hash Of A String](postgres/compute-the-md5-hash-of-a-string.md)
|
- [Compute The md5 Hash Of A String](postgres/compute-the-md5-hash-of-a-string.md)
|
||||||
- [Concatenate Strings With A Separator](postgres/concatenate-strings-with-a-separator.md)
|
- [Concatenate Strings With A Separator](postgres/concatenate-strings-with-a-separator.md)
|
||||||
@@ -1025,7 +904,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Prevent A Query From Running Too Long](postgres/prevent-a-query-from-running-too-long.md)
|
- [Prevent A Query From Running Too Long](postgres/prevent-a-query-from-running-too-long.md)
|
||||||
- [Print The Query Buffer In psql](postgres/print-the-query-buffer-in-psql.md)
|
- [Print The Query Buffer In psql](postgres/print-the-query-buffer-in-psql.md)
|
||||||
- [Put Unique Constraint On Generated Column](postgres/put-unique-constraint-on-generated-column.md)
|
- [Put Unique Constraint On Generated Column](postgres/put-unique-constraint-on-generated-column.md)
|
||||||
- [References Target Primary Key By Default](postgres/references-target-primary-key-by-default.md)
|
|
||||||
- [Remove Not Null Constraint From A Column](postgres/remove-not-null-constraint-from-a-column.md)
|
- [Remove Not Null Constraint From A Column](postgres/remove-not-null-constraint-from-a-column.md)
|
||||||
- [Renaming A Sequence](postgres/renaming-a-sequence.md)
|
- [Renaming A Sequence](postgres/renaming-a-sequence.md)
|
||||||
- [Renaming A Table](postgres/renaming-a-table.md)
|
- [Renaming A Table](postgres/renaming-a-table.md)
|
||||||
@@ -1033,11 +911,9 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Restarting Sequences When Truncating Tables](postgres/restarting-sequences-when-truncating-tables.md)
|
- [Restarting Sequences When Truncating Tables](postgres/restarting-sequences-when-truncating-tables.md)
|
||||||
- [Salt And Hash A Password With pgcrypto](postgres/salt-and-hash-a-password-with-pgcrypto.md)
|
- [Salt And Hash A Password With pgcrypto](postgres/salt-and-hash-a-password-with-pgcrypto.md)
|
||||||
- [Send A Command To psql](postgres/send-a-command-to-psql.md)
|
- [Send A Command To psql](postgres/send-a-command-to-psql.md)
|
||||||
- [Sequence Side-Effect When Rolling Back Inserts](postgres/sequence-side-effect-when-rolling-back-inserts.md)
|
|
||||||
- [Set Inclusion With hstore](postgres/set-inclusion-with-hstore.md)
|
- [Set Inclusion With hstore](postgres/set-inclusion-with-hstore.md)
|
||||||
- [Set A Seed For The Random Number Generator](postgres/set-a-seed-for-the-random-number-generator.md)
|
- [Set A Seed For The Random Number Generator](postgres/set-a-seed-for-the-random-number-generator.md)
|
||||||
- [Set A Statement Timeout Threshold For A Session](postgres/set-a-statement-timeout-threshold-for-a-session.md)
|
- [Set A Statement Timeout Threshold For A Session](postgres/set-a-statement-timeout-threshold-for-a-session.md)
|
||||||
- [Set Up A Project-Local Cluster With Postgres.app](postgres/set-up-a-project-local-cluster-with-postgres-app.md)
|
|
||||||
- [Sets With The Values Command](postgres/sets-with-the-values-command.md)
|
- [Sets With The Values Command](postgres/sets-with-the-values-command.md)
|
||||||
- [Shorthand Absolute Value Operator](postgres/shorthand-absolute-value-operator.md)
|
- [Shorthand Absolute Value Operator](postgres/shorthand-absolute-value-operator.md)
|
||||||
- [Show All Versions Of An Operator](postgres/show-all-versions-of-an-operator.md)
|
- [Show All Versions Of An Operator](postgres/show-all-versions-of-an-operator.md)
|
||||||
@@ -1094,74 +970,13 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
### Python
|
### Python
|
||||||
|
|
||||||
- [Access Instance Variables](python/access-instance-variables.md)
|
- [Access Instance Variables](python/access-instance-variables.md)
|
||||||
- [Access Most Recent Return Value In REPL](python/access-most-recent-return-value-in-repl.md)
|
|
||||||
- [Access SQLite Result Values By Name With Row Factory](python/access-sqlite-result-values-by-name-with-row-factory.md)
|
|
||||||
- [Access Variables Outside Loop Scope](python/access-variables-outside-loop-scope.md)
|
|
||||||
- [Annotate Return Type On Enum Function](python/annotate-return-type-on-enum-function.md)
|
|
||||||
- [Another Way To Mark Keyword-Only Dataclass Fields](python/another-way-to-mark-keyword-only-dataclass-fields.md)
|
|
||||||
- [Argument Defaults Are Evaluated When Function Is Defined](python/argument-defaults-are-evaluated-when-function-is-defined.md)
|
|
||||||
- [Assert Is Only A Development Check](python/assert-is-only-a-development-check.md)
|
|
||||||
- [Avoid Modification With Frozen Dataclass](python/avoid-modification-with-frozen-dataclass.md)
|
|
||||||
- [BasedPyright Will Use Pyright Config](python/basedpyright-will-use-pyright-config.md)
|
|
||||||
- [Break Debugger On First Line Of Program](python/break-debugger-on-first-line-of-program.md)
|
- [Break Debugger On First Line Of Program](python/break-debugger-on-first-line-of-program.md)
|
||||||
- [Check If Package Is Installed With Pip](python/check-if-package-is-installed-with-pip.md)
|
|
||||||
- [Check Precondition Before Click Arg Parsing](python/check-precondition-before-click-arg-parsing.md)
|
|
||||||
- [Combine StrEnum With Pydantic For Union Type](python/combine-strenum-with-pydantic-for-union-type.md)
|
|
||||||
- [Commit Writes From Executed SQLite Statements](python/commit-writes-from-executed-sqlite-statements.md)
|
|
||||||
- [Configure Other Attributes Of Dataclass Field](python/configure-other-attributes-of-dataclass-field.md)
|
|
||||||
- [Control Passing Of Time In Tests](python/control-passing-of-time-in-tests.md)
|
|
||||||
- [Create A Dummy DataFrame In Pandas](python/create-a-dummy-dataframe-in-pandas.md)
|
- [Create A Dummy DataFrame In Pandas](python/create-a-dummy-dataframe-in-pandas.md)
|
||||||
- [Create A Range Of Descending Values](python/create-a-range-of-descending-values.md)
|
|
||||||
- [Dedent Common Whitespace From Multiline String](python/dedent-common-whitespace-from-multiline-string.md)
|
|
||||||
- [Deduplicate A List Into A Tuple](python/deduplicate-a-list-into-a-tuple.md)
|
|
||||||
- [Define Sequence Of Tests With Parametrize Decorator](python/define-sequence-of-tests-with-parametrize-decorator.md)
|
|
||||||
- [Define Typed Class Interface With Protocol](python/define-typed-class-interface-with-protocol.md)
|
|
||||||
- [Dunder Methods](python/dunder-methods.md)
|
- [Dunder Methods](python/dunder-methods.md)
|
||||||
- [Easy Key-Value Aggregates With defaultdict](python/easy-key-value-aggregates-with-defaultdict.md)
|
|
||||||
- [Enable Pyright Type Checking In Cursor](python/enable-pyright-type-checking-in-cursor.md)
|
|
||||||
- [Escape Curly Braces Within Formatted String](python/escape-curly-braces-within-formatted-string.md)
|
|
||||||
- [Experiment With SQLite Queries In Memory](python/experiment-with-sqlite-queries-in-memory.md)
|
|
||||||
- [Force Remaining Arguments To Be Named](python/force-remaining-arguments-to-be-named.md)
|
|
||||||
- [Generate Sample PDFs With ReportLab](python/generate-sample-pdfs-with-reportlab.md)
|
|
||||||
- [Get Absolute Seconds From `timedelta` Object](python/get-absolute-seconds-from-timedelta-object.md)
|
|
||||||
- [Get Quotient And Remainder In One Operation](python/get-quotient-and-remainder-in-one-operation.md)
|
|
||||||
- [Globally Install CLI Tool With UV](python/globally-install-cli-tool-with-uv.md)
|
|
||||||
- [Initialize A PyTorch Tensor](python/initialize-a-pytorch-tensor.md)
|
|
||||||
- [Install With PIP For Specific Interpreter](python/install-with-pip-for-specific-interpreter.md)
|
|
||||||
- [Iterate First N Items From Enumerable](python/iterate-first-n-items-from-enumerable.md)
|
|
||||||
- [Iterate Over A Dictionary](python/iterate-over-a-dictionary.md)
|
|
||||||
- [Join A List Of Strings](python/join-a-list-of-strings.md)
|
|
||||||
- [Keep A Tally With collections.Counter](python/keep-a-tally-with-collections-counter.md)
|
|
||||||
- [Lint And Format Project With Ruff](python/lint-and-format-project-with-ruff.md)
|
|
||||||
- [Load A File Into The Python REPL](python/load-a-file-into-the-python-repl.md)
|
|
||||||
- [Look Inside Pytest tmp_path](python/look-inside-pytest-tmp-path.md)
|
|
||||||
- [Make Dataclass Sortable By Specific Field](python/make-dataclass-sortable-by-specific-field.md)
|
|
||||||
- [Make Secure Temp File For Atomic Write](python/make-secure-temp-file-for-atomic-write.md)
|
|
||||||
- [Override The Boolean Context Of A Class](python/override-the-boolean-context-of-a-class.md)
|
- [Override The Boolean Context Of A Class](python/override-the-boolean-context-of-a-class.md)
|
||||||
- [Override Timezone That All Tests Run In](python/override-timezone-that-all-tests-run-in.md)
|
|
||||||
- [Parse Relative Time To datetime Object](python/parse-relative-time-to-datetime-object.md)
|
|
||||||
- [Publish A Package To A Test Env As A Dry Run](python/publish-a-package-to-a-test-env-as-a-dry-run.md)
|
|
||||||
- [Reclassify Certain Packages As Dev Dependencies](python/reclassify-certain-packages-as-dev-dependencies.md)
|
|
||||||
- [Register SQLite Adapter To Serialize Datetimes](python/register-sqlite-adapter-to-serialize-datetimes.md)
|
|
||||||
- [Resurface Exceptions Swallowed By Click Under Test](python/resurface-exceptions-swallowed-by-click-under-test.md)
|
|
||||||
- [Run Python Tools With `uvx`](python/run-python-tools-with-uvx.md)
|
|
||||||
- [Select Implementation With Class Registry](python/select-implementation-with-class-registry.md)
|
|
||||||
- [Set Up Pyright Type Checking In GitHub](python/set-up-pyright-type-checking-in-github.md)
|
|
||||||
- [Skip Specific Pytest Test Cases](python/skip-specific-pytest-test-cases.md)
|
|
||||||
- [Sort A List Of Dataclass Instances](python/sort-a-list-of-dataclass-instances.md)
|
|
||||||
- [Sort Normalized Version Of Data](python/sort-normalized-version-of-data.md)
|
|
||||||
- [Specify Parameter Name For Click Option](python/specify-parameter-name-for-click-option.md)
|
|
||||||
- [Start Jupyter Notebook With Extra Packages](python/start-jupyter-notebook-with-extra-packages.md)
|
|
||||||
- [Start The Debugger When A Test Errors](python/start-the-debugger-when-a-test-errors.md)
|
|
||||||
- [Store And Access Immutable Data In A Tuple](python/store-and-access-immutable-data-in-a-tuple.md)
|
- [Store And Access Immutable Data In A Tuple](python/store-and-access-immutable-data-in-a-tuple.md)
|
||||||
- [Strictly Separate Positional And Keyword Arguments](python/strictly-separate-positional-and-keyword-arguments.md)
|
|
||||||
- [Test A Function With Pytest](python/test-a-function-with-pytest.md)
|
- [Test A Function With Pytest](python/test-a-function-with-pytest.md)
|
||||||
- [Try Out The Latest Version Of Ruff](python/try-out-the-latest-version-of-ruff.md)
|
|
||||||
- [Turn Method Into Cached Property On Class Instance](python/turn-method-into-cached-property-on-class-instance.md)
|
|
||||||
- [Use pipx To Install End User Apps](python/use-pipx-to-install-end-user-apps.md)
|
- [Use pipx To Install End User Apps](python/use-pipx-to-install-end-user-apps.md)
|
||||||
- [Use `__post_init__` For `dataclass` Validations](python/use-post-init-for-dataclass-validations.md)
|
|
||||||
- [Use Verbose Flag To Get More Diff](python/use-verbose-flag-to-get-more-diff.md)
|
|
||||||
- [Validate Click Option With Callback](python/validate-click-option-with-callback.md)
|
|
||||||
|
|
||||||
### Rails
|
### Rails
|
||||||
|
|
||||||
@@ -1196,18 +1011,14 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Cast Common Boolean-Like Values To Booleans](rails/cast-common-boolean-like-values-to-booleans.md)
|
- [Cast Common Boolean-Like Values To Booleans](rails/cast-common-boolean-like-values-to-booleans.md)
|
||||||
- [Change The Nullability Of A Column](rails/change-the-nullability-of-a-column.md)
|
- [Change The Nullability Of A Column](rails/change-the-nullability-of-a-column.md)
|
||||||
- [Change The Time Zone Offset Of A DateTime Object](rails/change-the-time-zone-offset-of-a-datetime-object.md)
|
- [Change The Time Zone Offset Of A DateTime Object](rails/change-the-time-zone-offset-of-a-datetime-object.md)
|
||||||
- [Check How Database Is Configured](rails/check-how-database-is-configured.md)
|
|
||||||
- [Check If ActiveRecord Update Fails](rails/check-if-activerecord-update-fails.md)
|
- [Check If ActiveRecord Update Fails](rails/check-if-activerecord-update-fails.md)
|
||||||
- [Check If Any Records Have A Null Value](rails/check-if-any-records-have-a-null-value.md)
|
- [Check If Any Records Have A Null Value](rails/check-if-any-records-have-a-null-value.md)
|
||||||
- [Check Specific Attributes On ActiveRecord Array](rails/check-specific-attributes-on-activerecord-array.md)
|
- [Check Specific Attributes On ActiveRecord Array](rails/check-specific-attributes-on-activerecord-array.md)
|
||||||
- [Check The Current Named Log Level](rails/check-the-current-named-log-level.md)
|
|
||||||
- [Clean Up Memory Hungry Rails Console Processes](rails/clean-up-memory-hungry-rails-console-processes.md)
|
|
||||||
- [Code Statistics For An Application](rails/code-statistics-for-an-application.md)
|
- [Code Statistics For An Application](rails/code-statistics-for-an-application.md)
|
||||||
- [Columns With Default Values Are Nil On Create](rails/columns-with-default-values-are-nil-on-create.md)
|
- [Columns With Default Values Are Nil On Create](rails/columns-with-default-values-are-nil-on-create.md)
|
||||||
- [Comparing DateTimes Down To Second Precision](rails/comparing-datetimes-down-to-second-precision.md)
|
- [Comparing DateTimes Down To Second Precision](rails/comparing-datetimes-down-to-second-precision.md)
|
||||||
- [Conditional Class Selectors in Haml](rails/conditional-class-selectors-in-haml.md)
|
- [Conditional Class Selectors in Haml](rails/conditional-class-selectors-in-haml.md)
|
||||||
- [Convert A Symbol To A Constant](rails/convert-a-symbol-to-a-constant.md)
|
- [Convert A Symbol To A Constant](rails/convert-a-symbol-to-a-constant.md)
|
||||||
- [Convert JSON Field To Hash With Indifferent Access](rails/convert-json-field-to-hash-with-indifferent-access.md)
|
|
||||||
- [Count The Number Of Records By Attribute](rails/count-the-number-of-records-by-attribute.md)
|
- [Count The Number Of Records By Attribute](rails/count-the-number-of-records-by-attribute.md)
|
||||||
- [Create A Custom Named References Column](rails/create-a-custom-named-references-column.md)
|
- [Create A Custom Named References Column](rails/create-a-custom-named-references-column.md)
|
||||||
- [Create A Join Table With The Migration DSL](rails/create-a-join-table-with-the-migration-dsl.md)
|
- [Create A Join Table With The Migration DSL](rails/create-a-join-table-with-the-migration-dsl.md)
|
||||||
@@ -1215,9 +1026,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Creating Records of Has_One Associations](rails/creating-records-of-has-one-associations.md)
|
- [Creating Records of Has_One Associations](rails/creating-records-of-has-one-associations.md)
|
||||||
- [Custom Validation Message](rails/custom-validation-message.md)
|
- [Custom Validation Message](rails/custom-validation-message.md)
|
||||||
- [Customize Paths And Helpers For Devise Routes](rails/customize-paths-and-helpers-for-devise-routes.md)
|
- [Customize Paths And Helpers For Devise Routes](rails/customize-paths-and-helpers-for-devise-routes.md)
|
||||||
- [Customize Template For New Schema Migration](rails/customize-template-for-new-schema-migration.md)
|
|
||||||
- [Customize The Path Of A Resource Route](rails/customize-the-path-of-a-resource-route.md)
|
- [Customize The Path Of A Resource Route](rails/customize-the-path-of-a-resource-route.md)
|
||||||
- [Define Conditional Routing Logic In Routes File](rails/define-conditional-routing-logic-in-routes-file.md)
|
|
||||||
- [Define The Root Path For The App](rails/define-the-root-path-for-the-app.md)
|
- [Define The Root Path For The App](rails/define-the-root-path-for-the-app.md)
|
||||||
- [Delete Paranoid Records](rails/delete-paranoid-records.md)
|
- [Delete Paranoid Records](rails/delete-paranoid-records.md)
|
||||||
- [Demodulize A Class Name](rails/demodulize-a-class-name.md)
|
- [Demodulize A Class Name](rails/demodulize-a-class-name.md)
|
||||||
@@ -1233,11 +1042,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Filter ActiveStorage Blobs To Only Images](rails/filter-active-storage-blobs-to-only-images.md)
|
- [Filter ActiveStorage Blobs To Only Images](rails/filter-active-storage-blobs-to-only-images.md)
|
||||||
- [Find Or Create A Record With FactoryBot](rails/find-or-create-a-record-with-factory-bot.md)
|
- [Find Or Create A Record With FactoryBot](rails/find-or-create-a-record-with-factory-bot.md)
|
||||||
- [Find Records With Multiple Associated Records](rails/find-records-with-multiple-associated-records.md)
|
- [Find Records With Multiple Associated Records](rails/find-records-with-multiple-associated-records.md)
|
||||||
- [Flipper Discards Actors When Feature Fully Enabled](rails/flipper-discards-actors-when-feature-fully-enabled.md)
|
|
||||||
- [Force All Users To Sign Out](rails/force-all-users-to-sign-out.md)
|
- [Force All Users To Sign Out](rails/force-all-users-to-sign-out.md)
|
||||||
- [Format Amount As Currency](rails/format-amount-as-currency.md)
|
|
||||||
- [Format DateTime With Builtin Formats](rails/format-datetime-with-builtin-formats.md)
|
|
||||||
- [Format Specific html.erb Template Files](rails/format-specific-html-erb-template-files.md)
|
|
||||||
- [Generate A Model](rails/generate-a-model.md)
|
- [Generate A Model](rails/generate-a-model.md)
|
||||||
- [Generate A Rails App From The Main Branch](rails/generate-a-rails-app-from-the-main-branch.md)
|
- [Generate A Rails App From The Main Branch](rails/generate-a-rails-app-from-the-main-branch.md)
|
||||||
- [Generating And Executing SQL](rails/generating-and-executing-sql.md)
|
- [Generating And Executing SQL](rails/generating-and-executing-sql.md)
|
||||||
@@ -1250,8 +1055,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Get The Column Names For A Model](rails/get-the-column-names-for-a-model.md)
|
- [Get The Column Names For A Model](rails/get-the-column-names-for-a-model.md)
|
||||||
- [Get The Current Time](rails/get-the-current-time.md)
|
- [Get The Current Time](rails/get-the-current-time.md)
|
||||||
- [Grab A Random Record From The Database](rails/grab-a-random-record-from-the-database.md)
|
- [Grab A Random Record From The Database](rails/grab-a-random-record-from-the-database.md)
|
||||||
- [Halt ActionMailer Delivery With Callback](rails/halt-action-mailer-delivery-with-callback.md)
|
|
||||||
- [Handle Bad Numerical Amounts With BigDecimal](rails/handle-bad-numerical-amounts-with-big-decimal.md)
|
|
||||||
- [Handle Named Arguments In A Rake Task](rails/handle-named-arguments-in-a-rake-task.md)
|
- [Handle Named Arguments In A Rake Task](rails/handle-named-arguments-in-a-rake-task.md)
|
||||||
- [Hash Slicing](rails/hash-slicing.md)
|
- [Hash Slicing](rails/hash-slicing.md)
|
||||||
- [Ignore Poltergeist JavaScript Errors](rails/ignore-poltergeist-javascript-errors.md)
|
- [Ignore Poltergeist JavaScript Errors](rails/ignore-poltergeist-javascript-errors.md)
|
||||||
@@ -1269,7 +1072,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Make A String Attribute Easy To Inquire About](rails/make-a-string-attribute-easy-to-inquire-about.md)
|
- [Make A String Attribute Easy To Inquire About](rails/make-a-string-attribute-easy-to-inquire-about.md)
|
||||||
- [Make ActionMailer Synchronous In Test](rails/make-action-mailer-synchronous-in-test.md)
|
- [Make ActionMailer Synchronous In Test](rails/make-action-mailer-synchronous-in-test.md)
|
||||||
- [Make Remove Column Migration Reversible](rails/make-remove-column-migration-reversible.md)
|
- [Make Remove Column Migration Reversible](rails/make-remove-column-migration-reversible.md)
|
||||||
- [Manage Timestamps With Upsert](rails/manage-timestamps-with-upsert.md)
|
|
||||||
- [Manually Run A Migration From Rails Console](rails/manually-run-a-migration-from-rails-console.md)
|
- [Manually Run A Migration From Rails Console](rails/manually-run-a-migration-from-rails-console.md)
|
||||||
- [Mark For Destruction](rails/mark-for-destruction.md)
|
- [Mark For Destruction](rails/mark-for-destruction.md)
|
||||||
- [Mask An ActiveRecord Attribute](rails/mask-an-activerecord-attribute.md)
|
- [Mask An ActiveRecord Attribute](rails/mask-an-activerecord-attribute.md)
|
||||||
@@ -1278,7 +1080,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Mock Rails Environment With An Inquiry Instance](rails/mock-rails-environment-with-an-inquiry-instance.md)
|
- [Mock Rails Environment With An Inquiry Instance](rails/mock-rails-environment-with-an-inquiry-instance.md)
|
||||||
- [Order Matters For `rescue_from` Blocks](rails/order-matters-for-rescue-from-blocks.md)
|
- [Order Matters For `rescue_from` Blocks](rails/order-matters-for-rescue-from-blocks.md)
|
||||||
- [Override Text Displayed By Form Label](rails/override-text-displayed-by-form-label.md)
|
- [Override Text Displayed By Form Label](rails/override-text-displayed-by-form-label.md)
|
||||||
- [Parameterize A String With Underscores](rails/parameterize-a-string-with-underscores.md)
|
|
||||||
- [Params Includes Submission Button Info](rails/params-includes-submission-button-info.md)
|
- [Params Includes Submission Button Info](rails/params-includes-submission-button-info.md)
|
||||||
- [Params Is A Hash With Indifferent Access](rails/params-is-a-hash-with-indifferent-access.md)
|
- [Params Is A Hash With Indifferent Access](rails/params-is-a-hash-with-indifferent-access.md)
|
||||||
- [Parse Query Params From A URL](rails/parse-query-params-from-a-url.md)
|
- [Parse Query Params From A URL](rails/parse-query-params-from-a-url.md)
|
||||||
@@ -1287,15 +1088,12 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Polymorphic Path Helpers](rails/polymorphic-path-helpers.md)
|
- [Polymorphic Path Helpers](rails/polymorphic-path-helpers.md)
|
||||||
- [Prefer select_all Over execute For Read Queries](rails/prefer-select-all-over-execute-for-read-queries.md)
|
- [Prefer select_all Over execute For Read Queries](rails/prefer-select-all-over-execute-for-read-queries.md)
|
||||||
- [Pretend Generations](rails/pretend-generations.md)
|
- [Pretend Generations](rails/pretend-generations.md)
|
||||||
- [Prevent Mailer Previews From Cluttering Database](rails/prevent-mailer-previews-from-cluttering-database.md)
|
|
||||||
- [Prevent Writes With A Sandboxed Rails Console](rails/prevent-writes-with-a-sandboxed-rails-console.md)
|
- [Prevent Writes With A Sandboxed Rails Console](rails/prevent-writes-with-a-sandboxed-rails-console.md)
|
||||||
- [Provide Fake Form Helper To Controllers](rails/provide-fake-form-helper-to-controllers.md)
|
|
||||||
- [Query A Single Value From The Database](rails/query-a-single-value-from-the-database.md)
|
- [Query A Single Value From The Database](rails/query-a-single-value-from-the-database.md)
|
||||||
- [Read In Environment-Specific Config Values](rails/read-in-environment-specific-config-values.md)
|
- [Read In Environment-Specific Config Values](rails/read-in-environment-specific-config-values.md)
|
||||||
- [Read-Only Models](rails/read-only-models.md)
|
- [Read-Only Models](rails/read-only-models.md)
|
||||||
- [Rebuild Tailwind Bundle For Dev Server](rails/rebuild-tailwind-bundle-for-dev-server.md)
|
- [Rebuild Tailwind Bundle For Dev Server](rails/rebuild-tailwind-bundle-for-dev-server.md)
|
||||||
- [Remove A Database Column From A Table](rails/remove-a-database-column-from-a-table.md)
|
- [Remove A Database Column From A Table](rails/remove-a-database-column-from-a-table.md)
|
||||||
- [Remove Blank Values From A Hash](rails/remove-blank-values-from-a-hash.md)
|
|
||||||
- [Remove The Default Value On A Column](rails/remove-the-default-value-on-a-column.md)
|
- [Remove The Default Value On A Column](rails/remove-the-default-value-on-a-column.md)
|
||||||
- [Render An Alternative ActionMailer Template](rails/render-an-alternative-action-mailer-template.md)
|
- [Render An Alternative ActionMailer Template](rails/render-an-alternative-action-mailer-template.md)
|
||||||
- [Render The Response Body In Controller Specs](rails/render-the-response-body-in-controller-specs.md)
|
- [Render The Response Body In Controller Specs](rails/render-the-response-body-in-controller-specs.md)
|
||||||
@@ -1310,12 +1108,9 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Rounding Numbers With Precision](rails/rounding-numbers-with-precision.md)
|
- [Rounding Numbers With Precision](rails/rounding-numbers-with-precision.md)
|
||||||
- [Run A Rake Task Programmatically](rails/run-a-rake-task-programmatically.md)
|
- [Run A Rake Task Programmatically](rails/run-a-rake-task-programmatically.md)
|
||||||
- [Run Commands With Specific Rails Version](rails/run-commands-with-specific-rails-version.md)
|
- [Run Commands With Specific Rails Version](rails/run-commands-with-specific-rails-version.md)
|
||||||
- [Run Dev Processes With Overmind Instead Of Foreman](rails/run-dev-processes-with-overmind-instead-of-foreman.md)
|
|
||||||
- [Run Rails Console With Remote Dokku App](rails/run-rails-console-with-remote-dokku-app.md)
|
|
||||||
- [Run Some Code Whenever Rails Console Starts](rails/run-some-code-whenever-rails-console-starts.md)
|
- [Run Some Code Whenever Rails Console Starts](rails/run-some-code-whenever-rails-console-starts.md)
|
||||||
- [Scaffold Auth Functionality With Rails 8 Generator](rails/scaffold-auth-functionality-with-rails-8-generator.md)
|
- [Scaffold Auth Functionality With Rails 8 Generator](rails/scaffold-auth-functionality-with-rails-8-generator.md)
|
||||||
- [Schedule Sidekiq Jobs Out Into The Future](rails/schedule-sidekiq-jobs-out-into-the-future.md)
|
- [Schedule Sidekiq Jobs Out Into The Future](rails/schedule-sidekiq-jobs-out-into-the-future.md)
|
||||||
- [Scope Records To A Lower Or Upper Bound](rails/scope-records-to-a-lower-or-upper-bound.md)
|
|
||||||
- [Secure Passwords With Rails And Bcrypt](rails/secure-passwords-with-rails-and-bcrypt.md)
|
- [Secure Passwords With Rails And Bcrypt](rails/secure-passwords-with-rails-and-bcrypt.md)
|
||||||
- [Select A Select By Selector](rails/select-a-select-by-selector.md)
|
- [Select A Select By Selector](rails/select-a-select-by-selector.md)
|
||||||
- [Select A Specific Rails Version To Install](rails/select-a-specific-rails-version-to-install.md)
|
- [Select A Specific Rails Version To Install](rails/select-a-specific-rails-version-to-install.md)
|
||||||
@@ -1344,7 +1139,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Update Column Versus Update Attribute](rails/update-column-versus-update-attribute.md)
|
- [Update Column Versus Update Attribute](rails/update-column-versus-update-attribute.md)
|
||||||
- [Upgrading Your Manifest For Sprocket's 4](rails/upgrading-your-manifest-for-sprockets-4.md)
|
- [Upgrading Your Manifest For Sprocket's 4](rails/upgrading-your-manifest-for-sprockets-4.md)
|
||||||
- [Use IRB And Ruby Flags With Rails Console](rails/use-irb-and-ruby-flags-with-rails-console.md)
|
- [Use IRB And Ruby Flags With Rails Console](rails/use-irb-and-ruby-flags-with-rails-console.md)
|
||||||
- [Use .ruby Extension For Template File](rails/use-ruby-extension-for-template-file.md)
|
|
||||||
- [Useful ActiveSupport Constants For Durations](rails/useful-active-support-constants-for-durations.md)
|
- [Useful ActiveSupport Constants For Durations](rails/useful-active-support-constants-for-durations.md)
|
||||||
- [Validate Column Data With Check Constraints](rails/validate-column-data-with-check-constraints.md)
|
- [Validate Column Data With Check Constraints](rails/validate-column-data-with-check-constraints.md)
|
||||||
- [Verify And Read A Signed Cookie Value](rails/verify-and-read-a-signed-cookie-value.md)
|
- [Verify And Read A Signed Cookie Value](rails/verify-and-read-a-signed-cookie-value.md)
|
||||||
@@ -1484,10 +1278,8 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Add Progress Reporting To Long-Running Script](ruby/add-progress-reporting-to-long-running-script.md)
|
- [Add Progress Reporting To Long-Running Script](ruby/add-progress-reporting-to-long-running-script.md)
|
||||||
- [Are They All True?](ruby/are-they-all-true.md)
|
- [Are They All True?](ruby/are-they-all-true.md)
|
||||||
- [Assert About An Object's Attributes With RSpec](ruby/assert-about-an-objects-attributes-with-rspec.md)
|
- [Assert About An Object's Attributes With RSpec](ruby/assert-about-an-objects-attributes-with-rspec.md)
|
||||||
- [Assoc For Hashes](ruby/assoc-for-hashes.md)
|
|
||||||
- [Audit Your Ruby Project For Any CVEs](ruby/audit-your-ruby-project-for-any-cves.md)
|
- [Audit Your Ruby Project For Any CVEs](ruby/audit-your-ruby-project-for-any-cves.md)
|
||||||
- [Avoid Double Negation With Minitest Refute](ruby/avoid-double-negation-with-minitest-refute.md)
|
- [Assoc For Hashes](ruby/assoc-for-hashes.md)
|
||||||
- [Avoid Dynamically Dispatching Private Methods](ruby/avoid-dynamically-dispatching-private-methods.md)
|
|
||||||
- [Block Comments](ruby/block-comments.md)
|
- [Block Comments](ruby/block-comments.md)
|
||||||
- [Block Syntaxes Have Different Precedence](ruby/block-syntaxes-have-different-precedence.md)
|
- [Block Syntaxes Have Different Precedence](ruby/block-syntaxes-have-different-precedence.md)
|
||||||
- [Build HTTP And HTTPS URLs](ruby/build-http-and-https-urls.md)
|
- [Build HTTP And HTTPS URLs](ruby/build-http-and-https-urls.md)
|
||||||
@@ -1507,15 +1299,11 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Create a CSV::Table Object](ruby/create-a-csv-table-object.md)
|
- [Create a CSV::Table Object](ruby/create-a-csv-table-object.md)
|
||||||
- [Create A Hash From An Array Of Arrays](ruby/create-a-hash-from-an-array-of-arrays.md)
|
- [Create A Hash From An Array Of Arrays](ruby/create-a-hash-from-an-array-of-arrays.md)
|
||||||
- [Create Listing Of All Middleman Pages](ruby/create-listing-of-all-middleman-pages.md)
|
- [Create Listing Of All Middleman Pages](ruby/create-listing-of-all-middleman-pages.md)
|
||||||
- [Create Mock Class That Can Be Overridden](ruby/create-mock-class-that-can-be-overridden.md)
|
|
||||||
- [Create A Module Of Utility Functions](ruby/create-a-module-of-utility-functions.md)
|
|
||||||
- [Create Named Structs With Struct.new](ruby/create-named-structs-with-struct-new.md)
|
- [Create Named Structs With Struct.new](ruby/create-named-structs-with-struct-new.md)
|
||||||
- [Create Thumbnail Image For A PDF](ruby/create-thumbnail-image-for-a-pdf.md)
|
- [Create Thumbnail Image For A PDF](ruby/create-thumbnail-image-for-a-pdf.md)
|
||||||
- [Decompose Unicode Character With Diacritic Mark](ruby/decompose-unicode-character-with-diacritic-mark.md)
|
|
||||||
- [Defaulting To Frozen String Literals](ruby/defaulting-to-frozen-string-literals.md)
|
- [Defaulting To Frozen String Literals](ruby/defaulting-to-frozen-string-literals.md)
|
||||||
- [Define A Custom RSpec Matcher](ruby/define-a-custom-rspec-matcher.md)
|
- [Define A Custom RSpec Matcher](ruby/define-a-custom-rspec-matcher.md)
|
||||||
- [Define A Method On A Struct](ruby/define-a-method-on-a-struct.md)
|
- [Define A Method On A Struct](ruby/define-a-method-on-a-struct.md)
|
||||||
- [Define A Set Of Class Methods](ruby/define-a-set-of-class-methods.md)
|
|
||||||
- [Define Multiline Strings With Heredocs](ruby/define-multiline-strings-with-heredocs.md)
|
- [Define Multiline Strings With Heredocs](ruby/define-multiline-strings-with-heredocs.md)
|
||||||
- [Destructure The First Item From An Array](ruby/destructure-the-first-item-from-an-array.md)
|
- [Destructure The First Item From An Array](ruby/destructure-the-first-item-from-an-array.md)
|
||||||
- [Destructuring Arrays In Blocks](ruby/destructuring-arrays-in-blocks.md)
|
- [Destructuring Arrays In Blocks](ruby/destructuring-arrays-in-blocks.md)
|
||||||
@@ -1536,7 +1324,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [FactoryGirl Sequences](ruby/factory-girl-sequences.md)
|
- [FactoryGirl Sequences](ruby/factory-girl-sequences.md)
|
||||||
- [Fail](ruby/fail.md)
|
- [Fail](ruby/fail.md)
|
||||||
- [Fetch Warns About Superseding Block Argument](ruby/fetch-warns-about-superseding-block-argument.md)
|
- [Fetch Warns About Superseding Block Argument](ruby/fetch-warns-about-superseding-block-argument.md)
|
||||||
- [Filter By Type](ruby/filter-by-type.md)
|
|
||||||
- [Find The Min And Max With A Single Call](ruby/find-the-min-and-max-with-a-single-call.md)
|
- [Find The Min And Max With A Single Call](ruby/find-the-min-and-max-with-a-single-call.md)
|
||||||
- [Finding The Source of Ruby Methods](ruby/finding-the-source-of-ruby-methods.md)
|
- [Finding The Source of Ruby Methods](ruby/finding-the-source-of-ruby-methods.md)
|
||||||
- [Format A Hash Into A String Template](ruby/format-a-hash-into-a-string-template.md)
|
- [Format A Hash Into A String Template](ruby/format-a-hash-into-a-string-template.md)
|
||||||
@@ -1545,8 +1332,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Generate A Signed JWT Token](ruby/generate-a-signed-jwt-token.md)
|
- [Generate A Signed JWT Token](ruby/generate-a-signed-jwt-token.md)
|
||||||
- [Generate Ruby Version And Gemset Files With RVM](ruby/generate-ruby-version-and-gemset-files-with-rvm.md)
|
- [Generate Ruby Version And Gemset Files With RVM](ruby/generate-ruby-version-and-gemset-files-with-rvm.md)
|
||||||
- [Get Info About Your RubyGems Environment](ruby/get-info-about-your-ruby-gems-environment.md)
|
- [Get Info About Your RubyGems Environment](ruby/get-info-about-your-ruby-gems-environment.md)
|
||||||
- [Get Specific Values From Arrays And Hashes](ruby/get-specific-values-from-hashes-and-arrays.md)
|
|
||||||
- [Get The Names Of The Month](ruby/get-the-names-of-the-month.md)
|
|
||||||
- [Get The Output Of Running A System Program](ruby/get-the-output-of-running-a-system-program.md)
|
- [Get The Output Of Running A System Program](ruby/get-the-output-of-running-a-system-program.md)
|
||||||
- [Get UTC Offset For Different Time Zones](ruby/get-utc-offset-for-different-time-zones.md)
|
- [Get UTC Offset For Different Time Zones](ruby/get-utc-offset-for-different-time-zones.md)
|
||||||
- [Identify Outdated Gems](ruby/identify-outdated-gems.md)
|
- [Identify Outdated Gems](ruby/identify-outdated-gems.md)
|
||||||
@@ -1554,21 +1339,15 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Iterate With An Offset Index](ruby/iterate-with-an-offset-index.md)
|
- [Iterate With An Offset Index](ruby/iterate-with-an-offset-index.md)
|
||||||
- [Include Extra Context In A Honeybadger Notify](ruby/include-extra-context-in-a-honeybadger-notify.md)
|
- [Include Extra Context In A Honeybadger Notify](ruby/include-extra-context-in-a-honeybadger-notify.md)
|
||||||
- [Ins And Outs Of Pry](ruby/ins-and-outs-of-pry.md)
|
- [Ins And Outs Of Pry](ruby/ins-and-outs-of-pry.md)
|
||||||
- [Install And Require Gems Inline Without Gemfile](ruby/install-and-require-gems-inline-without-gemfile.md)
|
|
||||||
- [Install Latest Version Of Ruby With asdf](ruby/install-latest-version-of-ruby-with-asdf.md)
|
- [Install Latest Version Of Ruby With asdf](ruby/install-latest-version-of-ruby-with-asdf.md)
|
||||||
- [Invoking Rake Tasks Multiple Times](ruby/invoking-rake-tasks-multiple-times.md)
|
- [Invoking Rake Tasks Multiple Times](ruby/invoking-rake-tasks-multiple-times.md)
|
||||||
- [IRB Has Built-In Benchmarking With Ruby 3](ruby/irb-has-built-in-benchmarking-with-ruby-3.md)
|
- [IRB Has Built-In Benchmarking With Ruby 3](ruby/irb-has-built-in-benchmarking-with-ruby-3.md)
|
||||||
- [IRB Prints A Helpful Welcome Prompt](ruby/irb-prints-a-helpful-welcome-prompt.md)
|
|
||||||
- [Join URI Path Parts](ruby/join-uri-path-parts.md)
|
|
||||||
- [Jump Out Of A Nested Context With Throw/Catch](ruby/jump-out-of-a-nested-context-with-throw-catch.md)
|
- [Jump Out Of A Nested Context With Throw/Catch](ruby/jump-out-of-a-nested-context-with-throw-catch.md)
|
||||||
- [Last Raised Exception In The Call Stack](ruby/last-raised-exception-in-the-call-stack.md)
|
- [Last Raised Exception In The Call Stack](ruby/last-raised-exception-in-the-call-stack.md)
|
||||||
- [Limit Split](ruby/limit-split.md)
|
- [Limit Split](ruby/limit-split.md)
|
||||||
- [List The Running Ruby Version](ruby/list-the-running-ruby-version.md)
|
- [List The Running Ruby Version](ruby/list-the-running-ruby-version.md)
|
||||||
- [Listing Local Variables](ruby/listing-local-variables.md)
|
- [Listing Local Variables](ruby/listing-local-variables.md)
|
||||||
- [Load A Module And Execute A Statement](ruby/load-a-module-and-execute-a-statement.md)
|
|
||||||
- [Make A Long String Of Text Readable](ruby/make-a-long-string-of-text-readable.md)
|
|
||||||
- [Make An Executable Ruby Script](ruby/make-an-executable-ruby-script.md)
|
- [Make An Executable Ruby Script](ruby/make-an-executable-ruby-script.md)
|
||||||
- [Make Structs Easier To Use With Keyword Initialization](ruby/make-structs-easier-to-use-with-keyword-initialization.md)
|
|
||||||
- [Map With Index Over An Array](ruby/map-with-index-over-an-array.md)
|
- [Map With Index Over An Array](ruby/map-with-index-over-an-array.md)
|
||||||
- [Mock Method Chain Calls With RSpec](ruby/mock-method-chain-calls-with-rspec.md)
|
- [Mock Method Chain Calls With RSpec](ruby/mock-method-chain-calls-with-rspec.md)
|
||||||
- [Mocking Requests With Partial URIs Using Regex](ruby/mocking-requests-with-partial-uris-using-regex.md)
|
- [Mocking Requests With Partial URIs Using Regex](ruby/mocking-requests-with-partial-uris-using-regex.md)
|
||||||
@@ -1579,7 +1358,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [OpenStruct Has Bad Performance Characteristics](ruby/open-struct-has-bad-performance-characteristics.md)
|
- [OpenStruct Has Bad Performance Characteristics](ruby/open-struct-has-bad-performance-characteristics.md)
|
||||||
- [Or Operator Precedence](ruby/or-operator-precedence.md)
|
- [Or Operator Precedence](ruby/or-operator-precedence.md)
|
||||||
- [Output Bytecode For A Ruby Program](ruby/output-bytecode-for-a-ruby-program.md)
|
- [Output Bytecode For A Ruby Program](ruby/output-bytecode-for-a-ruby-program.md)
|
||||||
- [Override Output Field Separator](ruby/override-output-field-separator.md)
|
|
||||||
- [Override The Initial Sequence Value](ruby/override-the-initial-sequence-value.md)
|
- [Override The Initial Sequence Value](ruby/override-the-initial-sequence-value.md)
|
||||||
- [Parallel Bundle Install](ruby/parallel-bundle-install.md)
|
- [Parallel Bundle Install](ruby/parallel-bundle-install.md)
|
||||||
- [Parse JSON Into An OpenStruct](ruby/parse-json-into-an-open-struct.md)
|
- [Parse JSON Into An OpenStruct](ruby/parse-json-into-an-open-struct.md)
|
||||||
@@ -1596,8 +1374,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Rake Only Lists Tasks With Descriptions](ruby/rake-only-lists-tasks-with-descriptions.md)
|
- [Rake Only Lists Tasks With Descriptions](ruby/rake-only-lists-tasks-with-descriptions.md)
|
||||||
- [Read The First Line From A File](ruby/read-the-first-line-from-a-file.md)
|
- [Read The First Line From A File](ruby/read-the-first-line-from-a-file.md)
|
||||||
- [Refer To Implicit Block Argument With It](ruby/refer-to-implicit-block-argument-with-it.md)
|
- [Refer To Implicit Block Argument With It](ruby/refer-to-implicit-block-argument-with-it.md)
|
||||||
- [Reference Hash Key With Safe Navigation](ruby/reference-hash-key-with-safe-navigation.md)
|
|
||||||
- [Regenerate Lock File With Newer Bundler](ruby/regenerate-lock-file-with-newer-bundler.md)
|
|
||||||
- [Rendering ERB](ruby/rendering-erb.md)
|
- [Rendering ERB](ruby/rendering-erb.md)
|
||||||
- [Replace The Current Process With An External Command](ruby/replace-the-current-process-with-an-external-command.md)
|
- [Replace The Current Process With An External Command](ruby/replace-the-current-process-with-an-external-command.md)
|
||||||
- [Require Entire Gemfile In Pry Session](ruby/require-entire-gemfile-in-pry-session.md)
|
- [Require Entire Gemfile In Pry Session](ruby/require-entire-gemfile-in-pry-session.md)
|
||||||
@@ -1612,7 +1388,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Scripting With RVM](ruby/scripting-with-rvm.md)
|
- [Scripting With RVM](ruby/scripting-with-rvm.md)
|
||||||
- [Scroll To Top Of Page With Capybara](ruby/scroll-to-top-of-page-with-capybara.md)
|
- [Scroll To Top Of Page With Capybara](ruby/scroll-to-top-of-page-with-capybara.md)
|
||||||
- [Search For Gem Versions Available To Install](ruby/search-for-gem-versions-available-to-install.md)
|
- [Search For Gem Versions Available To Install](ruby/search-for-gem-versions-available-to-install.md)
|
||||||
- [Set Default Tasks For Rake To Run](ruby/set-default-tasks-for-rake-to-run.md)
|
|
||||||
- [Set RVM Default Ruby](ruby/set-rvm-default-ruby.md)
|
- [Set RVM Default Ruby](ruby/set-rvm-default-ruby.md)
|
||||||
- [Shift The Month On A Date Object](ruby/shift-the-month-on-a-date-object.md)
|
- [Shift The Month On A Date Object](ruby/shift-the-month-on-a-date-object.md)
|
||||||
- [Show Public Methods With Pry](ruby/show-public-methods-with-pry.md)
|
- [Show Public Methods With Pry](ruby/show-public-methods-with-pry.md)
|
||||||
@@ -1621,7 +1396,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Single And Double Quoted String Notation](ruby/single-and-double-quoted-string-notation.md)
|
- [Single And Double Quoted String Notation](ruby/single-and-double-quoted-string-notation.md)
|
||||||
- [Skip Specific CVEs When Auditing Your Bundle](ruby/skip-specific-cves-when-auditing-your-bundle.md)
|
- [Skip Specific CVEs When Auditing Your Bundle](ruby/skip-specific-cves-when-auditing-your-bundle.md)
|
||||||
- [Skip The Front Of An Array With Drop](ruby/skip-the-front-of-an-array-with-drop.md)
|
- [Skip The Front Of An Array With Drop](ruby/skip-the-front-of-an-array-with-drop.md)
|
||||||
- [Specify Default For Data Definition](ruby/specify-default-for-data-definition.md)
|
|
||||||
- [Specify Dependencies For A Rake Task](ruby/specify-dependencies-for-a-rake-task.md)
|
- [Specify Dependencies For A Rake Task](ruby/specify-dependencies-for-a-rake-task.md)
|
||||||
- [Specify How Random Array#sample Is](ruby/specify-how-random-array-sample-is.md)
|
- [Specify How Random Array#sample Is](ruby/specify-how-random-array-sample-is.md)
|
||||||
- [Split A Float Into Its Integer And Decimal](ruby/split-a-float-into-its-integer-and-decimal.md)
|
- [Split A Float Into Its Integer And Decimal](ruby/split-a-float-into-its-integer-and-decimal.md)
|
||||||
@@ -1641,8 +1415,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Update The Gemfile Bundled With Version](ruby/update-the-gemfile-bundled-with-version.md)
|
- [Update The Gemfile Bundled With Version](ruby/update-the-gemfile-bundled-with-version.md)
|
||||||
- [Use A Case Statement As A Cond Statement](ruby/use-a-case-statement-as-a-cond-statement.md)
|
- [Use A Case Statement As A Cond Statement](ruby/use-a-case-statement-as-a-cond-statement.md)
|
||||||
- [Use dotenv In A Non-Rails Project](ruby/use-dotenv-in-a-non-rails-project.md)
|
- [Use dotenv In A Non-Rails Project](ruby/use-dotenv-in-a-non-rails-project.md)
|
||||||
- [Use Rescue As Part Of Inline Statement](ruby/use-rescue-as-part-of-inline-statement.md)
|
|
||||||
- [Use Slice To Reorder Hash Keys](ruby/use-slice-to-reorder-hash-keys.md)
|
|
||||||
- [Use Tap For Better Test Data Setup](ruby/use-tap-for-better-test-data-setup.md)
|
- [Use Tap For Better Test Data Setup](ruby/use-tap-for-better-test-data-setup.md)
|
||||||
- [Using BCrypt To Create And Check Hashed Passwords](ruby/using-bcrypt-to-create-and-check-hashed-passwords.md)
|
- [Using BCrypt To Create And Check Hashed Passwords](ruby/using-bcrypt-to-create-and-check-hashed-passwords.md)
|
||||||
- [What To Do When You Don't Rescue](ruby/what-to-do-when-you-dont-rescue.md)
|
- [What To Do When You Don't Rescue](ruby/what-to-do-when-you-dont-rescue.md)
|
||||||
@@ -1660,7 +1432,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [OSX sed Does Regex A Bit Different](sed/osx-sed-does-regex-a-bit-different.md)
|
- [OSX sed Does Regex A Bit Different](sed/osx-sed-does-regex-a-bit-different.md)
|
||||||
- [Output Only Lines Involved In A Substitution](sed/output-only-lines-involved-in-a-substitution.md)
|
- [Output Only Lines Involved In A Substitution](sed/output-only-lines-involved-in-a-substitution.md)
|
||||||
- [Reference A Capture In The Regex](sed/reference-a-capture-in-the-regex.md)
|
- [Reference A Capture In The Regex](sed/reference-a-capture-in-the-regex.md)
|
||||||
- [Reference The Full Match In The Replacement](sed/reference-the-full-match-in-the-replacement.md)
|
|
||||||
- [Use An Alternative Delimiter In A Substitution](sed/use-an-alternative-delimiter-in-a-substitution.md)
|
- [Use An Alternative Delimiter In A Substitution](sed/use-an-alternative-delimiter-in-a-substitution.md)
|
||||||
|
|
||||||
### Shell
|
### Shell
|
||||||
@@ -1670,11 +1441,8 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
|
|
||||||
### SQLite
|
### SQLite
|
||||||
|
|
||||||
- [Add Check Constraint To Existing Column](sqlite/add-check-constraint-to-existing-column.md)
|
|
||||||
- [Display Results In Readable Column Format](sqlite/display-results-in-readable-column-format.md)
|
- [Display Results In Readable Column Format](sqlite/display-results-in-readable-column-format.md)
|
||||||
- [Explore The Database Schema](sqlite/explore-the-database-schema.md)
|
- [Explore The Database Schema](sqlite/explore-the-database-schema.md)
|
||||||
- [Manage Lightweight Schema Migrations With `user_version`](sqlite/manage-lightweight-schema-migrations-with-user-version.md)
|
|
||||||
- [Output Query Result In Nicely Formatted Table](sqlite/output-query-result-in-nicely-formatted-table.md)
|
|
||||||
|
|
||||||
### Streaming
|
### Streaming
|
||||||
|
|
||||||
@@ -1684,27 +1452,17 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
|
|
||||||
- [Apply Tailwind Classes To Existing CSS Class](tailwind/apply-tailwind-classes-to-existing-css-class.md)
|
- [Apply Tailwind Classes To Existing CSS Class](tailwind/apply-tailwind-classes-to-existing-css-class.md)
|
||||||
- [Base Styles For Text Link](tailwind/base-styles-for-text-link.md)
|
- [Base Styles For Text Link](tailwind/base-styles-for-text-link.md)
|
||||||
- [Disable And Enable A Button](tailwind/disable-and-enable-a-button.md)
|
|
||||||
- [Specify Paths For Purging Unused CSS](tailwind/specify-paths-for-purging-unused-css.md)
|
- [Specify Paths For Purging Unused CSS](tailwind/specify-paths-for-purging-unused-css.md)
|
||||||
- [Use Tailwind Typography Prose In Dark Mode](tailwind/use-tailwind-typography-prose-in-dark-mode.md)
|
- [Use Tailwind Typography Prose In Dark Mode](tailwind/use-tailwind-typography-prose-in-dark-mode.md)
|
||||||
|
|
||||||
### Taskfile
|
|
||||||
|
|
||||||
- [Add Default Task To List All Tasks](taskfile/add-default-task-to-list-all-tasks.md)
|
|
||||||
- [Create Interactive Picker For Set Of Subtasks](taskfile/create-interactive-picker-for-set-of-subtasks.md)
|
|
||||||
- [Initialize New Taskfile For A Project](taskfile/initialize-new-taskfile-for-a-project.md)
|
|
||||||
- [Run A Task If It Meets Criteria](taskfile/run-a-task-if-it-meets-criteria.md)
|
|
||||||
|
|
||||||
### tmux
|
### tmux
|
||||||
|
|
||||||
- [Access Past Copy Buffer History](tmux/access-past-copy-buffer-history.md)
|
- [Access Past Copy Buffer History](tmux/access-past-copy-buffer-history.md)
|
||||||
- [Add Bindings To Split Panes To Current Directory](tmux/add-bindings-to-split-panes-to-current-directory.md)
|
|
||||||
- [Adjusting Window Pane Size](tmux/adjusting-window-pane-size.md)
|
- [Adjusting Window Pane Size](tmux/adjusting-window-pane-size.md)
|
||||||
- [Break Current Pane Out To Separate Window](tmux/break-current-pane-out-to-separate-window.md)
|
- [Break Current Pane Out To Separate Window](tmux/break-current-pane-out-to-separate-window.md)
|
||||||
- [Change Base Directory Of Existing Session](tmux/change-base-directory-of-existing-session.md)
|
- [Change Base Directory Of Existing Session](tmux/change-base-directory-of-existing-session.md)
|
||||||
- [Change Base Directory Without Detaching](tmux/change-base-directory-without-detaching.md)
|
- [Change Base Directory Without Detaching](tmux/change-base-directory-without-detaching.md)
|
||||||
- [Change The Default Prefix Key](tmux/change-the-default-prefix-key.md)
|
- [Change The Default Prefix Key](tmux/change-the-default-prefix-key.md)
|
||||||
- [Connect To Individual Overmind Processes Via tmux](tmux/connect-to-individual-overmind-processes-via-tmux.md)
|
|
||||||
- [Create A Named tmux Session](tmux/create-a-named-tmux-session.md)
|
- [Create A Named tmux Session](tmux/create-a-named-tmux-session.md)
|
||||||
- [Create A New Session In A New Server](tmux/create-a-new-session-in-a-new-server.md)
|
- [Create A New Session In A New Server](tmux/create-a-new-session-in-a-new-server.md)
|
||||||
- [Cycle Through Layouts](tmux/cycle-through-layouts.md)
|
- [Cycle Through Layouts](tmux/cycle-through-layouts.md)
|
||||||
@@ -1717,7 +1475,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Kill Other Connections To A Session](tmux/kill-other-connections-to-a-session.md)
|
- [Kill Other Connections To A Session](tmux/kill-other-connections-to-a-session.md)
|
||||||
- [Kill The Current Session](tmux/kill-the-current-session.md)
|
- [Kill The Current Session](tmux/kill-the-current-session.md)
|
||||||
- [List All Key Bindings](tmux/list-all-key-bindings.md)
|
- [List All Key Bindings](tmux/list-all-key-bindings.md)
|
||||||
- [List Processes Running Across All Session](tmux/list-processes-running-across-all-sessions.md)
|
|
||||||
- [List Sessions](tmux/list-sessions.md)
|
- [List Sessions](tmux/list-sessions.md)
|
||||||
- [Open New Splits To The Current Directory](tmux/open-new-splits-to-the-current-directory.md)
|
- [Open New Splits To The Current Directory](tmux/open-new-splits-to-the-current-directory.md)
|
||||||
- [Open New Window With A Specific Directory](tmux/open-new-window-with-a-specific-directory.md)
|
- [Open New Window With A Specific Directory](tmux/open-new-window-with-a-specific-directory.md)
|
||||||
@@ -1730,7 +1487,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Reset An Option Back To Its Default Value](tmux/reset-an-option-back-to-its-default-value.md)
|
- [Reset An Option Back To Its Default Value](tmux/reset-an-option-back-to-its-default-value.md)
|
||||||
- [Set Environment Variables When Creating Session](tmux/set-environment-variables-when-creating-session.md)
|
- [Set Environment Variables When Creating Session](tmux/set-environment-variables-when-creating-session.md)
|
||||||
- [Set Session Specific Environment Variables](tmux/set-session-specific-environment-variables.md)
|
- [Set Session Specific Environment Variables](tmux/set-session-specific-environment-variables.md)
|
||||||
- [Set Up Forwarding Prefix For Nested Session](tmux/set-up-forwarding-prefix-for-nested-session.md)
|
|
||||||
- [Show The Current Value For An Option](tmux/show-the-current-value-for-an-option.md)
|
- [Show The Current Value For An Option](tmux/show-the-current-value-for-an-option.md)
|
||||||
- [Swap Split Panes](tmux/swap-split-panes.md)
|
- [Swap Split Panes](tmux/swap-split-panes.md)
|
||||||
- [Switch To A Specific Session And Window](tmux/switch-to-a-specific-session-and-window.md)
|
- [Switch To A Specific Session And Window](tmux/switch-to-a-specific-session-and-window.md)
|
||||||
@@ -1764,9 +1520,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
### Unix
|
### Unix
|
||||||
|
|
||||||
- [All The Environment Variables](unix/all-the-environment-variables.md)
|
- [All The Environment Variables](unix/all-the-environment-variables.md)
|
||||||
- [Apply Successive Filters To Lines In Less](unix/apply-successive-filters-to-lines-in-less.md)
|
|
||||||
- [Authorize A cURL Request](unix/authorize-a-curl-request.md)
|
|
||||||
- [Browse And Search Help Docs](unix/browse-and-search-help-docs.md)
|
|
||||||
- [Cat A File With Line Numbers](unix/cat-a-file-with-line-numbers.md)
|
- [Cat A File With Line Numbers](unix/cat-a-file-with-line-numbers.md)
|
||||||
- [Cat Files With Color Using Bat](unix/cat-files-with-color-using-bat.md)
|
- [Cat Files With Color Using Bat](unix/cat-files-with-color-using-bat.md)
|
||||||
- [Change Default Shell For A User](unix/change-default-shell-for-a-user.md)
|
- [Change Default Shell For A User](unix/change-default-shell-for-a-user.md)
|
||||||
@@ -1777,9 +1530,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Check SSH Key Fingerprints Of Known Hosts](unix/check-ssh-key-fingerprints-of-known-hosts.md)
|
- [Check SSH Key Fingerprints Of Known Hosts](unix/check-ssh-key-fingerprints-of-known-hosts.md)
|
||||||
- [Check The Current Working Directory](unix/check-the-current-working-directory.md)
|
- [Check The Current Working Directory](unix/check-the-current-working-directory.md)
|
||||||
- [Check The Installed OpenSSL Version](unix/check-the-installed-openssl-version.md)
|
- [Check The Installed OpenSSL Version](unix/check-the-installed-openssl-version.md)
|
||||||
- [Check What Is Inside A Zip File](unix/check-what-is-inside-a-zip-file.md)
|
|
||||||
- [Clear The Screen](unix/clear-the-screen.md)
|
- [Clear The Screen](unix/clear-the-screen.md)
|
||||||
- [Combine All My TILs Into A Single File](unix/combine-all-my-tils-into-a-single-file.md)
|
|
||||||
- [Command Line Length Limitations](unix/command-line-length-limitations.md)
|
- [Command Line Length Limitations](unix/command-line-length-limitations.md)
|
||||||
- [Compare Two Variables In A Bash Script](unix/compare-two-variables-in-a-bash-script.md)
|
- [Compare Two Variables In A Bash Script](unix/compare-two-variables-in-a-bash-script.md)
|
||||||
- [Configure cd To Behave Like pushd In Zsh](unix/configure-cd-to-behave-like-pushd-in-zsh.md)
|
- [Configure cd To Behave Like pushd In Zsh](unix/configure-cd-to-behave-like-pushd-in-zsh.md)
|
||||||
@@ -1797,23 +1548,16 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Curl With Cookies](unix/curl-with-cookies.md)
|
- [Curl With Cookies](unix/curl-with-cookies.md)
|
||||||
- [Curling For Headers](unix/curling-for-headers.md)
|
- [Curling For Headers](unix/curling-for-headers.md)
|
||||||
- [Curling With Basic Auth Credentials](unix/curling-with-basic-auth-credentials.md)
|
- [Curling With Basic Auth Credentials](unix/curling-with-basic-auth-credentials.md)
|
||||||
- [Deduplicate List While Preserving Original Order](unix/deduplicate-list-while-preserving-original-order.md)
|
|
||||||
- [Delete Empty Files With Find](unix/delete-empty-files-with-find.md)
|
|
||||||
- [Determine ipv4 And ipv6 Public IP Addresses](unix/determine-ipv4-and-ipv6-public-ip-addresses.md)
|
|
||||||
- [Diff Two Files In Unified Format](unix/diff-two-files-in-unified-format.md)
|
|
||||||
- [Different Ways To Generate A v4 UUID](unix/different-ways-to-generate-a-v4-uuid.md)
|
- [Different Ways To Generate A v4 UUID](unix/different-ways-to-generate-a-v4-uuid.md)
|
||||||
- [Display All The Terminal Colors](unix/display-all-the-terminal-colors.md)
|
- [Display All The Terminal Colors](unix/display-all-the-terminal-colors.md)
|
||||||
- [Display Free Disk Space](unix/display-free-disk-space.md)
|
- [Display Free Disk Space](unix/display-free-disk-space.md)
|
||||||
- [Display Line Numbers While Using Less](unix/display-line-numbers-while-using-less.md)
|
|
||||||
- [Display The Contents Of A Directory As A Tree](unix/display-the-contents-of-a-directory-as-a-tree.md)
|
- [Display The Contents Of A Directory As A Tree](unix/display-the-contents-of-a-directory-as-a-tree.md)
|
||||||
- [Display The Target Of A Symbolic Link](unix/display-the-target-of-a-symbolic-link.md)
|
|
||||||
- [Do A Dry Run Of An rsync](unix/do-a-dry-run-of-an-rsync.md)
|
- [Do A Dry Run Of An rsync](unix/do-a-dry-run-of-an-rsync.md)
|
||||||
- [Do Not Overwrite Existing Files](unix/do-not-overwrite-existing-files.md)
|
- [Do Not Overwrite Existing Files](unix/do-not-overwrite-existing-files.md)
|
||||||
- [Download A File With Curl](unix/download-a-file-with-curl.md)
|
- [Download A File With Curl](unix/download-a-file-with-curl.md)
|
||||||
- [Enable Multi-Select Of Results With fzf](unix/enable-multi-select-of-results-with-fzf.md)
|
- [Enable Multi-Select Of Results With fzf](unix/enable-multi-select-of-results-with-fzf.md)
|
||||||
- [Exclude A Command From The ZSH History File](unix/exclude-a-command-from-the-zsh-history-file.md)
|
- [Exclude A Command From The ZSH History File](unix/exclude-a-command-from-the-zsh-history-file.md)
|
||||||
- [Exclude A Directory With Find](unix/exclude-a-directory-with-find.md)
|
- [Exclude A Directory With Find](unix/exclude-a-directory-with-find.md)
|
||||||
- [Exclude A Specific File From fd Results](unix/exclude-a-specific-file-from-fd-results.md)
|
|
||||||
- [Exclude Certain Files From An rsync Run](unix/exclude-certain-files-from-an-rsync-run.md)
|
- [Exclude Certain Files From An rsync Run](unix/exclude-certain-files-from-an-rsync-run.md)
|
||||||
- [Figure Out The Week Of The Year From The Terminal](unix/figure-out-the-week-of-the-year-from-the-terminal.md)
|
- [Figure Out The Week Of The Year From The Terminal](unix/figure-out-the-week-of-the-year-from-the-terminal.md)
|
||||||
- [File Type Info With File](unix/file-type-info-with-file.md)
|
- [File Type Info With File](unix/file-type-info-with-file.md)
|
||||||
@@ -1831,10 +1575,8 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Fix Previous Command With fc](unix/fix-previous-command-with-fc.md)
|
- [Fix Previous Command With fc](unix/fix-previous-command-with-fc.md)
|
||||||
- [Fix Shim Path After asdf Upgrade](unix/fix-shim-path-after-asdf-upgrade.md)
|
- [Fix Shim Path After asdf Upgrade](unix/fix-shim-path-after-asdf-upgrade.md)
|
||||||
- [Fix Unlinked Node Binaries With asdf](unix/fix-unlinked-node-binaries-with-asdf.md)
|
- [Fix Unlinked Node Binaries With asdf](unix/fix-unlinked-node-binaries-with-asdf.md)
|
||||||
- [Format And Display Small Amounts Of Columnar Data](unix/format-and-display-small-amounts-of-columnar-data.md)
|
|
||||||
- [Forward Multiple Ports Over SSH](unix/forward-multiple-ports-over-ssh.md)
|
- [Forward Multiple Ports Over SSH](unix/forward-multiple-ports-over-ssh.md)
|
||||||
- [Generate A SAML Key And Certificate Pair](unix/generate-a-saml-key-and-certificate-pair.md)
|
- [Generate A SAML Key And Certificate Pair](unix/generate-a-saml-key-and-certificate-pair.md)
|
||||||
- [Generate A Sequence Of Numbered Items](unix/generate-a-sequence-of-numbered-items.md)
|
|
||||||
- [Generate Base64 Encoding Without Newlines](unix/generate-base64-encoding-without-newlines.md)
|
- [Generate Base64 Encoding Without Newlines](unix/generate-base64-encoding-without-newlines.md)
|
||||||
- [Generate Random 20-Character Hex String](unix/generate-random-20-character-hex-string.md)
|
- [Generate Random 20-Character Hex String](unix/generate-random-20-character-hex-string.md)
|
||||||
- [Get A List Of Locales On Your System](unix/get-a-list-of-locales-on-your-system.md)
|
- [Get A List Of Locales On Your System](unix/get-a-list-of-locales-on-your-system.md)
|
||||||
@@ -1854,10 +1596,8 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Ignore A Directory During ripgrep Search](unix/ignore-a-directory-during-ripgrep-search.md)
|
- [Ignore A Directory During ripgrep Search](unix/ignore-a-directory-during-ripgrep-search.md)
|
||||||
- [Ignore The Alias When Running A Command](unix/ignore-the-alias-when-running-a-command.md)
|
- [Ignore The Alias When Running A Command](unix/ignore-the-alias-when-running-a-command.md)
|
||||||
- [Include Ignore Files In Ripgrep Search](unix/include-ignore-files-in-ripgrep-search.md)
|
- [Include Ignore Files In Ripgrep Search](unix/include-ignore-files-in-ripgrep-search.md)
|
||||||
- [Inspect EXIF Data For An Image File](unix/inspect-exif-data-for-an-image-file.md)
|
|
||||||
- [Interactively Browse Available Node Versions](unix/interactively-browse-availabile-node-versions.md)
|
- [Interactively Browse Available Node Versions](unix/interactively-browse-availabile-node-versions.md)
|
||||||
- [Interactively Switch asdf Package Versions](unix/interactively-switch-asdf-package-versions.md)
|
- [Interactively Switch asdf Package Versions](unix/interactively-switch-asdf-package-versions.md)
|
||||||
- [Interpret Cron Schedule From The CLI](unix/interpret-cron-schedule-from-the-cli.md)
|
|
||||||
- [Jump To The Ends Of Your Shell History](unix/jump-to-the-ends-of-your-shell-history.md)
|
- [Jump To The Ends Of Your Shell History](unix/jump-to-the-ends-of-your-shell-history.md)
|
||||||
- [Kill Everything Running On A Certain Port](unix/kill-everything-running-on-a-certain-port.md)
|
- [Kill Everything Running On A Certain Port](unix/kill-everything-running-on-a-certain-port.md)
|
||||||
- [Killing A Frozen SSH Session](unix/killing-a-frozen-ssh-session.md)
|
- [Killing A Frozen SSH Session](unix/killing-a-frozen-ssh-session.md)
|
||||||
@@ -1880,11 +1620,8 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Load Env Vars In Bash Script](unix/load-env-vars-in-bash-script.md)
|
- [Load Env Vars In Bash Script](unix/load-env-vars-in-bash-script.md)
|
||||||
- [Look Through All Files That Have Been Git Stashed](unix/look-through-all-files-that-have-been-git-stashed.md)
|
- [Look Through All Files That Have Been Git Stashed](unix/look-through-all-files-that-have-been-git-stashed.md)
|
||||||
- [Make Direnv Less Noisy](unix/make-direnv-less-noisy.md)
|
- [Make Direnv Less Noisy](unix/make-direnv-less-noisy.md)
|
||||||
- [Make Neovim The Default Way To View Man Pages](unix/make-neovim-the-default-way-to-view-man-pages.md)
|
|
||||||
- [Manually Pass Two Git Files To Delta](unix/manually-pass-two-git-files-to-delta.md)
|
- [Manually Pass Two Git Files To Delta](unix/manually-pass-two-git-files-to-delta.md)
|
||||||
- [Map A Domain To localhost](unix/map-a-domain-to-localhost.md)
|
- [Map A Domain To localhost](unix/map-a-domain-to-localhost.md)
|
||||||
- [Merge A Sequence Of Lines Of Output](unix/merge-a-sequence-of-lines-of-output.md)
|
|
||||||
- [Move A List Of Files To Another Directory](unix/move-a-list-of-files-to-another-directory.md)
|
|
||||||
- [Negative Look-Ahead Search With ripgrep](unix/negative-look-ahead-search-with-ripgrep.md)
|
- [Negative Look-Ahead Search With ripgrep](unix/negative-look-ahead-search-with-ripgrep.md)
|
||||||
- [Occupy A Local Port With Netcat](unix/occupy-a-local-port-with-netcat.md)
|
- [Occupy A Local Port With Netcat](unix/occupy-a-local-port-with-netcat.md)
|
||||||
- [Only Show The Matches](unix/only-show-the-matches.md)
|
- [Only Show The Matches](unix/only-show-the-matches.md)
|
||||||
@@ -1895,18 +1632,13 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Print A Range Of Lines For A File With Bat](unix/print-a-range-of-lines-for-a-file-with-bat.md)
|
- [Print A Range Of Lines For A File With Bat](unix/print-a-range-of-lines-for-a-file-with-bat.md)
|
||||||
- [Print DateTime Represented By Unix Timestamp](unix/print-datetime-represented-by-unix-timestamp.md)
|
- [Print DateTime Represented By Unix Timestamp](unix/print-datetime-represented-by-unix-timestamp.md)
|
||||||
- [Print Milliseconds In Human-Readable Format](unix/print-milliseconds-in-human-readable-format.md)
|
- [Print Milliseconds In Human-Readable Format](unix/print-milliseconds-in-human-readable-format.md)
|
||||||
- [Print Out File With Bat Without Formatting](unix/print-out-file-with-bat-without-formatting.md)
|
|
||||||
- [Print Out Files In Reverse](unix/print-out-files-in-reverse.md)
|
- [Print Out Files In Reverse](unix/print-out-files-in-reverse.md)
|
||||||
- [Print The Current Date In Human-Readable Format](unix/print-the-current-date-in-human-readable-format.md)
|
- [Print The Current Date In Human-Readable Format](unix/print-the-current-date-in-human-readable-format.md)
|
||||||
- [Produce A Lowercase V4 UUID](unix/produce-a-lowercase-v4-uuid.md)
|
- [Produce A Lowercase V4 UUID](unix/produce-a-lowercase-v4-uuid.md)
|
||||||
- [Provide A Fallback Value For Unset Parameter](unix/provide-a-fallback-value-for-unset-parameter.md)
|
- [Provide A Fallback Value For Unset Parameter](unix/provide-a-fallback-value-for-unset-parameter.md)
|
||||||
- [Remove A Directory Called `-p`](unix/remove-a-directory-called-dash-p.md)
|
- [Remove A Directory Called `-p`](unix/remove-a-directory-called-dash-p.md)
|
||||||
- [Rename A Bunch Of Files By Constructing mv Commands](unix/rename-a-bunch-of-files-by-constructing-mv-commands.md)
|
|
||||||
- [Repeat Yourself](unix/repeat-yourself.md)
|
- [Repeat Yourself](unix/repeat-yourself.md)
|
||||||
- [Replace Pattern Across Many Files In A Project](unix/replace-pattern-across-many-files-in-a-project.md)
|
- [Replace Pattern Across Many Files In A Project](unix/replace-pattern-across-many-files-in-a-project.md)
|
||||||
- [Restart Process Managed By `process-compose`](unix/restart-process-managed-by-process-compose.md)
|
|
||||||
- [Restart Specific Overmind Process](unix/restart-specific-overmind-process.md)
|
|
||||||
- [Reverse Each Line Of A File](unix/reverse-each-line-of-a-file.md)
|
|
||||||
- [Run A Command Repeatedly Several Times](unix/run-a-command-repeatedly-several-times.md)
|
- [Run A Command Repeatedly Several Times](unix/run-a-command-repeatedly-several-times.md)
|
||||||
- [Run A cURL Command Without The Progress Meter](unix/run-a-curl-command-without-the-progress-meter.md)
|
- [Run A cURL Command Without The Progress Meter](unix/run-a-curl-command-without-the-progress-meter.md)
|
||||||
- [Safely Edit The Sudoers File With Vim](unix/safely-edit-the-sudoers-file-with-vim.md)
|
- [Safely Edit The Sudoers File With Vim](unix/safely-edit-the-sudoers-file-with-vim.md)
|
||||||
@@ -1918,11 +1650,9 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Securely Remove Files](unix/securely-remove-files.md)
|
- [Securely Remove Files](unix/securely-remove-files.md)
|
||||||
- [See Where asdf Gets Current Tool Version](unix/see-where-asdf-gets-current-tool-version.md)
|
- [See Where asdf Gets Current Tool Version](unix/see-where-asdf-gets-current-tool-version.md)
|
||||||
- [Set The asdf Package Version For A Single Shell](unix/set-the-asdf-package-version-for-a-single-shell.md)
|
- [Set The asdf Package Version For A Single Shell](unix/set-the-asdf-package-version-for-a-single-shell.md)
|
||||||
- [Shorten SSH Commands With Aliases](unix/shorten-ssh-commands-with-aliases.md)
|
|
||||||
- [Show A File Preview When Searching With FZF](unix/show-a-file-preview-when-searching-with-fzf.md)
|
- [Show A File Preview When Searching With FZF](unix/show-a-file-preview-when-searching-with-fzf.md)
|
||||||
- [Show Disk Usage For The Current Directory](unix/show-disk-usage-for-the-current-directory.md)
|
- [Show Disk Usage For The Current Directory](unix/show-disk-usage-for-the-current-directory.md)
|
||||||
- [Show The Size Of Everything In A Directory](unix/show-the-size-of-everything-in-a-directory.md)
|
- [Show The Size Of Everything In A Directory](unix/show-the-size-of-everything-in-a-directory.md)
|
||||||
- [Show Tree View Of Processes And Subprocesses](unix/show-tree-view-of-processes-and-subprocesses.md)
|
|
||||||
- [Skip Paging If Output Fits On Screen With Less](unix/skip-paging-if-output-fits-on-screen-with-less.md)
|
- [Skip Paging If Output Fits On Screen With Less](unix/skip-paging-if-output-fits-on-screen-with-less.md)
|
||||||
- [SSH Escape Sequences](unix/ssh-escape-sequences.md)
|
- [SSH Escape Sequences](unix/ssh-escape-sequences.md)
|
||||||
- [SSH With Port Forwarding](unix/ssh-with-port-forwarding.md)
|
- [SSH With Port Forwarding](unix/ssh-with-port-forwarding.md)
|
||||||
@@ -1931,19 +1661,14 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Switch Versions of a Brew Formula](unix/switch-versions-of-a-brew-formula.md)
|
- [Switch Versions of a Brew Formula](unix/switch-versions-of-a-brew-formula.md)
|
||||||
- [Tell direnv To Load The Env File](unix/tell-direnv-to-load-the-env-file.md)
|
- [Tell direnv To Load The Env File](unix/tell-direnv-to-load-the-env-file.md)
|
||||||
- [Touch Access And Modify Times Individually](unix/touch-access-and-modify-times-individually.md)
|
- [Touch Access And Modify Times Individually](unix/touch-access-and-modify-times-individually.md)
|
||||||
- [Track Line Occurrences From Input With AWK](unix/track-line-occurrences-from-input-with-awk.md)
|
|
||||||
- [Transform Text To Lowercase](unix/transform-text-to-lowercase.md)
|
|
||||||
- [Type Fewer Paths With Brace Expansion](unix/type-fewer-paths-with-brace-expansion.md)
|
- [Type Fewer Paths With Brace Expansion](unix/type-fewer-paths-with-brace-expansion.md)
|
||||||
- [Undo Changes Made To Current Terminal Prompt](unix/undo-changes-made-to-current-terminal-prompt.md)
|
- [Undo Changes Made To Current Terminal Prompt](unix/undo-changes-made-to-current-terminal-prompt.md)
|
||||||
- [Undo Some Command Line Editing](unix/undo-some-command-line-editing.md)
|
- [Undo Some Command Line Editing](unix/undo-some-command-line-editing.md)
|
||||||
- [Unrestrict Where ripgrep Searches](unix/unrestrict-where-ripgrep-searches.md)
|
- [Unrestrict Where ripgrep Searches](unix/unrestrict-where-ripgrep-searches.md)
|
||||||
- [Update Package Versions Known By asdf Plugin](unix/update-package-versions-known-by-asdf-plugin.md)
|
- [Update Package Versions Known By asdf Plugin](unix/update-package-versions-known-by-asdf-plugin.md)
|
||||||
- [Use fzf To Change Directories](unix/use-fzf-to-change-directories.md)
|
- [Use fzf To Change Directories](unix/use-fzf-to-change-directories.md)
|
||||||
- [Use Negative Lookbehind Matching With ripgrep](unix/use-negative-lookbehind-matching-with-ripgrep.md)
|
|
||||||
- [Use Regex Pattern Matching With Grep](unix/use-regex-pattern-matching-with-grep.md)
|
- [Use Regex Pattern Matching With Grep](unix/use-regex-pattern-matching-with-grep.md)
|
||||||
- [Use The Readline Keybindings Anywhere](unix/use-the-readline-keybindings-anywhere.md)
|
|
||||||
- [View A Web Page In The Terminal](unix/view-a-web-page-in-the-terminal.md)
|
- [View A Web Page In The Terminal](unix/view-a-web-page-in-the-terminal.md)
|
||||||
- [View Manpages With More Color Using Bat](unix/view-manpages-with-more-color-using-bat.md)
|
|
||||||
- [View The Source For A Brew Formula](unix/view-the-source-for-a-brew-formula.md)
|
- [View The Source For A Brew Formula](unix/view-the-source-for-a-brew-formula.md)
|
||||||
- [Watch The Difference](unix/watch-the-difference.md)
|
- [Watch The Difference](unix/watch-the-difference.md)
|
||||||
- [Watch This Run Repeatedly](unix/watch-this-run-repeatedly.md)
|
- [Watch This Run Repeatedly](unix/watch-this-run-repeatedly.md)
|
||||||
@@ -2080,7 +1805,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Replace A Character](vim/replace-a-character.md)
|
- [Replace A Character](vim/replace-a-character.md)
|
||||||
- [Reset Target tslime Pane](vim/reset-target-tslime-pane.md)
|
- [Reset Target tslime Pane](vim/reset-target-tslime-pane.md)
|
||||||
- [Reverse A Group Of Lines](vim/reverse-a-group-of-lines.md)
|
- [Reverse A Group Of Lines](vim/reverse-a-group-of-lines.md)
|
||||||
- [Reword A Commit Message With Fugitive](vim/reword-a-commit-message-with-fugitive.md)
|
|
||||||
- [Rotate Everything By 13 Letters](vim/rotate-everything-by-13-letters.md)
|
- [Rotate Everything By 13 Letters](vim/rotate-everything-by-13-letters.md)
|
||||||
- [Rotate The Orientation Of Split Windows](vim/rotate-the-orientation-of-split-windows.md)
|
- [Rotate The Orientation Of Split Windows](vim/rotate-the-orientation-of-split-windows.md)
|
||||||
- [Running Bundle With vim-bundler](vim/running-bundle-with-vim-bundler.md)
|
- [Running Bundle With vim-bundler](vim/running-bundle-with-vim-bundler.md)
|
||||||
@@ -2127,10 +1851,8 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Advance Through Search Results](vscode/advance-through-search-results.md)
|
- [Advance Through Search Results](vscode/advance-through-search-results.md)
|
||||||
- [Enable Breadcrumbs For Version 1.26 Release](vscode/enable-breadcrumbs-for-version-126-release.md)
|
- [Enable Breadcrumbs For Version 1.26 Release](vscode/enable-breadcrumbs-for-version-126-release.md)
|
||||||
- [Find The Location Of User Settings JSON File](vscode/find-the-location-of-user-settings-json-file.md)
|
- [Find The Location Of User Settings JSON File](vscode/find-the-location-of-user-settings-json-file.md)
|
||||||
- [Jump Between Changes In Git Diff View](vscode/jump-between-changes-in-git-diff-view.md)
|
|
||||||
- [Jump To Problems In The Current File](vscode/jump-to-problems-in-the-current-file.md)
|
- [Jump To Problems In The Current File](vscode/jump-to-problems-in-the-current-file.md)
|
||||||
- [Open An Integrated Terminal Window](vscode/open-an-integrated-terminal-window.md)
|
- [Open An Integrated Terminal Window](vscode/open-an-integrated-terminal-window.md)
|
||||||
- [Open File On Remote Like GitHub](vscode/open-file-on-remote-like-github.md)
|
|
||||||
- [Pop Open The Quick Fix Window](vscode/pop-open-the-quick-fix-window.md)
|
- [Pop Open The Quick Fix Window](vscode/pop-open-the-quick-fix-window.md)
|
||||||
- [Step Through Project-Wide Search Results](vscode/step-through-project-wide-search-results.md)
|
- [Step Through Project-Wide Search Results](vscode/step-through-project-wide-search-results.md)
|
||||||
- [Synchronize Vim Clipboard With System Clipboard](vscode/synchronize-vim-clipboard-with-system-clipboard.md)
|
- [Synchronize Vim Clipboard With System Clipboard](vscode/synchronize-vim-clipboard-with-system-clipboard.md)
|
||||||
@@ -2156,36 +1878,28 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Change Window Name In iTerm](workflow/change-window-name-in-iterm.md)
|
- [Change Window Name In iTerm](workflow/change-window-name-in-iterm.md)
|
||||||
- [Configure Email Redirect With Cloudflare](workflow/configure-email-redirect-with-cloudflare.md)
|
- [Configure Email Redirect With Cloudflare](workflow/configure-email-redirect-with-cloudflare.md)
|
||||||
- [Control Media With Drop Keyboard](workflow/control-media-with-drop-keyboard.md)
|
- [Control Media With Drop Keyboard](workflow/control-media-with-drop-keyboard.md)
|
||||||
- [Create 1Password Login Item From The CLI](workflow/create-1password-login-item-from-the-cli.md)
|
|
||||||
- [Convert An ePub Document To PDF On Mac](workflow/convert-an-epub-document-to-pdf-on-mac.md)
|
- [Convert An ePub Document To PDF On Mac](workflow/convert-an-epub-document-to-pdf-on-mac.md)
|
||||||
- [Create A Local Sanity Dataset Backup](workflow/create-a-local-sanity-dataset-backup.md)
|
- [Create A Local Sanity Dataset Backup](workflow/create-a-local-sanity-dataset-backup.md)
|
||||||
- [Create A Public URL For A Local Server](workflow/create-a-public-url-for-a-local-server.md)
|
- [Create A Public URL For A Local Server](workflow/create-a-public-url-for-a-local-server.md)
|
||||||
- [Create Todo Items In Logseq](workflow/create-todo-items-in-logseq.md)
|
- [Create Todo Items In Logseq](workflow/create-todo-items-in-logseq.md)
|
||||||
- [Do Project Time Tracking From The CLI](workflow/do-project-time-tracking-from-the-cli.md)
|
|
||||||
- [Enable Dev Tools For Safari](workflow/enable-dev-tools-for-safari.md)
|
- [Enable Dev Tools For Safari](workflow/enable-dev-tools-for-safari.md)
|
||||||
- [Ensure Tooltips Appear In Screenshots](workflow/ensure-tooltips-appear-in-screenshots.md)
|
|
||||||
- [Forward Stripe Events To Local Server](workflow/forward-stripe-events-to-local-server.md)
|
- [Forward Stripe Events To Local Server](workflow/forward-stripe-events-to-local-server.md)
|
||||||
- [Get URL For GitHub User Profile Photo](workflow/get-url-for-github-user-profile-photo.md)
|
- [Get URL For GitHub User Profile Photo](workflow/get-url-for-github-user-profile-photo.md)
|
||||||
- [Get Your Public IP Address](workflow/get-your-public-ip-address.md)
|
- [Get Your Public IP Address](workflow/get-your-public-ip-address.md)
|
||||||
- [Import A Github Project Into CodeSandbox](workflow/import-a-github-project-into-codesandbox.md)
|
- [Import A Github Project Into CodeSandbox](workflow/import-a-github-project-into-codesandbox.md)
|
||||||
- [Interactively Kill A Process With fkill](workflow/interactively-kill-a-process-with-fkill.md)
|
- [Interactively Kill A Process With fkill](workflow/interactively-kill-a-process-with-fkill.md)
|
||||||
- [Move YouTube Subtitles Out Of The Way](workflow/move-youtube-subtitles-out-of-the-way.md)
|
|
||||||
- [Open Slack's Keyboard Shortcuts Reference Panel](workflow/open-slacks-keyboard-shortcuts-reference-panel.md)
|
- [Open Slack's Keyboard Shortcuts Reference Panel](workflow/open-slacks-keyboard-shortcuts-reference-panel.md)
|
||||||
- [Pop Videos Out As Picture-in-Picture](workflow/pop-videos-out-as-picture-in-picture.md)
|
- [Pop Videos Out As Picture-in-Picture](workflow/pop-videos-out-as-picture-in-picture.md)
|
||||||
- [Prune The Excess From node_modules](workflow/prune-the-excess-from-node-modules.md)
|
- [Prune The Excess From node_modules](workflow/prune-the-excess-from-node-modules.md)
|
||||||
- [Remove Pages From A PDF](workflow/remove-pages-from-a-pdf.md)
|
|
||||||
- [Rotate An Image To Be Oriented Upright](workflow/rotate-an-image-to-be-oriented-upright.md)
|
- [Rotate An Image To Be Oriented Upright](workflow/rotate-an-image-to-be-oriented-upright.md)
|
||||||
- [See Overlaps For A Set Of Time Zones](workflow/see-overlaps-for-a-set-of-time-zones.md)
|
- [See Overlaps For A Set Of Time Zones](workflow/see-overlaps-for-a-set-of-time-zones.md)
|
||||||
- [Send A Message To A Discord Channel](workflow/send-a-message-to-a-discord-channel.md)
|
- [Send A Message To A Discord Channel](workflow/send-a-message-to-a-discord-channel.md)
|
||||||
- [Send A PDF To Your Kindle](workflow/send-a-pdf-to-your-kindle.md)
|
- [Send A PDF To Your Kindle](workflow/send-a-pdf-to-your-kindle.md)
|
||||||
- [Set Recurring Reminders In Slack](workflow/set-recurring-reminders-in-slack.md)
|
- [Set Recurring Reminders In Slack](workflow/set-recurring-reminders-in-slack.md)
|
||||||
- [Show All Linear Keyboard Shortcuts](workflow/show-all-linear-keyboard-shortcuts.md)
|
|
||||||
- [Show Linting Errors In Zed](workflow/show-linting-errors-in-zed.md)
|
- [Show Linting Errors In Zed](workflow/show-linting-errors-in-zed.md)
|
||||||
- [Temporarily Hide CleanShot X Capture Previews](workflow/temporarily-hide-cleanshot-x-capture-previews.md)
|
- [Temporarily Hide CleanShot X Capture Previews](workflow/temporarily-hide-cleanshot-x-capture-previews.md)
|
||||||
- [Toggle Between Stories In Storybook](workflow/toggle-between-stories-in-storybook.md)
|
- [Toggle Between Stories In Storybook](workflow/toggle-between-stories-in-storybook.md)
|
||||||
- [Update asdf Plugins With Latest Package Versions](workflow/update-asdf-plugins-with-latest-package-versions.md)
|
- [Update asdf Plugins With Latest Package Versions](workflow/update-asdf-plugins-with-latest-package-versions.md)
|
||||||
- [View A Nicely-Formatted CSV In Terminal](workflow/view-a-nicely-formatted-csv-in-terminal.md)
|
|
||||||
- [View Nicely Formatted Markdown From Terminal](workflow/view-nicely-formatted-markdown-from-terminal.md)
|
|
||||||
- [View The PR For The Current GitHub Branch](workflow/view-the-pr-for-the-current-github-branch.md)
|
- [View The PR For The Current GitHub Branch](workflow/view-the-pr-for-the-current-github-branch.md)
|
||||||
|
|
||||||
### XState
|
### XState
|
||||||
@@ -2205,11 +1919,6 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Create Multi-Line Strings Without The Line Breaks](yaml/create-multi-line-strings-without-the-line-breaks.md)
|
- [Create Multi-Line Strings Without The Line Breaks](yaml/create-multi-line-strings-without-the-line-breaks.md)
|
||||||
- [YAML Is A Superset Of JSON](yaml/yaml-is-a-superset-of-json.md)
|
- [YAML Is A Superset Of JSON](yaml/yaml-is-a-superset-of-json.md)
|
||||||
|
|
||||||
### Zed
|
|
||||||
|
|
||||||
- [Jump From Section To Section](zed/jump-from-section-to-section.md)
|
|
||||||
- [Open Picker To Switch Between Projects](zed/open-picker-to-switch-between-projects.md)
|
|
||||||
|
|
||||||
### Zod
|
### Zod
|
||||||
|
|
||||||
- [Check If An Object Is Empty With Zod](zod/check-if-an-object-is-empty-with-zod.md)
|
- [Check If An Object Is Empty With Zod](zod/check-if-an-object-is-empty-with-zod.md)
|
||||||
@@ -2225,10 +1934,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Add To The Path Via Path Array](zsh/add-to-the-path-via-path-array.md)
|
- [Add To The Path Via Path Array](zsh/add-to-the-path-via-path-array.md)
|
||||||
- [Create And Jump Into A Directory](zsh/create-and-jump-into-a-directory.md)
|
- [Create And Jump Into A Directory](zsh/create-and-jump-into-a-directory.md)
|
||||||
- [Link A Scalar To An Array](zsh/link-a-scalar-to-an-array.md)
|
- [Link A Scalar To An Array](zsh/link-a-scalar-to-an-array.md)
|
||||||
- [List Available Zle Keybindings](zsh/list-available-zle-keybindings.md)
|
|
||||||
- [Open Current Command Line Prompt In Editor](zsh/open-current-command-line-prompt-in-editor.md)
|
|
||||||
- [Use A Space To Exclude Command From History](zsh/use-a-space-to-exclude-command-from-history.md)
|
- [Use A Space To Exclude Command From History](zsh/use-a-space-to-exclude-command-from-history.md)
|
||||||
- [Where And Which Are Whence](zsh/where-and-which-are-whence.md)
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -2238,10 +1944,6 @@ current number of TILs and display the result in the command tray.
|
|||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
I've written more about how this repo came to be in [How I Built a Learning
|
|
||||||
Machine](https://dev.to/jbranchaud/how-i-built-a-learning-machine-45k9) and [A
|
|
||||||
Decade of TILs](https://www.visualmode.dev/a-decade-of-tils).
|
|
||||||
|
|
||||||
I shamelessly stole this idea from
|
I shamelessly stole this idea from
|
||||||
[thoughtbot/til](https://github.com/thoughtbot/til).
|
[thoughtbot/til](https://github.com/thoughtbot/til).
|
||||||
|
|
||||||
@@ -2253,7 +1955,7 @@ I shamelessly stole this idea from
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
© 2015-2026 Josh Branchaud
|
© 2015-2025 Josh Branchaud
|
||||||
|
|
||||||
This repository is licensed under the MIT license. See `LICENSE` for
|
This repository is licensed under the MIT license. See `LICENSE` for
|
||||||
details.
|
details.
|
||||||
|
|||||||
-104
@@ -1,104 +0,0 @@
|
|||||||
version: '3'
|
|
||||||
|
|
||||||
vars:
|
|
||||||
NOTES_DIR: notes
|
|
||||||
NOTES_FILE: '{{.NOTES_DIR}}/NOTES.md'
|
|
||||||
EDITOR: '{{.EDITOR | default "nvim"}}'
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
default:
|
|
||||||
desc: Show available commands
|
|
||||||
cmds:
|
|
||||||
- task --list
|
|
||||||
|
|
||||||
browse:list:
|
|
||||||
desc: Print deduped, newest-first TIL paths
|
|
||||||
silent: true
|
|
||||||
cmds:
|
|
||||||
- |
|
|
||||||
git log --diff-filter=A --name-only --pretty=format: -- '*/*.md' \
|
|
||||||
| grep -v '^$' \
|
|
||||||
| awk '!seen[$0]++'
|
|
||||||
|
|
||||||
browse:
|
|
||||||
desc: Pick from 5 most recent TILs (fzf) and open in browser
|
|
||||||
interactive: true
|
|
||||||
silent: true
|
|
||||||
cmds:
|
|
||||||
- |
|
|
||||||
LIST=$(task browse:list)
|
|
||||||
FILE=$(printf '%s\n' "$LIST" | head -5 | fzf --prompt="Open TIL: " --height=40% --reverse) || true
|
|
||||||
if [ -n "$FILE" ]; then
|
|
||||||
gh browse "$FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
browse:latest:
|
|
||||||
desc: Open the single most recent TIL in the browser
|
|
||||||
silent: true
|
|
||||||
cmds:
|
|
||||||
- |
|
|
||||||
FILE=$(task browse:list | awk 'NR==1')
|
|
||||||
if [ -n "$FILE" ]; then
|
|
||||||
gh browse "$FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
notes:
|
|
||||||
desc: Interactive picker for notes tasks
|
|
||||||
cmds:
|
|
||||||
- |
|
|
||||||
TASK=$(task --list | grep "^\* notes:" | sed 's/^\* notes://' | sed 's/\s\+/ - /' | fzf --prompt="Select notes task: " --height=40% --reverse) || true
|
|
||||||
if [ -n "$TASK" ]; then
|
|
||||||
TASK_NAME=$(echo "$TASK" | awk '{print $1}' | sed 's/:$//')
|
|
||||||
task notes:$TASK_NAME
|
|
||||||
fi
|
|
||||||
interactive: true
|
|
||||||
silent: true
|
|
||||||
|
|
||||||
notes:edit:
|
|
||||||
desc: All-in-one edit, commit, and push notes
|
|
||||||
cmds:
|
|
||||||
- task notes:open
|
|
||||||
- task notes:push
|
|
||||||
|
|
||||||
notes:sync:
|
|
||||||
desc: Sync latest changes from the notes submodule
|
|
||||||
cmds:
|
|
||||||
- cd {{.NOTES_DIR}} && git checkout main && git pull
|
|
||||||
silent: false
|
|
||||||
|
|
||||||
notes:open:
|
|
||||||
desc: Opens NOTES.md (syncs latest changes first) in default editor
|
|
||||||
deps: [notes:sync]
|
|
||||||
cmds:
|
|
||||||
- $EDITOR {{.NOTES_FILE}}
|
|
||||||
interactive: true
|
|
||||||
|
|
||||||
notes:push:
|
|
||||||
desc: Commit and push changes to notes submodule
|
|
||||||
dir: '{{.NOTES_DIR}}'
|
|
||||||
cmds:
|
|
||||||
- git add NOTES.md
|
|
||||||
- git commit -m "Update notes - $(date '+%Y-%m-%d %H:%M')"
|
|
||||||
- git pull --rebase
|
|
||||||
- git push
|
|
||||||
status:
|
|
||||||
- git diff --exit-code NOTES.md
|
|
||||||
silent: false
|
|
||||||
|
|
||||||
notes:status:
|
|
||||||
desc: Check status of notes submodule
|
|
||||||
dir: '{{.NOTES_DIR}}'
|
|
||||||
cmds:
|
|
||||||
- git status
|
|
||||||
|
|
||||||
notes:diff:
|
|
||||||
desc: Show uncommitted changes in notes
|
|
||||||
dir: '{{.NOTES_DIR}}'
|
|
||||||
cmds:
|
|
||||||
- git diff NOTES.md
|
|
||||||
|
|
||||||
notes:log:
|
|
||||||
desc: Show recent commit history for notes
|
|
||||||
dir: '{{.NOTES_DIR}}'
|
|
||||||
cmds:
|
|
||||||
- git log --oneline -10
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Edit The Current Command Prompt
|
|
||||||
|
|
||||||
A neat feature of `bash` is the ability to open whatever the current state of
|
|
||||||
the command prompt is into your default editor.
|
|
||||||
|
|
||||||
Let's say we have a really long command that we've just tried to run, but it
|
|
||||||
failed and we need to make a small change somewhere in the middle. Instead of
|
|
||||||
holding the left arrow key for 30 seconds, we can instead hit `CTRL-X CTRL-E`.
|
|
||||||
|
|
||||||
This pops us into our `EDITOR` (or maybe `VISUAL`, not sure which). In my case,
|
|
||||||
that is `nvim`. I now have access to all the features I'm used to in `nvim` for
|
|
||||||
quickly navigating to and editing, searching and replacing, or whatever.
|
|
||||||
|
|
||||||
Once I've got the command how I like it, I can save and exit (`:wq`) and the
|
|
||||||
updated command will be executed.
|
|
||||||
|
|
||||||
This is similar to [the `fc` builtin](unix/fix-previous-command-with-fc.md),
|
|
||||||
which also happens to be available for `zsh`.
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# Clean Up Your Brew Installations
|
|
||||||
|
|
||||||
Over time as you upgrade brew-installed programs and make changes to your
|
|
||||||
`Brewfile`, your machine will have artifacts left behind that you no longer
|
|
||||||
need.
|
|
||||||
|
|
||||||
Periodically, it is good to clean things up.
|
|
||||||
|
|
||||||
First, you can get a summary of stale and outdated files that brew has
|
|
||||||
installed. Use the `--dry-run` flag.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ brew cleanup --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
If you feel good about what you see in the output, then give things a clean.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ brew cleanup
|
|
||||||
```
|
|
||||||
|
|
||||||
Second, if you are using a `Brewfile` to manage what `brew` installs, then you
|
|
||||||
can instruct `brew` to uninstall any dependencies that aren't specified in that
|
|
||||||
file.
|
|
||||||
|
|
||||||
By default it operates as a dry run and the `--force` flag will be needed to
|
|
||||||
actually do the cleanup. And specify the filename if it doesn't match the
|
|
||||||
default of `Brewfile`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ brew bundle cleanup --file=Brewfile.personal
|
|
||||||
```
|
|
||||||
|
|
||||||
If the output looks good, then force the cleanup:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ brew bundle cleanup --force --file=Brewfile.personal
|
|
||||||
```
|
|
||||||
|
|
||||||
See `brew cleanup --help` and `brew bundle --help` for more details.
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Install From Nonstandard Brewfile
|
|
||||||
|
|
||||||
When you want to install the packages listed in the `Brewfile` for your current
|
|
||||||
project (or dotfiles), you can run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ brew bundle
|
|
||||||
```
|
|
||||||
|
|
||||||
And `brew` knows to look for and use the `Brewfile` in the current directory.
|
|
||||||
|
|
||||||
If, however, you are trying to run `brew bundle` for a `Brewfile` located
|
|
||||||
somewhere besides the current directory *OR* you want to target a file with a
|
|
||||||
non-standard name (like
|
|
||||||
[`Brewfile.personal`](https://github.com/jbranchaud/dotfiles/blob/main/Brewfile.personal)),
|
|
||||||
then you can use the `--file` flag.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ brew bundle --file Brewfile.personal
|
|
||||||
```
|
|
||||||
|
|
||||||
This is what I do [here in my `dotfiles`
|
|
||||||
repo](https://github.com/jbranchaud/dotfiles/blob/b053f6251cae7ed52f698fc2a2c40ba82c5881b0/installer/mac-setup.sh#L42-L48).
|
|
||||||
|
|
||||||
See `man brew` and find the section on `brew bundle` for more details.
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Install Go Packages In Brewfile
|
|
||||||
|
|
||||||
Typically my `Brewfile` is only full of `brew` and `cask` directives. That's
|
|
||||||
starting to change now that `brew` supports installing Go packages listed in the
|
|
||||||
`Brewfile`.
|
|
||||||
|
|
||||||
Use the `go` directive and the URL to the hosted Go package.
|
|
||||||
|
|
||||||
Here is an example of a `Brewfile` that includes a `cask`, `brew`, and `go`
|
|
||||||
directive.
|
|
||||||
|
|
||||||
```
|
|
||||||
# screen resolution tool
|
|
||||||
cask "betterdisplay"
|
|
||||||
|
|
||||||
# Mac keychain management, gpg key
|
|
||||||
brew "pinentry-mac"
|
|
||||||
|
|
||||||
# Sanitized production Postgres dumps
|
|
||||||
go "github.com/jackc/pg_partialcopy"
|
|
||||||
```
|
|
||||||
|
|
||||||
I've recently added the exact package from above to my [`dotfiles`
|
|
||||||
repo](https://github.com/jbranchaud/dotfiles/commit/e83e9d19504f0e2f95eba33123f907f999bf865e).
|
|
||||||
|
|
||||||
Here is the [PR to `brew`](https://github.com/Homebrew/brew/pull/20798) where
|
|
||||||
this functionality was added back in October of 2025.
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# Duplicate Current Browser Tab
|
|
||||||
|
|
||||||
Let's say I'm on a specific page within a web app. Maybe I'm typing out a
|
|
||||||
comment on that page. Before I can hit submit, I need to reference something
|
|
||||||
elsewhere in the app, perhaps on the previous page.
|
|
||||||
|
|
||||||
I can `cmd+t` to open a new tab, type out the URL, hit enter, and then navigate
|
|
||||||
around until I find the page I'm looking for. I do this exact thing sometimes,
|
|
||||||
but it feels slow and clunky.
|
|
||||||
|
|
||||||
The other way I accomplish this which feels way smoother is to _duplicate the
|
|
||||||
current tab_. I can do that by `cmd`-clicking the reload button next to the URL
|
|
||||||
bar.
|
|
||||||
|
|
||||||
This opens another tab at the same URL with the same navigation history. I can
|
|
||||||
switch to that tab and hit the back button to go to the previous page, find the
|
|
||||||
thing I wanted to reference, and then return to the previous tab to finish what
|
|
||||||
I was doing.
|
|
||||||
|
|
||||||
To give a more concrete example: this happens all the time with GitHub PR
|
|
||||||
comments where I want to copy the URL or number of a specific PR to reference in
|
|
||||||
a comment I'm leaving on the current PR. Duplicating the tab, going _back_ to
|
|
||||||
the PR index view, finding the other PR, and copying its URL -- to me that is a
|
|
||||||
quicker flow popping open a fresh browser tab.
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Allow Edits From The Start
|
|
||||||
|
|
||||||
A common pattern for me when using Claude Code is that I start it up in a
|
|
||||||
project, I prompt it with a question or feature spec, it either comes up with a
|
|
||||||
plan or just starts working, and as soon as it is ready to make its first edits
|
|
||||||
to a file, it prompts me something like:
|
|
||||||
|
|
||||||
```
|
|
||||||
Do you want to make this edit to Taskfile.yml?
|
|
||||||
❯ 1. Yes
|
|
||||||
2. Yes, allow all edits during this session (shift+tab)
|
|
||||||
3. Type here to tell Claude what to do differently
|
|
||||||
```
|
|
||||||
|
|
||||||
That's a nice default so that I don't get surprised by Claude Code editing a
|
|
||||||
bunch of files.
|
|
||||||
|
|
||||||
However, if I'm in a git-backed project and I'm going into a session intending
|
|
||||||
to make edits, then I can skip the formalities. I can tell Claude Code when
|
|
||||||
starting up the session that edits are allowed.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ claude --permission-mode acceptEdits
|
|
||||||
```
|
|
||||||
|
|
||||||
When I do this, I'll see the following indicator below the prompt input field:
|
|
||||||
|
|
||||||
```
|
|
||||||
⏵⏵ accept edits on (shift+tab to cycle)
|
|
||||||
```
|
|
||||||
|
|
||||||
If I've already started `claude` but I forgot to specify that permission mode, I
|
|
||||||
can also toggle right into _accept edits_ by hitting `Shift+Tab`.
|
|
||||||
|
|
||||||
[source](https://www.youtube.com/watch?v=_IK18goX4X8)
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
# Ask An Agent To Fix Merge Conflicts
|
|
||||||
|
|
||||||
I work across a lot of different branches as part of a busy software team that
|
|
||||||
is doing the same. As I'm integrating feature branches into the `staging` branch
|
|
||||||
or rebasing the latest from `main` onto my feature branch, I often run into
|
|
||||||
merge conflicts. I find that frontier models are fast and accurate at fixing
|
|
||||||
merge conflicts. They quickly look at commit context on both sides of the merge,
|
|
||||||
figure out how the changes fit together, remove conflict markers, and run
|
|
||||||
targeted parts of the test suite as needed.
|
|
||||||
|
|
||||||
My workflow for a long time tended to be opening a fresh `claude` session and
|
|
||||||
then typing the words "Can you fix the merge conflict?" and letting the agent do
|
|
||||||
its thing.
|
|
||||||
|
|
||||||
I've shaved some of the friction from that process by turning it into a
|
|
||||||
one-liner that will show up in my shell history.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ claude -p "Can you fix the merge conflict?" --permission-mode auto
|
|
||||||
|
|
||||||
I fixed the merge conflicts in all 3 files and staged them. I haven't committed.
|
|
||||||
The two email-campaign test files (model and controller) pass: 64 runs, 0
|
|
||||||
failures.
|
|
||||||
|
|
||||||
The main thing: staging (HEAD) has already removed the old content columns from
|
|
||||||
`email_campaigns`. So where your branch's changes assumed those columns still
|
|
||||||
existed, I kept staging's version.
|
|
||||||
|
|
||||||
- **`app/models/email_campaign.rb`**: kept staging's comment, which says
|
|
||||||
`email_campaigns` has no content columns. Your branch's change to
|
|
||||||
`body_well_formed`, which uses `content_attribute_changed?`, merged in without
|
|
||||||
conflict and is kept.
|
|
||||||
- **`app/models/email_campaign/revisable.rb`**: kept staging's comment. I also
|
|
||||||
removed the `self.ignored_columns += REVISABLE_ATTRIBUTES...` line your branch
|
|
||||||
added, since the columns it hides no longer exist.
|
|
||||||
- **`test/models/email_campaign_test.rb`**: kept your branch's version. That
|
|
||||||
drops staging's "an edit that rewrites the body validates it" test: its checks
|
|
||||||
are the same as your branch's "an edit that changes the body validates it", and
|
|
||||||
its comment is about `body_changed?`, which is out of date now.
|
|
||||||
|
|
||||||
To finish the merge, run `git commit`.
|
|
||||||
```
|
|
||||||
|
|
||||||
The way this command works is that `-p "..."` specifies the prompt which is the
|
|
||||||
part I found myself typing out every single time. And then the
|
|
||||||
`--permission-mode auto` is important for invoking `claude` not in the
|
|
||||||
_interactive_ mode because it needs to be able to run without prompting you for
|
|
||||||
permission to inspect git things, edit files, and run tests.
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Build From My Phone In Cloud Environments
|
|
||||||
|
|
||||||
I mostly use Claude Code from a terminal with the `claude` CLI. Everything is
|
|
||||||
running on my machine (except the inference). The codebase is already there, the
|
|
||||||
feature branch is already in flight, all my tools and dotfiles are installed,
|
|
||||||
the dev server or container VMs are running, etc. It's the closest to how I
|
|
||||||
already worked before coding harnesses and allows me to seamlessly flow between
|
|
||||||
agentic code, review, making my own edits, and so forth.
|
|
||||||
|
|
||||||
However, I've been finding it pretty satisfying to open _Claude Code_ either in
|
|
||||||
the MacOS app or iOS app, connect a GitHub repo, and then ask for a quick
|
|
||||||
feature landed as a PR.
|
|
||||||
|
|
||||||
This flow uses [Claude in the Cloud](https://code.claude.com/docs/en/claude-code-on-the-web) to boot up a
|
|
||||||
development environment, pull down your codebase, create a branch, build a
|
|
||||||
feature, run tests, boot the app, do all the different explorations and checks
|
|
||||||
that `claude` typically does, and eventually land a PR back on GitHub.
|
|
||||||
|
|
||||||
What I find particularly remarkable about this flow is that this _cloud session_
|
|
||||||
is effectively synced across any device where I'm using Claude. So while I'm on
|
|
||||||
the train home from the gym, I open the Claude iOS app, pick my repo, and
|
|
||||||
describe a feature. By the time I get home, I open Claude.app on my computer
|
|
||||||
where I can skim through the chat summary, view the diff, and then suggest next
|
|
||||||
steps or jump to the PR on GitHub.
|
|
||||||
|
|
||||||
I'm finding this workflow particularly exciting for side projects because I can
|
|
||||||
kick off feature experiments from anywhere when the idea comes to me.
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# Distinguish Sessions With Different Colors
|
|
||||||
|
|
||||||
I sometimes have several Claude Code sessions open at once. As I bounce between
|
|
||||||
tmux windows, it can sometimes be tricky to tell them apart at a glance. One way
|
|
||||||
that Claude Code can help with this is with some light styling. You can change
|
|
||||||
the accent color of a session with the `/color` command.
|
|
||||||
|
|
||||||
Run it as is and it will choose a random color to set the session to.
|
|
||||||
|
|
||||||
Or you can pick from any of the available colors which it will give you a hint
|
|
||||||
for if you type a space after `/color`.
|
|
||||||
|
|
||||||
```
|
|
||||||
/color [red|blue|green|yellow|purple|orange|pink|cyan|default]
|
|
||||||
```
|
|
||||||
|
|
||||||
I can run the following to set it to cyan:
|
|
||||||
|
|
||||||
```
|
|
||||||
/color cyan
|
|
||||||
```
|
|
||||||
|
|
||||||
More details on this kinds of commands can be found in the [_Commands_
|
|
||||||
docs](https://code.claude.com/docs/en/commands).
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Monitor Usage Limits From CLI
|
|
||||||
|
|
||||||
When I first started using Claude Code enough to push the usage limits, I would
|
|
||||||
periodically switch over to the browser to check
|
|
||||||
`https://claude.ai/settings/usage` to see how close I was getting. That page
|
|
||||||
would tell me what percentage of my allotted usage I had consumed so far for the
|
|
||||||
current 5-hour session and then how long until that 5-hour usage window resets.
|
|
||||||
|
|
||||||
This can also be viewed directly in Claude Code for the CLI.
|
|
||||||
|
|
||||||
First, run the `/status` slash command and then _tab_ over to the _Usage_
|
|
||||||
section. There you will see the same details as in the web view.
|
|
||||||
|
|
||||||
I'm also learned, as I write this, that you can go directly to the _Usage_
|
|
||||||
section by typing the `/usage` slash command.
|
|
||||||
|
|
||||||
See [the docs](https://code.claude.com/docs/en/slash-commands) for a listing of
|
|
||||||
all slash commands.
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Open Current Prompt In Default Editor
|
|
||||||
|
|
||||||
[Claude Code](https://www.claude.com/product/claude-code) gives you a single
|
|
||||||
line to write a prompt. You can write and write as much as you want, but it will
|
|
||||||
all be on that single line. And avoid accidentally hitting 'Enter' before you're
|
|
||||||
done.
|
|
||||||
|
|
||||||
I found myself wanting to space out my thoughts, create a code block as part of
|
|
||||||
a prompt, and generally have a scratch pad instead of just a text box. By
|
|
||||||
hitting `ctrl-g`, I can move the current prompt into my default editor (in my
|
|
||||||
case, `nvim`). From there I can continue to write, edit, and format with all the
|
|
||||||
affordances of an editor.
|
|
||||||
|
|
||||||
Once I'm done crafting the prompt, I can save (e.g. `:wq`) and Claude Code will
|
|
||||||
be primed with that text. I can then hit 'Enter' to let `claude` do its thing.
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Pick Up Session Locally That Started In Cloud
|
|
||||||
|
|
||||||
I've been enjoying using _Claude Code_ from the iOS and MacOS apps for various
|
|
||||||
side tasks recently. For smaller things I can usually get most of the way there
|
|
||||||
from the app. And eventually I pull down the branch or have Claude create a PR
|
|
||||||
that I can review.
|
|
||||||
|
|
||||||
Sometimes I want to transfer the session onto my computer to pick up where it
|
|
||||||
left off for various reasons (e.g. I want the session to have access to some
|
|
||||||
local data or specific dependencies).
|
|
||||||
|
|
||||||
The `claude` CLI has a flag for that — `--teleport`.
|
|
||||||
|
|
||||||
> Resume a teleport session, optionally specify session ID
|
|
||||||
|
|
||||||
```
|
|
||||||
❯ claude --teleport
|
|
||||||
|
|
||||||
Select a session to resume (jbranchaud/still):
|
|
||||||
|
|
||||||
Updated Session Title
|
|
||||||
❯ 1. 21m ago Blogmark link search modal
|
|
||||||
2. 11h ago Mobile feed reader margins
|
|
||||||
3. 11h ago Feed pagination with Pagy
|
|
||||||
4. 1d ago RSS feed highlights and annotations
|
|
||||||
5. 1d ago RSS feed categories
|
|
||||||
6. 3d ago Blogmarks image drag-and-drop upload
|
|
||||||
|
|
||||||
↑/↓ to select · Enter to confirm · Esc to cancel
|
|
||||||
```
|
|
||||||
|
|
||||||
This is similar to how `--resume` works, but it is for a session that was
|
|
||||||
previously running in the cloud.
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# Resume Specific Session
|
|
||||||
|
|
||||||
There are a few different ways to resume a [Claude
|
|
||||||
Code](https://code.claude.com/docs/en/overview) session.
|
|
||||||
|
|
||||||
First, if I have exited a session for the current project and I want to pick
|
|
||||||
back up with that most recent one, then I can use `claude --continue`.
|
|
||||||
|
|
||||||
If I have had a few recent sessions for the current project and I want to
|
|
||||||
remember what they were and pick up where I left off with one of them, then I
|
|
||||||
can use `claude --resume` (with no argument). That will open a picker where I
|
|
||||||
can browser through a summary of the recent sessions based on their starting
|
|
||||||
prompt. The one I pick is the session that will be resumed.
|
|
||||||
|
|
||||||
Finally, if I have grabbed a specific session ID (UUID) during the session from
|
|
||||||
the `/status` output, then I can reference that value directly.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ claude --resume 92170532-be31-4a91-b2a9-025b8fa78232
|
|
||||||
```
|
|
||||||
|
|
||||||
See `claude --help` for more details.
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Set Permission Mode When Starting Session
|
|
||||||
|
|
||||||
The way I typically use Claude Code day-to-day is with a couple long-running
|
|
||||||
sessions for one to two clones of the project. I start a session with `claude`
|
|
||||||
and then hit `shift+tab` until I've toggled it to _auto_ mode. I do tightly
|
|
||||||
scoped features and `/clear` the context in between each.
|
|
||||||
|
|
||||||
I get used to being in _auto_ mode, so whenever I start a new `claude` session I
|
|
||||||
forget to first toggle from _manual_ to _auto_ mode.
|
|
||||||
|
|
||||||
This is where the
|
|
||||||
[`--permission-mode`](https://code.claude.com/docs/en/permission-modes) flag can
|
|
||||||
help. I can start a session directly in _auto_ mode like so:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ claude --permission-mode auto
|
|
||||||
```
|
|
||||||
|
|
||||||
Or if I know I want to generate a plan first, I can start it in _plan_ mode.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ claude --permission-mode plan
|
|
||||||
```
|
|
||||||
|
|
||||||
There is also the `--dangerously-skip-permissions` flag which is equivalent to
|
|
||||||
`--permission-mode bypassPermissions`. I tend to stay away from those unless I'm
|
|
||||||
working from a sandboxed dev container.
|
|
||||||
|
|
||||||
See `claude --help` for more details.
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Stash The Current Prompt To Send Another First
|
|
||||||
|
|
||||||
I've been working my way through the current cohort of Matt Pocock's [Claude
|
|
||||||
Code for Real
|
|
||||||
Engineers](https://www.aihero.dev/cohorts/claude-code-for-real-engineers-2026-04).
|
|
||||||
The best part about going through a series of videos like this is being able to
|
|
||||||
pick up big and small tips and tricks from another person's workflow.
|
|
||||||
|
|
||||||
One of the small things I picked up in an early video is the ability to stash
|
|
||||||
the current prompt.
|
|
||||||
|
|
||||||
Let's say I've gone to the trouble of writing out a detailed prompt, `@`'ing
|
|
||||||
some files, and so forth. Then I realize I need first prompt Claude to do
|
|
||||||
something else first. Instead of copy-pasting that prompt into my notes,
|
|
||||||
deleting it, issuing a different prompt, and then pasting it back in, I can hit
|
|
||||||
`Ctrl-s`.
|
|
||||||
|
|
||||||
`Ctrl-s` will _stash_ the current prompt, clearing out the prompt input. I can
|
|
||||||
then type in something else. Once I hit enter for that new prompt, it will be
|
|
||||||
sent to Claude and the stashed prompt will be immediately populated back into
|
|
||||||
the input.
|
|
||||||
|
|
||||||
Though `Ctrl-s` is mentioned when you hit `?` from within `claude` session, I
|
|
||||||
don't see it documented anywhere in their [Interactive Mode
|
|
||||||
reference](https://code.claude.com/docs/en/interactive-mode).
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
# Use Claude Code From Multiple Accounts
|
|
||||||
|
|
||||||
When I first start using Claude Code (`claude`) from the CLI, it will by default
|
|
||||||
use the `~/.claude` directory for settings, authentication, memory, sessions,
|
|
||||||
etc. This works fine as long as I'm working from a single, personal Claude
|
|
||||||
subscription. If I am juggling multiple subscriptions, there is not an obvious
|
|
||||||
way to switch between them.
|
|
||||||
|
|
||||||
A client I work with recently invited me to their Claude Team subscription via a
|
|
||||||
company email. I needed a way to access `claude` both from my existing
|
|
||||||
subscription, for other projects and work, while also doing stuff specific to
|
|
||||||
this client from the team account. Constantly logging in and out sure doesn't
|
|
||||||
feel like a sustainable solution.
|
|
||||||
|
|
||||||
The solution was to make use of the `CLAUDE_CONFIG_DIR` environment variable.
|
|
||||||
|
|
||||||
I first make a new config directory for Claude that is specific to this client.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ mkdir -p ~/.claude-client-x
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, from the project directory for this client (e.g.
|
|
||||||
`~/dev/clients/client-x/codebase`), I start a `claude` session pointing at this
|
|
||||||
new, empty directory.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ CLAUDE_CONFIG_DIR="~/.claude-client-x" claude
|
|
||||||
```
|
|
||||||
|
|
||||||
I'm prompted with a couple settings and config questions since this is a blank
|
|
||||||
slate `claude` session. Then I need to do a fresh authentication with `/login`.
|
|
||||||
For me, this involved authenticating in a separate Chrome profile where this
|
|
||||||
secondary Claude Team subscription was already active.
|
|
||||||
|
|
||||||
Lastly, I need to make sure that I use the correct "credentials"
|
|
||||||
whenever I'm starting a `claude` session. That means pointing `claude` to the
|
|
||||||
correct _config dir_. I tend to use `mise` or `direnv` across all my projects.
|
|
||||||
For any projects that pertain to _Client X_, I add the following to my
|
|
||||||
environment (i.e. `mise.local.toml`):
|
|
||||||
|
|
||||||
```
|
|
||||||
[env]
|
|
||||||
CLAUDE_CONFIG_DIR = "~/.claude-client-x"
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, whenever I run `claude` from that project, it will use that specific config
|
|
||||||
in `~/.claude-client-x`.
|
|
||||||
|
|
||||||
Pretty much everywhere else on my machine that I'm using `claude`, I want to use
|
|
||||||
the account that is already signed in at the default config dir, so no other
|
|
||||||
change is needed there.
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# Show Full URLs With Print Styles
|
|
||||||
|
|
||||||
Web pages are best experienced in a browser where you can fully interact with
|
|
||||||
them. Links, for instance, can be hovered, inspected, and clicked on to navigate
|
|
||||||
to the target location -- that's a core part of the web browser experience and
|
|
||||||
what makes the internet.
|
|
||||||
|
|
||||||
Some people have printers though and they want to be able to print off web
|
|
||||||
pages. Any web page can be printed off as is, but if your site or app is
|
|
||||||
anticipating certain pages being printed, then you may add some
|
|
||||||
`@print`-specific CSS styling to improve how it looks in print format.
|
|
||||||
|
|
||||||
Links are a prime example of lost interactivity. When printed, links render as
|
|
||||||
blue underlined text with no way to know what they are linking to. One trick
|
|
||||||
that I recently picked up from [this lobste.rs thread](https://lobste.rs/s/olnqh2/websites_should_be_printable#c_wigxfy) is to
|
|
||||||
add _after content_ that renders the actual, full URL next to the link.
|
|
||||||
|
|
||||||
```css
|
|
||||||
@media print
|
|
||||||
{
|
|
||||||
a[href]::after
|
|
||||||
{
|
|
||||||
content: " [" attr(href) "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This means that when a page has `<a href="https://still.visualmode.dev">still</a>`, the printed version will not
|
|
||||||
just render the word "still", but will be styled to render `still [https://still.visualmode.dev]`.
|
|
||||||
|
|
||||||
This will add content after links for both absolute URLs and relative paths (and
|
|
||||||
anchor tags). If I wanted to limit the after content to only show absolute URLs,
|
|
||||||
I could add a bit more specificity to the matching tag.
|
|
||||||
|
|
||||||
```css
|
|
||||||
@media print
|
|
||||||
{
|
|
||||||
a[href^="http"]::after
|
|
||||||
{
|
|
||||||
content: " [" attr(href) "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `^=` matches the pattern of `http` on the start of the `href` string which
|
|
||||||
means it will only display absolute URLs.
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# Allow Cursor To Be Launched From CLI
|
|
||||||
|
|
||||||
It is nice to be able to open Cursor for a specific project directly from the
|
|
||||||
terminal like so:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ cd ~/dev/my/project
|
|
||||||
|
|
||||||
$ cursor .
|
|
||||||
```
|
|
||||||
|
|
||||||
For the `cursor` launcher binary to be available like that, we have to find it
|
|
||||||
and add it to the path.
|
|
||||||
|
|
||||||
It is probably located in the `/Applications` folder and within that nested down
|
|
||||||
a couple directories is a `bin` directory that contains the binary we're looking
|
|
||||||
for.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls /Applications/Cursor.app/Contents/Resources/app/bin
|
|
||||||
bin/
|
|
||||||
├── code*
|
|
||||||
├── cursor*
|
|
||||||
└── cursor-tunnel*
|
|
||||||
```
|
|
||||||
|
|
||||||
The `cursor` binary is what we want, so let's add that to our path. In my case,
|
|
||||||
I'll add this to my `~/.zshrc` file.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export PATH="/Applications/Cursor.app/Contents/Resources/app/bin:$PATH"
|
|
||||||
```
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Cloudflare Allows CNAME For Apex Domain
|
|
||||||
|
|
||||||
If you want to set up a custom root (apex) domain with an app hosting provider
|
|
||||||
[like
|
|
||||||
Heroku](https://devcenter.heroku.com/articles/custom-domains#add-a-custom-root-domain),
|
|
||||||
you're going to need to work with a DNS provider that supports the non-standard
|
|
||||||
`ALIAS` records (or something equivalent).
|
|
||||||
|
|
||||||
In my case, I have my domain registered with Cloudflare. Cloudflare supports
|
|
||||||
this kind of CNAME lookup of an apex domain through [_CNAME
|
|
||||||
flattening_](https://developers.cloudflare.com/dns/cname-flattening/).
|
|
||||||
|
|
||||||
Unlike other registrars that use a separate `ALIAS` record concept, Cloudflare
|
|
||||||
allows you to set up a specialized `CNAME` record. Go into the DNS settings for
|
|
||||||
the domain of interest, click "Add Record", and then select `CNAME`. From there,
|
|
||||||
instead of entering a traditional subdomain like `www`, you put the `@` symbol
|
|
||||||
which tells Cloudflare that this is a record for the apex domain. That record
|
|
||||||
will still point to a target like `abc123.herokudns.com` as a more traditional
|
|
||||||
`CANME` would do.
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Set, Get, And Unset Env Vars With Dokku
|
|
||||||
|
|
||||||
The `dokku` CLI provides `config` subcommands for managing environment variables
|
|
||||||
for the target container.
|
|
||||||
|
|
||||||
An env var can be set for an active container with `config:set`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ dokku config:set app-name JEMALLOC_ENABLED=true MALLOC_CONF="stats_print:true"
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice I'm able to set multiple env vars at once if needed.
|
|
||||||
|
|
||||||
If I ever need to check what an env var is currently set to for one of my app
|
|
||||||
containers, I can use `config:get`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ dokku config:get app-name JEMALLOC_ENABLED
|
|
||||||
true
|
|
||||||
```
|
|
||||||
|
|
||||||
I can always override any value with another `config:set`. However, if I need to
|
|
||||||
entirely remove the env var, I can use `config:unset`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ dokku config:unset app-name MALLOC_CONF
|
|
||||||
```
|
|
||||||
|
|
||||||
[source](https://dokku.com/docs/configuration/environment-variables/)
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"excludes": ["README.md"],
|
|
||||||
"plugins": ["https://plugins.dprint.dev/markdown-0.16.0.wasm"]
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
# Check If A File Has Changed In A Script
|
|
||||||
|
|
||||||
If I'm at the command line and I want to check if a file has changed, I can run
|
|
||||||
`git diff` and see what has changed. If I want to be more specific, I can run
|
|
||||||
`git diff README.md` to see if there are changes to that specific file.
|
|
||||||
|
|
||||||
If I'm trying to do this check in a script though, I want the command to clearly
|
|
||||||
tell the script _Yes_ or _No_. Usually a script looks for an exit code to
|
|
||||||
determine what path to take. But as long as `git diff` runs successfully,
|
|
||||||
regardless of whether or not their are changes, it is going to have an
|
|
||||||
affirmative exit code of `0`.
|
|
||||||
|
|
||||||
This is why `git diff` offers the `--exit-code` flag.
|
|
||||||
|
|
||||||
> Make the program exit with codes similar to diff(1). That is, it exits with 1
|
|
||||||
> if there were differences and 0 means no differences.
|
|
||||||
|
|
||||||
With that in mind, we can wire up a script with `git diff` that takes different
|
|
||||||
paths depending on whether or not there are changes.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
if ! git diff --exit-code README.md; then
|
|
||||||
echo "README.md has changes"
|
|
||||||
else
|
|
||||||
echo "README.md is clean"
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
We can take this a step further and instead use the `--quiet` flag.
|
|
||||||
|
|
||||||
> Disable all output of the program. Implies --exit-code. Disables execution of
|
|
||||||
> external diff helpers whose exit code is not trusted
|
|
||||||
|
|
||||||
This exhibits the same behavior as `--exit-code` and goes the additional step of
|
|
||||||
silencing diff output and disabling execution of external diff helpers like
|
|
||||||
`delta`.
|
|
||||||
|
|
||||||
See `man git-diff` for more details.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Check If A File Is Under Version Control
|
|
||||||
|
|
||||||
The `git ls-files` command can be used with the `--error-unmatch` flag to check
|
|
||||||
if a file is under version control. It does this by checking if any of the
|
|
||||||
listed files appears on the _index_. If any does not, it is treated as an error.
|
|
||||||
|
|
||||||
In a project, I have a `README.md` that is under version control. And I have
|
|
||||||
`node_modules` that shouldn't be under version control (which is why they are
|
|
||||||
listed in my `.gitignore` file). I can check the README and a file somewhere in
|
|
||||||
`node_modules`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git ls-files --error-unmatch README.md
|
|
||||||
README.md
|
|
||||||
|
|
||||||
❯ git ls-files --error-unmatch node_modules/@ai-sdk/anthropic/CHANGELOG.md
|
|
||||||
error: pathspec 'node_modules/@ai-sdk/anthropic/CHANGELOG.md' did not match any file(s) known to git
|
|
||||||
Did you forget to 'git add'?
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice the second command results in an error because of the untracked
|
|
||||||
`CHANGELOG.md` file in `node_modules`.
|
|
||||||
|
|
||||||
Here is another example of this at work while specifying multiple files:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git ls-files --error-unmatch README.md node_modules/@ai-sdk/anthropic/CHANGELOG.md package.json
|
|
||||||
README.md
|
|
||||||
package.json
|
|
||||||
error: pathspec 'node_modules/@ai-sdk/anthropic/CHANGELOG.md' did not match any file(s) known to git
|
|
||||||
Did you forget to 'git add'?
|
|
||||||
```
|
|
||||||
|
|
||||||
Each tracked file gets listed and then the untracked file results in an error.
|
|
||||||
|
|
||||||
See `man git-ls-files` for more details.
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Check What Branches Contain A Specific Commit
|
|
||||||
|
|
||||||
The `git branch` command comes with a `--contains` flag that can tell me what
|
|
||||||
local branches contain a specific commit based on the SHA of that commit.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git branch --contains a73d9173c2399069fa202fe65da0a8927814fd84
|
|
||||||
* main
|
|
||||||
jb/migrate-to-basedpyright
|
|
||||||
jb/migrate-date-files-to-repository-pattern
|
|
||||||
```
|
|
||||||
|
|
||||||
I am currently on the `main` branch which is why it shows the `*` next to that
|
|
||||||
one. This SHA also appears on those other two branches.
|
|
||||||
|
|
||||||
This command could be useful in a variety of situations.
|
|
||||||
|
|
||||||
1. If I'm looking at a commit on a branch and I cannot remember if it has been
|
|
||||||
integrated upstream yet. This check could tell me (unless commit squashing
|
|
||||||
happens).
|
|
||||||
2. If I'm on `main`, as I was above, and I am trying to remember what branch
|
|
||||||
introduced a commit, this can help with that sleuthing. This assumes I don't
|
|
||||||
delete branches.
|
|
||||||
3. Maybe I've just run a `git bisect` to track down a bad commit and I want to
|
|
||||||
see what are all the local branches that are impacted.
|
|
||||||
|
|
||||||
See `man git-branch` for more details.
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Cherry Pick Multiple Commits At Once
|
|
||||||
|
|
||||||
I've always thought of `git cherry-pick` as being a command that you can run
|
|
||||||
against a single commit by specifying the SHA of that commit. That's how I've
|
|
||||||
always used it.
|
|
||||||
|
|
||||||
The man page for `git-cherry-pick` plainly states:
|
|
||||||
|
|
||||||
> Given one or more existing commits, apply the change each one introduces,
|
|
||||||
> recording a new commit for each.
|
|
||||||
|
|
||||||
We can cherry pick multiple commits at once in a single command. They will be
|
|
||||||
applied one at a time in the order listed.
|
|
||||||
|
|
||||||
Here we can see an example of applying two commits to the current branch and
|
|
||||||
the accompanying output as they are auto-merged.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ git cherry-pick 5206af5 6362f41
|
|
||||||
Auto-merging test/services/event_test.rb
|
|
||||||
[jb/my-feature-branch 961f3deb] Use the other testing syntax
|
|
||||||
Date: Fri May 2 10:50:14 2025 -0500
|
|
||||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
|
||||||
Auto-merging test/services/event_test.rb
|
|
||||||
[jb/my-feature-branch b15835d0] Make other changes to the test
|
|
||||||
Date: Fri May 2 10:54:48 2025 -0500
|
|
||||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
|
||||||
```
|
|
||||||
|
|
||||||
If the commits cannot be cleanly merged, then you may need to do some manual
|
|
||||||
resolution as they are applied. Or maybe you want to try including the
|
|
||||||
`-Xpatience` merge strategy.
|
|
||||||
|
|
||||||
See `man git-cherry-pick` for more details. Make sure to look at the _Examples_
|
|
||||||
section which contains much more advanced examples beyond what is shown above.
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# Clear Entries From Git Stash
|
|
||||||
|
|
||||||
I often stash changes as I'm moving between branches, rebasing, or pulling in
|
|
||||||
changes from the remote. Usually these are changes that I will want to restore
|
|
||||||
with a `git stash pop` in a few moments.
|
|
||||||
|
|
||||||
However, sometimes these stashed changes are abandoned to time.
|
|
||||||
|
|
||||||
When I run `git stash list` on an active project, I see that there are nine
|
|
||||||
entries in the list. When I do `git show stash@{0}` and `git show stash@{1}` to
|
|
||||||
see the changes that comprise the latest two entries, I don't see anything I
|
|
||||||
care about.
|
|
||||||
|
|
||||||
I can get rid of those individual entries with, say, `git stash drop
|
|
||||||
stash@{0}`.
|
|
||||||
|
|
||||||
But I'm pretty confident that I don't care about any of the nine entries in my
|
|
||||||
stash list, so I want to _clear_ out all of them. I can do that with:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ git stash clear
|
|
||||||
```
|
|
||||||
|
|
||||||
Now when I run `git stash list`, I see nothing.
|
|
||||||
|
|
||||||
See `man git-stash` for more details.
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Determine Absolute Path Of Top-Level Project Directory
|
|
||||||
|
|
||||||
The `git rev-parse` command is a git plumbing command for parsing different
|
|
||||||
kinds of things in git into a canonical form that can be used in a deterministic
|
|
||||||
way by scripts. I would typically think of using it to work with branch names,
|
|
||||||
tags, and other kinds of refs.
|
|
||||||
|
|
||||||
There is a handy, sorta off-label use for it in determining the absolute path of
|
|
||||||
the root directory for the current git repository. Use the `--show-toplevel`
|
|
||||||
flag with no other arguments.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git rev-parse --show-toplevel
|
|
||||||
/Users/lastword/dev/jbranchaud/til
|
|
||||||
```
|
|
||||||
|
|
||||||
Here, I am in the local copy of [my TIL repo](https://github.com/jbranchaud/til). This command gives me the absolute
|
|
||||||
path of the top-level directory where that `.git` directory resides.
|
|
||||||
|
|
||||||
This is useful for scripts that need to orient themselves to the current
|
|
||||||
project's top-level directory regardless of what directory they are being
|
|
||||||
executed from. This is useful for things like a git hook script or monorepos
|
|
||||||
with scripts located in a specific sub-project directory.
|
|
||||||
|
|
||||||
Also worth mentioning is the `--show-superproject-working-tree` flag. In my TIL
|
|
||||||
repo, I have a private repository included as a submodule. Within that directory
|
|
||||||
`--show-toplevel` will produce the absolute path to the submodule. If I instead
|
|
||||||
want the absolute path of the _super project_ (in this case TIL), then I can use
|
|
||||||
this other flag.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git rev-parse --show-toplevel
|
|
||||||
/Users/lastword/dev/jbranchaud/til/notes
|
|
||||||
|
|
||||||
❯ git rev-parse --show-superproject-working-tree
|
|
||||||
/Users/lastword/dev/jbranchaud/til
|
|
||||||
```
|
|
||||||
|
|
||||||
See `man git-rev-parse` for more details.
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Display All Git Log Entries In My Local Timezone
|
|
||||||
|
|
||||||
I tend to work with remote teams distributed across across multiple time zones.
|
|
||||||
In that context, it is important to have an awareness of what time zone each
|
|
||||||
person is operating in and to communicate clearly around that.
|
|
||||||
|
|
||||||
When looking at the output for `git log` on a distributed team, the timestamps
|
|
||||||
for each entry can be all over the place. If I want to understand when something
|
|
||||||
was committed, I have to look at the time as well as the time zone offset and
|
|
||||||
mentally translate it to my own time zone.
|
|
||||||
|
|
||||||
There is a `git config` option to alleviate this issue by having `git log`
|
|
||||||
convert and display all timestamps into your local time zone.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ git config --global log.date rfc-local
|
|
||||||
```
|
|
||||||
|
|
||||||
Running that will add this entry to your _global_ git config file:
|
|
||||||
|
|
||||||
```
|
|
||||||
[log]
|
|
||||||
date = rfc-local
|
|
||||||
```
|
|
||||||
|
|
||||||
Now the time that was displaying as `Wed Apr 8 20:12:33 2026 -0400` will display
|
|
||||||
as `Wed, 8 Apr 2026 19:12:33 -0500`.
|
|
||||||
|
|
||||||
This also helps with smoothing out differences from DST and for commits produced
|
|
||||||
by AI agents in sandbox environments where the locale is set to UTC.
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# Exclude A Directory During A Command
|
|
||||||
|
|
||||||
Many of the git commands we use, such as `git add`, `git restore`, etc., target
|
|
||||||
files and paths relative to the current directory. This is typically exactly
|
|
||||||
what we want, to stage and unstage and so forth the files and directories in
|
|
||||||
front of us.
|
|
||||||
|
|
||||||
I recently ran into a situation where I needed to restore a small subset of
|
|
||||||
changes. At the same time, I had a massive number of auto-generated files
|
|
||||||
recording HTTP interactions (hundreds of files, modified on the working tree).
|
|
||||||
I wanted to run a `git restore`, but wading through all those HTTP recording
|
|
||||||
files was not feasible.
|
|
||||||
|
|
||||||
I needed to exclude those files. They all belonged to a `spec/cassettes`
|
|
||||||
directory. I could exclude them with a _pathspec_ magic signature pattern which
|
|
||||||
is used to alter and limit the paths in a git command.
|
|
||||||
|
|
||||||
A _pathspec_ magic signature is a special pattern made up of a `:` followed by
|
|
||||||
some signature declaring what the pattern means.
|
|
||||||
|
|
||||||
The `(exclude)`, `!`, and `^` magic signatures all mean the same thing —
|
|
||||||
exclude. So, we can exclude a directory from a `git restore` command like so:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ git restore --patch -- . ':!spec/cassettes'
|
|
||||||
```
|
|
||||||
|
|
||||||
We've employed two pathspec patterns here. The first, `.`, scopes everything to
|
|
||||||
the current directory. The second, `':!spec/cassettes'` excludes everything in
|
|
||||||
the `spec/cassettes` directory.
|
|
||||||
|
|
||||||
See `man gitglossary` for more on _pathspecs_.
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# Highlight Small Change On Single Line
|
|
||||||
|
|
||||||
Sometimes a change gets made on a single, long line of text in a Git tracked
|
|
||||||
file. If it is a small, subtle change, then it can be hard to pick out when
|
|
||||||
looking at the diff. A standard diff will show a green line of text stacked on
|
|
||||||
a red line of text with no more granular information.
|
|
||||||
|
|
||||||
There are two ways we can improve the diff output in these situations.
|
|
||||||
|
|
||||||
The first is built-in to git. It is the `--word-diff` flag which will visually
|
|
||||||
isolate the portions of the line that have changed.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git diff --word-diff README.md
|
|
||||||
```
|
|
||||||
|
|
||||||
Which will produce something like this:
|
|
||||||
|
|
||||||
```diff
|
|
||||||
A collection of concise write-ups on small things I learn [-day to day-]{+day-to-day+} across a
|
|
||||||
```
|
|
||||||
|
|
||||||
The outgoing part is wrapped in `[-...-]` and the incoming part is wrapped in
|
|
||||||
`{+...+}`.
|
|
||||||
|
|
||||||
The second (and my preference) is to use
|
|
||||||
[`delta`](https://github.com/dandavison/delta) as an external differ and pager
|
|
||||||
for git.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git -c core.pager=delta diff README.md
|
|
||||||
```
|
|
||||||
|
|
||||||
I cannot visually demonstrate the difference in a standard code block. So I'll
|
|
||||||
describe it. We see a red and green line stacked on each other, but with muted
|
|
||||||
background colors. Then the specific characters that are different stand out
|
|
||||||
because they are highlighted with brighter red and green. I [posted a visual
|
|
||||||
here](https://bsky.app/profile/jbranchaud.bsky.social/post/3ln245orlxs2j).
|
|
||||||
|
|
||||||
`delta` can also be added as a standard part of your config like I demonstrate
|
|
||||||
in [Better Diffs With Delta](git/better-diffs-with-delta.md).
|
|
||||||
|
|
||||||
h/t to [Dillon Hafer's post on
|
|
||||||
`--word-diff`](https://til.hashrocket.com/posts/t994rwt3fg-finds-diffs-in-long-line)
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
# List All Authors On Git Repository
|
|
||||||
|
|
||||||
The `git log` is the ledger of all commits made to the repository. If I am on
|
|
||||||
the `main` branch and I have the latest pulled from the remote, then running
|
|
||||||
`git log` will be a complete listing of all commits.
|
|
||||||
|
|
||||||
`git log` includes more information than just authorship. I can narrow that all
|
|
||||||
down to only author name and author email using the `--format` flag. For all the
|
|
||||||
format string options available, I can run `man git-log` and jump to the `PRETTY
|
|
||||||
FORMATS` section, scrolling just past the built-in formats.
|
|
||||||
|
|
||||||
The two I am interested in are `%an` (Author Name) and `%ae` (Author Email). I
|
|
||||||
can arrange these however I want in the format string argument. Here is what it
|
|
||||||
looks like for the [`egghead-next`
|
|
||||||
project](https://github.com/skillrecordings/egghead-next):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git log --format='%an <%ae>'
|
|
||||||
Zac Jones <zacjones93@gmail.com>
|
|
||||||
Zac Jones <zacjones93@gmail.com>
|
|
||||||
Zac Jones <zacjones93@gmail.com>
|
|
||||||
Zac Jones <zacjones93@gmail.com>
|
|
||||||
Zac Jones <zacjones93@gmail.com>
|
|
||||||
Zac Jones <zacjones93@gmail.com>
|
|
||||||
Zac Jones <zacjones93@gmail.com>
|
|
||||||
John Lindquist <johnlindquist@gmail.com>
|
|
||||||
Zac Jones <zacjones93@gmail.com>
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
I get _name_ followed by _email_ wrapped in angle brackets. This is only so
|
|
||||||
useful though because I am going to see tons duplicate authors especially for a
|
|
||||||
project with hundreds and thousands of commits. I can narrow this down with [a
|
|
||||||
deduplication trick via
|
|
||||||
`awk`](unix/deduplicate-list-while-preserving-original-order.md):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git log --format='%an <%ae>' | awk '!seen[$0]++'
|
|
||||||
Zac Jones <zacjones93@gmail.com>
|
|
||||||
John Lindquist <johnlindquist@gmail.com>
|
|
||||||
Josh Branchaud <jbranchaud@gmail.com>
|
|
||||||
Vojta Holik <vojta@egghead.io>
|
|
||||||
Creeland A. Provinsal <cree@egghead.io>
|
|
||||||
joel <joelhooks@gmail.com>
|
|
||||||
Creeland <cree@provinsal.com>
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
That's already a big improvement. The only other change I want to make is
|
|
||||||
related to the default ordering of `git log`. It lists out commits in descending
|
|
||||||
order (most recent first). I want to see authors listed in the order that they
|
|
||||||
first committed to the project. Adding in the `--reverse` flag will solve for
|
|
||||||
that.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git log --reverse --format='%an <%ae>' | awk '!seen[$0]++'
|
|
||||||
Joel Hooks <joelhooks@gmail.com>
|
|
||||||
johnlindquist <johnlindquist@gmail.com>
|
|
||||||
John Lindquist <johnlindquist@gmail.com>
|
|
||||||
William Johnson <w.alexander.johnson@gmail.com>
|
|
||||||
depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
|
|
||||||
Evgeniy Nagalskiy <evgeniy.nagalskiy@gmail.com>
|
|
||||||
Taylor Bell <taylorbell@gmail.com>
|
|
||||||
Maggie Appleton <maggie.fm.appleton@gmail.com>
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
See `man git-log` for more details.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# List All Commits Where File Was Added Or Deleted
|
|
||||||
|
|
||||||
I noticed I wasn't able to find a file with a specific name anywhere in my
|
|
||||||
codebase. I expected it to be there, so I wondered when it had been added and
|
|
||||||
deleted from the codebase according to the git commit history.
|
|
||||||
|
|
||||||
This calls for running a `git log`, but with a couple flags. First, I'll include
|
|
||||||
`--name-status` so that each commit that is listed includes the file names with
|
|
||||||
the change status (i.e. `A` for added and `D` for deleted). Then the
|
|
||||||
`--diff-filter` flag tells git that I am only looking for `A`dded and `D`eleted
|
|
||||||
files. Then the `--` indicates that a file path will follow, even a regex
|
|
||||||
pattern is valid here.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git log --name-status --diff-filter=AD -- '*_mock_payment_form.*'
|
|
||||||
```
|
|
||||||
|
|
||||||
I'm looking for what is called a _partial_ in Rails. I know the filename
|
|
||||||
consists of `_mock_payment_form`. The leading `*` is so that I can be vague
|
|
||||||
about the directory this might be found in. That's useful if this file was
|
|
||||||
potentially moved around. The trailing `.*` indicates the file extension which I
|
|
||||||
also want to be vague about.
|
|
||||||
|
|
||||||
For any of the commits returned by this `git log`, I can grab the SHA and run
|
|
||||||
`git show <SHA>` to see the full picture of that commit.
|
|
||||||
|
|
||||||
Another flag that might be useful to add is the `--all` flag which will look
|
|
||||||
across all refs/branches instead of just the branch (`main`) that I'm currently
|
|
||||||
on.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git log --all --name-status --diff-filter=AD -- '*_mock_payment_form.*'
|
|
||||||
```
|
|
||||||
|
|
||||||
Perhaps I'm thinking of a file that was added on an abandoned feature branch.
|
|
||||||
`--all` will help turn up that in the results as well.
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# List All Git Aliases From gitconfig
|
|
||||||
|
|
||||||
Running the `git config --list` command will show all of the configuration
|
|
||||||
settings you have for `git` relative to your current location. Though most of
|
|
||||||
these setting probably live in `~/.gitconfig`, you may also have some locally
|
|
||||||
specified ones in `.git/config`. This will grab them all including any `alias`
|
|
||||||
entries.
|
|
||||||
|
|
||||||
We can narrow things down to just `alias` entries using the `--get-regexp` flag.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ git config --get-regexp '^alias\.'
|
|
||||||
|
|
||||||
alias.ap add --patch
|
|
||||||
alias.authors shortlog -s -n -e
|
|
||||||
alias.co checkout
|
|
||||||
alias.st status
|
|
||||||
alias.put push origin HEAD
|
|
||||||
alias.fixup commit --fixup
|
|
||||||
alias.squash commit --squash
|
|
||||||
alias.doff reset HEAD^
|
|
||||||
alias.add-untracked !git status --porcelain | awk '/\?\?/{ print $2 }' | xargs git add
|
|
||||||
alias.reset-authors commit --amend --reset-author -CHEAD
|
|
||||||
```
|
|
||||||
|
|
||||||
I use `git doff` all the time on feature branches to "pop" the latest commmit
|
|
||||||
onto the working copy. I was trying to remember exactly what the `git doff`
|
|
||||||
command is and this was an easy way to check.
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# List And Count All Posts In TIL Repo
|
|
||||||
|
|
||||||
I want to be able to reliably list and count all posts in [my TIL
|
|
||||||
repo](https://github.com/jbranchaud/til). I do this to check that the count in
|
|
||||||
the README is accurate and in [the workflow
|
|
||||||
script](https://github.com/jbranchaud/jbranchaud/blob/71cba39dffb2bff68bf16d8895e435065e400250/scripts/update_tils.py#L101)
|
|
||||||
that powers [my GitHub Profile
|
|
||||||
README](https://github.com/jbranchaud/jbranchaud). In the past, I've used
|
|
||||||
pattern matching on the listing of all TILs in the
|
|
||||||
[README.md](https://github.com/jbranchaud/til/blob/master/README.md). That is
|
|
||||||
error prone and has required me to use two different markdown list styles.
|
|
||||||
|
|
||||||
A better approach is to ask `git` how many posts it currently has under version
|
|
||||||
control. I use a consistent directory structure where each TIL post is a
|
|
||||||
markdown file that is nested within a single category directory.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git ls-files -- */*.md
|
|
||||||
ack/ack-bar.md
|
|
||||||
ack/case-insensitive-search.md
|
|
||||||
ack/list-available-file-types.md
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Using `git ls-files` has the added benefit of only listing files that are
|
|
||||||
currently checked in to the project. So if I run this locally, it won't pick up
|
|
||||||
a draft post that hasn't been committed yet.
|
|
||||||
|
|
||||||
I can then pipe this to `wc -l` (count of all lines) to produce the count:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git ls-files -- */*.md | wc -l | xargs
|
|
||||||
1850
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: the empty `xargs` is a trick to trim the whitespace padding that `wc`
|
|
||||||
introduces.
|
|
||||||
|
|
||||||
See `man git-ls-files` for more details.
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
# Mark A Release With An Annotated Tag
|
|
||||||
|
|
||||||
There are two kinds of tags in Git -- lightweight tags and annotated tags.
|
|
||||||
|
|
||||||
The [`git-tag` docs](https://git-scm.com/docs/git-tag) explain the distinction:
|
|
||||||
|
|
||||||
> Annotated tags are meant for release while lightweight tags are meant for
|
|
||||||
> private or temporary object labels.
|
|
||||||
|
|
||||||
When an annotated tag is created, a _tag object_ is created which has a creation
|
|
||||||
timestamp, a "tagger" (who created it), a message, and potentially a signature
|
|
||||||
if GPG commit signing is configured.
|
|
||||||
|
|
||||||
I can create an annotated tag for the `HEAD` commit like so:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git tag -a v0.1.0 -m "Release v0.1.0"
|
|
||||||
```
|
|
||||||
|
|
||||||
I can then inspect what was created in a number of ways using `git tag --list`,
|
|
||||||
`git show`, `git cat-file`, and `git log --show-signature`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git tag --list
|
|
||||||
v0.1.0
|
|
||||||
|
|
||||||
❯ git show --no-patch v0.1.0
|
|
||||||
tag v0.1.0
|
|
||||||
Tagger: jbranchaud <jbranchaud@gmail.com>
|
|
||||||
Date: Sun, 2 Aug 2026 13:57:37 -0500
|
|
||||||
|
|
||||||
Release v0.1.0
|
|
||||||
|
|
||||||
commit 8a533ecfda526ebd1a4695639830f5620dd8572d (HEAD -> main, tag: v0.1.0, origin/main, origin/HEAD)
|
|
||||||
Author: jbranchaud <jbranchaud@gmail.com>
|
|
||||||
Date: Sun, 2 Aug 2026 12:51:41 -0500
|
|
||||||
|
|
||||||
Add changelog with v0.1.0 release changes documented
|
|
||||||
|
|
||||||
❯ git cat-file -t v0.1.0
|
|
||||||
tag
|
|
||||||
|
|
||||||
❯ git cat-file -p v0.1.0
|
|
||||||
object 8a533ecfda526ebd1a4695639830f5620dd8572d
|
|
||||||
type commit
|
|
||||||
tag v0.1.0
|
|
||||||
tagger jbranchaud <jbranchaud@gmail.com> 1785697057 -0500
|
|
||||||
|
|
||||||
Release v0.1.0
|
|
||||||
|
|
||||||
❯ git log --show-signature
|
|
||||||
commit 8a533ecfda526ebd1a4695639830f5620dd8572d (HEAD -> main, tag: v0.1.0, origin/main, origin/HEAD)
|
|
||||||
gpg: Signature made Sun Aug 2 13:57:09 2026 CDT
|
|
||||||
gpg: using RSA key B2570A9DA3E2A537781501B11A8656918A8D016B
|
|
||||||
gpg: Good signature from "jbranchaud <jbranchaud@gmail.com>" [ultimate]
|
|
||||||
Author: jbranchaud <jbranchaud@gmail.com>
|
|
||||||
Date: Sun, 2 Aug 2026 12:51:41 -0500
|
|
||||||
|
|
||||||
Add changelog with v0.1.0 release changes documented
|
|
||||||
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
This tag will be included in a push when I run either of the following:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git push origin main
|
|
||||||
❯ git push origin v0.1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
This tag, which is now tied to a _release_, can be seen at [_Releases /
|
|
||||||
v0.1.0_](https://github.com/jbranchaud/py-vmt/releases/tag/v0.1.0) on GitHub.
|
|
||||||
|
|
||||||
See `man git-tag` for more details.
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Programmatically Grab SHA For Head Commit
|
|
||||||
|
|
||||||
When I use `gh browse path/to/some-file.txt`, it opens the browser to that file
|
|
||||||
in GitHub. However, it targets the default branch (`main`) by default which is
|
|
||||||
not very useful as a permalink because what that file looks like on `main` is
|
|
||||||
liable to change.
|
|
||||||
|
|
||||||
There is a `--commit` flag you can use to have it instead open to that file at a
|
|
||||||
specific commit SHA.
|
|
||||||
|
|
||||||
So what SHA do I pass as an argument to that flag?
|
|
||||||
|
|
||||||
Often what I would like to grab is a reference to the current version of the
|
|
||||||
file which is whatever it looks like for the `HEAD` commit. But `HEAD` is
|
|
||||||
another moving target reference. The `git rev-parse` command can translate
|
|
||||||
`HEAD` into a specific SHA though.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git rev-parse --short HEAD
|
|
||||||
3402428
|
|
||||||
|
|
||||||
❯ git rev-parse HEAD
|
|
||||||
3402428aadc02cfdc9825c8feb593443e72f50cd
|
|
||||||
```
|
|
||||||
|
|
||||||
Either of those will work. I can use a bash command substitution then to tie it
|
|
||||||
all together into a single command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ gh browse path/to/some-file.txt --commit=$(git rev-parse --short HEAD)
|
|
||||||
```
|
|
||||||
|
|
||||||
See `man git-rev-parse` for more details.
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
While preparing some stats for a recent blog post on [A Decade of
|
While preparing some stats for a recent blog post on [A Decade of
|
||||||
TILs](https://www.visualmode.dev/a-decade-of-tils), I ran into an issue
|
TILs](https://www.visualmode.dev/a-decade-of-tils), I ran into an issue
|
||||||
referencing chunks of time further back than 2020.
|
referencing chuncks of time further back than 2020.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
❯ git diff --diff-filter=A --name-only HEAD@{2016-02-06}..HEAD@{2017-02-06} -- "*.md"
|
❯ git diff --diff-filter=A --name-only HEAD@{2016-02-06}..HEAD@{2017-02-06} -- "*.md"
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# Restore File From One Branch To The Current
|
|
||||||
|
|
||||||
On one feature branch I have created some files and made changes to some
|
|
||||||
existing files as part of spiking a feature. Now I'm on a different branch
|
|
||||||
taking another shot at it. I want changes from one or two of the files. In the
|
|
||||||
past I've used `git-checkout` for this task. However, I believe this is one of
|
|
||||||
the use cases they had in mind when they added `git-restore`.
|
|
||||||
|
|
||||||
What I want to do is _restore_ the state of a file as it appears on some source
|
|
||||||
branch to my current branch. Here is what that looks like:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ git restore --source=some-feature-branch app/models/contact.rb
|
|
||||||
```
|
|
||||||
|
|
||||||
Now when I check `git status` I'll see the state of that file on the
|
|
||||||
`some-feature-branch` branch overlayed on my current working copy. If the file
|
|
||||||
doesn't exist, it will be created.
|
|
||||||
|
|
||||||
See `man git-restore` for more details.
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
# Set Up GPG Signing Key
|
|
||||||
|
|
||||||
I wanted to have that "Verified" icon start showing up next to my commits in
|
|
||||||
GitHub. To do that, I need to generate a GPG key, configure the secret key in
|
|
||||||
GitHub, and then configure the public signing key with my git config.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# generate a gpg key
|
|
||||||
$ gpg --full-generate-key
|
|
||||||
|
|
||||||
# Pick the following options when prompted
|
|
||||||
# - Choose "RSA and RSA" (Options 1)
|
|
||||||
# - Max out key size at 4096
|
|
||||||
# - Choose expiration date (e.g. 0 for no expiration)
|
|
||||||
# - Enter "Real name" and "Email"
|
|
||||||
(I matched those to what is in my global git config)
|
|
||||||
# - Set passphrase (I had 1password generate a 4-word passphrase)
|
|
||||||
```
|
|
||||||
|
|
||||||
It may take a few seconds to create.
|
|
||||||
|
|
||||||
I can see it was created by listing my GPG keys.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gpg --list-secret-keys --keyid-format=long
|
|
||||||
[keyboxd]
|
|
||||||
---------
|
|
||||||
sec rsa4096/1A8656918A8D016B 2025-10-19 [SC]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
I'll need the `1A8656918A8D016B` portion of that response for the next command
|
|
||||||
and it is what I set as my public signing key in my git config.
|
|
||||||
|
|
||||||
First, though, I add the full key block to my GitHub profile which I can copy
|
|
||||||
like so:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gpg --armor --export 1A8656918A8D016B | pbcopy
|
|
||||||
```
|
|
||||||
|
|
||||||
And then I paste that as a new GPG Key on GitHub under _Settings_ -> _SSH and
|
|
||||||
GPG Keys_.
|
|
||||||
|
|
||||||
Last, I update my global git config with the signing key and the preference to
|
|
||||||
sign commits:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git config --global user.signingkey 1A8656918A8D016B
|
|
||||||
git config --global commit.gpgsign true
|
|
||||||
```
|
|
||||||
|
|
||||||
Without `commit.gpgsign`, I would have to specify the `-S` flag every time I
|
|
||||||
want to create a signed commit.
|
|
||||||
|
|
||||||
[source](https://git-scm.com/book/ms/v2/Git-Tools-Signing-Your-Work)
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# Show Summary Stats For Current Branch
|
|
||||||
|
|
||||||
When I push a branch up to GitHub as a PR, there is a part of the UI that shows
|
|
||||||
you how many lines you've added and removed for this branch. It bases that off
|
|
||||||
the target branch which is typically your `main` branch.
|
|
||||||
|
|
||||||
The `git diff` command can provide those same stats right in the terminal. The
|
|
||||||
key is to specify the `--shortstat` flag which tells `git` to exclude other diff
|
|
||||||
output and only show:
|
|
||||||
|
|
||||||
- Number of files changed
|
|
||||||
- Number of insertions
|
|
||||||
- Number of deletions
|
|
||||||
|
|
||||||
Here is the summary stats for a branch I'm working on:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git diff --shortstat main
|
|
||||||
8 files changed, 773 insertions(+), 25 deletions(-)
|
|
||||||
```
|
|
||||||
|
|
||||||
We have to be on our feature branch and then we point to the branch (or whatever
|
|
||||||
ref) we want to diff against. Since I want to know how my feature branch
|
|
||||||
compares to `main`, I specify that.
|
|
||||||
|
|
||||||
See `man git-diff` for more details.
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Skip Git Hooks As Needed
|
|
||||||
|
|
||||||
Projects have Git hooks configured for all sorts of reasons. Most common are
|
|
||||||
`pre-commit` hooks which verify certain aspects of the contents of a commit.
|
|
||||||
A `pre-commit` hook could check that the tests all pass, that the changes don't
|
|
||||||
include any debugging statements, and so forth. There are all kinds of hooks
|
|
||||||
though, like `pre-rebase` and `post-checkout`.
|
|
||||||
|
|
||||||
These hooks can sometimes get in the way and we may need to skip or disable them
|
|
||||||
on a one-off basis.
|
|
||||||
|
|
||||||
Several Git commands offer a `--no-verify` flag which can skip running the hook
|
|
||||||
associated with that command.
|
|
||||||
|
|
||||||
- `git commit --no-verify` (skips `pre-commit` and `commit-msg` hooks)
|
|
||||||
- `git push --no-verify` (skips `pre-push` hook)
|
|
||||||
- `git merge --no-verify` (skips `pre-merge-commit` hook)
|
|
||||||
- `git am --no-verify` (skips `applypatch-msg` and `pre-applypatch` hooks)
|
|
||||||
|
|
||||||
If you look in the `.git/hooks` directory, there are several other hooks not
|
|
||||||
covered by the above. So, what if I am doing an action like `git checkout` and I
|
|
||||||
want to skip the `post-checkout` hook?
|
|
||||||
|
|
||||||
I can override the `hooksPath` config for that one command with the `-c` flag.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ git -c core.hooksPath=/dev/null checkout ...
|
|
||||||
```
|
|
||||||
|
|
||||||
By setting it to `/dev/null`, it will find *no* hooks available, so none will be
|
|
||||||
executed for this command.
|
|
||||||
|
|
||||||
See `man git-config` for more details on `core.hooksPath`.
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Summarize Amount Of Change For Specific Commit
|
|
||||||
|
|
||||||
To get a quick headline summary of the amount of change that happened in a
|
|
||||||
commit, I can use the `--shortstat` flag. This will sum up file changed, lines
|
|
||||||
added, and lines removed. This can be combined with an _empty_ format flag to
|
|
||||||
suppress all other output.
|
|
||||||
|
|
||||||
I can run this for the latest commit on the current branch by referencing
|
|
||||||
`HEAD`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git show --shortstat --format= HEAD
|
|
||||||
3 files changed, 1046 insertions(+), 462 deletions(-)
|
|
||||||
```
|
|
||||||
|
|
||||||
Or I can point at some other commit via its SHA:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git show --shortstat --format= 8cbfcdd7
|
|
||||||
1 file changed, 238 insertions(+)
|
|
||||||
```
|
|
||||||
|
|
||||||
I can even summarize the amount of change for the entire feature branch I'm
|
|
||||||
working on by referencing a range between `main` and the `HEAD` commit.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ git diff --shortstat main...HEAD
|
|
||||||
36 files changed, 1125 insertions(+), 134 deletions(-)
|
|
||||||
```
|
|
||||||
|
|
||||||
See `man git-show` and `man git-diff` for more details.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Undo Latest Changes Committed To Specific File
|
|
||||||
|
|
||||||
I'm reviewing the changes I've made in a PR before I request a review from my
|
|
||||||
team. There are a scattering of changes in one file that I've changed my mind
|
|
||||||
on. Everything else looks good though. So, I need to undo the changes in that
|
|
||||||
file before proceeding.
|
|
||||||
|
|
||||||
Manually undoing them is going to be clunky. There is a way to do it with `git
|
|
||||||
checkout`, but that is one of the ways in which `git-checkout` was overloaded
|
|
||||||
leading to the release of `git-restore`.
|
|
||||||
|
|
||||||
Let's use `git-restore` instead. By specifying a `--source`, I can tell `git`
|
|
||||||
what _ref_ in the commit history that file should be restored to. I'm on a
|
|
||||||
short-lived feature branch, so pointing to `main` is good enough.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ git restore --source=main app/models/customer.rb
|
|
||||||
```
|
|
||||||
|
|
||||||
If I've changed a file at multiple points on this feature branch and I don't
|
|
||||||
want to undo all of them, then pointing to `main` is no longer going to work.
|
|
||||||
Instead, I can point to the commit right before the current one (`HEAD`) that
|
|
||||||
I'm trying to undo.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ git restore --source=HEAD~ app/models/customer.rb
|
|
||||||
```
|
|
||||||
|
|
||||||
This really isn't much different than the `git-checkout` version, but I still
|
|
||||||
find it to be a little clearer.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ git checkout HEAD~ -- app/models/customer.rb
|
|
||||||
```
|
|
||||||
|
|
||||||
See `man git-restore` for more details.
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
# Run Scheduled Action To Commit Regular Updates
|
|
||||||
|
|
||||||
The quintessential example of what GitHub Actions are used for is running CI
|
|
||||||
tasks like the test suite, type checker, linter, etc. Each CI step runs to
|
|
||||||
completion and either passes or fails and you see the results in the GitHub PR
|
|
||||||
interface. That's a great use case, but far from the only one. GitHub Actions
|
|
||||||
are a much more general-purpose execution environment that can be used for much
|
|
||||||
more.
|
|
||||||
|
|
||||||
Here is a recent example that expanded my mind a bit on what is possible with
|
|
||||||
GitHub actions. Imagine a GitHub Action that is scheduled to run once a day, it
|
|
||||||
executes a script that might make changes to the repo itself (e.g. the
|
|
||||||
`README.md`), and then commits those changes (self-updating the repo).
|
|
||||||
|
|
||||||
Here is a minimal version of a workflow that does that:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '17 11 * * *' # daily at 11:17 UTC (06:17 CT)
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4 # get the repo + push credentials
|
|
||||||
|
|
||||||
- run: ./bin/regenerate_readme.sh # apply updates to README
|
|
||||||
|
|
||||||
- run: |
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git add -A README.md
|
|
||||||
git diff --staged --quiet || {
|
|
||||||
git commit -m "chore: regenerate README with latest updates"
|
|
||||||
git push
|
|
||||||
} # commit updates to README if there are any, otherwise no-op
|
|
||||||
```
|
|
||||||
|
|
||||||
Once a day at 11:17 UTC, GitHub Actions will run this workflow which is made up
|
|
||||||
of a single job with permissions to write to the repo.
|
|
||||||
|
|
||||||
- First, it checks out the repo in the job container which includes push
|
|
||||||
credentials.
|
|
||||||
- Then it runs a script that might update the README (e.g. maybe based on other
|
|
||||||
things that have since been committed to the repo).
|
|
||||||
- Last, it attempts to stage any changes the script made to the README. If there
|
|
||||||
are any, then it will commit them with that generic commit message. Finally it
|
|
||||||
will push that commit to the main branch.
|
|
||||||
|
|
||||||
If this all sounds a bit untethered from a real-world example, then take a look
|
|
||||||
at how I use this exact pattern to [apply daily updates to my GitHub Profile
|
|
||||||
README](https://github.com/jbranchaud/jbranchaud/blob/main/.github/workflows/update-tils.yml)
|
|
||||||
based on the latest [TILs](https://github.com/jbranchaud/til) I have written.
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Set Repository Secret From CLI
|
|
||||||
|
|
||||||
I set up a GitHub Action that will run daily and potentially push data up to a
|
|
||||||
3rd-party API. To be able to post to that API, the action must include a secret
|
|
||||||
as the bearer token in the requests. I need to securely include that secret in
|
|
||||||
the GitHub Actions environment for this repo.
|
|
||||||
|
|
||||||
I can do that from the CLI with `gh` like so:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ gh secret set TIL_SYNC_TOKEN
|
|
||||||
? Paste your secret: ****************************************************************
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice that it prompts me for the secret and stars out what I paste in. That way
|
|
||||||
the secret doesn't end up in my bash history and isn't visible on my screen.
|
|
||||||
|
|
||||||
After I've run this, I can see that the secret is set by opening up the repo in
|
|
||||||
the GitHub web UI, clicking on _Settings_ > _Secrets and Variables_ > _Actions_.
|
|
||||||
I should see `TIL_SYNC_TOKEN` listed under the _Repository Secrets_ section.
|
|
||||||
|
|
||||||
Here is an excerpt from my workflow action sync script where that secret is
|
|
||||||
referenced -- notice the `${{ secrets.TIL_SYNC_TOKEN }}`.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- name: Sync posts
|
|
||||||
env:
|
|
||||||
TIL_SYNC_URL: ${{ vars.TIL_SYNC_URL }}
|
|
||||||
TIL_SYNC_TOKEN: ${{ secrets.TIL_SYNC_TOKEN }}
|
|
||||||
run: ruby script/til_sync/til_sync.rb --repo til ${{ inputs.all && '--all' || '--days 3' }}
|
|
||||||
```
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Access Your GitHub Profile Photo
|
|
||||||
|
|
||||||
Let's say I have my [GitHub profile](https://github.com/jbranchaud) pulled up in
|
|
||||||
the browser.
|
|
||||||
|
|
||||||
```
|
|
||||||
https://github.com/jbranchaud
|
|
||||||
```
|
|
||||||
|
|
||||||
If I then add `.png` to the end of that in the URL bar:
|
|
||||||
|
|
||||||
```
|
|
||||||
https://github.com/jbranchaud.png
|
|
||||||
```
|
|
||||||
|
|
||||||
I'll be redirected to the URL where the full image file lives. In my case:
|
|
||||||
|
|
||||||
```
|
|
||||||
https://avatars.githubusercontent.com/u/694063?v=4
|
|
||||||
```
|
|
||||||
|
|
||||||
You can pull up yours `https://github.com/<username>.png` to access your profile
|
|
||||||
image.
|
|
||||||
|
|
||||||
[source](https://dev.to/10xlearner/how-to-get-the-profile-picture-of-a-github-account-1d82)
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# Create A Private Repo From The CLI
|
|
||||||
|
|
||||||
The vast majority of the GitHub repos that I've created over my career have been
|
|
||||||
done from the web UI. It was only recently that I found out that [I can create a
|
|
||||||
new repo from the CLI with `gh`](create-and-push-to-new-repo-from-cli.md).
|
|
||||||
|
|
||||||
A repo can be created for the current directory (where a local git repo already
|
|
||||||
exists) using the `gh repo create` command. I'm wanting this to be a private
|
|
||||||
repo so I can include the `--private` flag instead of the `--public` flag.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ gh repo create marathon-training --private --source=. --remote=origin --push
|
|
||||||
✓ Created repository jbranchaud/marathon-training on github.com
|
|
||||||
https://github.com/jbranchaud/marathon-training
|
|
||||||
✓ Added remote https://github.com/jbranchaud/marathon-training.git
|
|
||||||
Enumerating objects: 125, done.
|
|
||||||
Counting objects: 100% (125/125), done.
|
|
||||||
Delta compression using up to 16 threads
|
|
||||||
Compressing objects: 100% (114/114), done.
|
|
||||||
Writing objects: 100% (125/125), 56.69 KiB | 14.17 MiB/s, done.
|
|
||||||
Total 125 (delta 52), reused 0 (delta 0), pack-reused 0 (from 0)
|
|
||||||
remote: Resolving deltas: 100% (52/52), done.
|
|
||||||
To https://github.com/jbranchaud/marathon-training.git
|
|
||||||
* [new branch] HEAD -> main
|
|
||||||
branch 'main' set up to track 'origin/main' by rebasing.
|
|
||||||
✓ Pushed commits to https://github.com/jbranchaud/marathon-training.git
|
|
||||||
```
|
|
||||||
|
|
||||||
Since I am running this command from the root directory of the git-backed
|
|
||||||
project, I specify the `--source` as `.` (mean _here_, the current directory).
|
|
||||||
The remaining flags tell it what the remote should be set up as and that I want
|
|
||||||
to push this local repo up to the GitHub remote once it is created.
|
|
||||||
|
|
||||||
See `gh repo create --help` for more details.
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
# Create And Push To New Repo From CLI
|
|
||||||
|
|
||||||
I figured there must be a good way to create a new repo in GitHub using the `gh`
|
|
||||||
CLI based on a local git repo. I spend so much time in existing git projects
|
|
||||||
that already have GitHub repos that I haven't had the chance to figure this out.
|
|
||||||
Until now.
|
|
||||||
|
|
||||||
I just finished a first pass on a fresh project for [a GitHub profile
|
|
||||||
README](https://github.com/jbranchaud/jbranchaud). It was time to put it up on
|
|
||||||
GitHub and see if worked. Instead of going through the GitHub web UI to create
|
|
||||||
this new repo, I found the `gh repo create` subcommand. I then asked Claude what
|
|
||||||
flags I needed for my use case. The recommendation was as follows:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ gh repo create --public --source=. --remote=origin --push
|
|
||||||
✓ Created repository jbranchaud/jbranchaud on github.com
|
|
||||||
https://github.com/jbranchaud/jbranchaud
|
|
||||||
✓ Added remote https://github.com/jbranchaud/jbranchaud.git
|
|
||||||
Enumerating objects: 11, done.
|
|
||||||
Counting objects: 100% (11/11), done.
|
|
||||||
Delta compression using up to 16 threads
|
|
||||||
Compressing objects: 100% (6/6), done.
|
|
||||||
Writing objects: 100% (11/11), 4.21 KiB | 4.21 MiB/s, done.
|
|
||||||
Total 11 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
|
|
||||||
To https://github.com/jbranchaud/jbranchaud.git
|
|
||||||
* [new branch] HEAD -> main
|
|
||||||
branch 'main' set up to track 'origin/main' by rebasing.
|
|
||||||
✓ Pushed commits to https://github.com/jbranchaud/jbranchaud.git
|
|
||||||
```
|
|
||||||
|
|
||||||
This created the repo on GitHub for my authenticated profile (`jbranchaud`)
|
|
||||||
using the name of the current directory (`jbranchaud`). It then setup the
|
|
||||||
`origin` remote to point to that repo on GitHub. It then pushed the current
|
|
||||||
state of `main` up to the remote.
|
|
||||||
|
|
||||||
- `--public` configures the created repo to be a public, rather than private,
|
|
||||||
one.
|
|
||||||
- `--source=.` tells the command to run for the current directory (I ran this
|
|
||||||
from the root of this new project)
|
|
||||||
- `--remote=origin` tells it what the remote should be called, though `origin`
|
|
||||||
is the default, so this wasn't strictly necessary
|
|
||||||
- `--push` tells the command to push to the remote once it is created and
|
|
||||||
configured
|
|
||||||
|
|
||||||
See `gh repo create --help` for more details and examples.
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# List PRs Awaiting Your Review
|
|
||||||
|
|
||||||
If you work on a software team or steward an open-source project, then there are
|
|
||||||
likely some open PRs that you've been tagged to review. I am usually able to
|
|
||||||
catch most review requests as they come up either from the GitHub email
|
|
||||||
notifications or by keeping an eye on the PRs tab of active projects. Sometimes
|
|
||||||
I get consumed by a task and something slips through the cracks.
|
|
||||||
|
|
||||||
There are a couple other ways to quickly check if anything is waiting on my
|
|
||||||
review.
|
|
||||||
|
|
||||||
From the web UI I can visit the following URL which will show all PRs across all
|
|
||||||
projects where my review has been requested:
|
|
||||||
|
|
||||||
[https://github.com/pulls/review-requested](https://github.com/pulls/review-requested)
|
|
||||||
|
|
||||||
The GitHub CLI (`gh`) can do the same and I can do it right from the terminal
|
|
||||||
instead of navigating several clicks within GitHub's web UI.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gh search prs --review-requested=@me --state=open
|
|
||||||
```
|
|
||||||
|
|
||||||
That too will list PRs across all projects that are open and awaiting my review.
|
|
||||||
|
|
||||||
If that one ends up being a little too noisy, you can also use `gh` to _list_
|
|
||||||
just PRs for the current project:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gh pr list --search "review-requested:@me"
|
|
||||||
```
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Open A PR To An Unforked Repo
|
|
||||||
|
|
||||||
Sometimes I will clone a repo to explore the source code or to look into a
|
|
||||||
potential bug. If my curiosity takes me far enough to make some changes, then I
|
|
||||||
jump through the hoops of creating a fork, reconfiguring branches, pushing to my
|
|
||||||
fork, and then opening the branch as a PR against the original repo.
|
|
||||||
|
|
||||||
The `gh` CLI allows me to avoid all that hoop-jumping. Directly from the cloned
|
|
||||||
repo I can use `gh` to create a new PR. It will prompt me to creat a fork. If I
|
|
||||||
accept, it will seamlessly create it and then open a PR from my fork to the
|
|
||||||
original.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gh pr create
|
|
||||||
```
|
|
||||||
|
|
||||||
This allows me to create the PR with a few prompts from the CLI. If you prefer,
|
|
||||||
you can include the `--web` flag to open the PR creation screen directly in the
|
|
||||||
browser.
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# Open File To Specific Line In Browser
|
|
||||||
|
|
||||||
Often one of the best ways to point a teammate to a line of code is to share a
|
|
||||||
GitHub link to a specific file and line number. Sometimes even a specific
|
|
||||||
commit.
|
|
||||||
|
|
||||||
For the longest time I would manually open GitHub, navigate to that file, and so
|
|
||||||
forth. The `gh` CLI supports this with the `browse` subcommand and it takes way
|
|
||||||
less time if you already have the repo in your local filesystem.
|
|
||||||
|
|
||||||
For instance, if I want to point you to line 11 of the `zshrc.local` file in my
|
|
||||||
`dotfiles` repo, I can run the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gh browse zshrc.local:11
|
|
||||||
```
|
|
||||||
|
|
||||||
That would open a browser tab to
|
|
||||||
[https://github.com/jbranchaud/dotfiles/blob/main/zshrc.local?plain=1#L11](https://github.com/jbranchaud/dotfiles/blob/main/zshrc.local?plain=1#L11).
|
|
||||||
|
|
||||||
If I wanted a range of lines, I could change it from `11` to, say, `11-27`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gh browse zshrc.local:11-27
|
|
||||||
```
|
|
||||||
|
|
||||||
And I would see this in the browser --
|
|
||||||
[https://github.com/jbranchaud/dotfiles/blob/main/zshrc.local?plain=1#L11-L27](https://github.com/jbranchaud/dotfiles/blob/main/zshrc.local?plain=1#L11-L27).
|
|
||||||
|
|
||||||
Both of these URLs are pointing to the `main` branch. If I instead want to
|
|
||||||
reference a specific commit, I can use the `--commit` flag.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gh browse zshrc.local:11-27 --commit=f2f9e78d4fc784643f725c88f7a5a7a077e7f261
|
|
||||||
```
|
|
||||||
|
|
||||||
I grabbed that from the latest commit in `git log`. That opens to
|
|
||||||
[https://github.com/jbranchaud/dotfiles/blob/f2f9e78d4fc784643f725c88f7a5a7a077e7f261/zshrc.local?plain=1#L11-L27](https://github.com/jbranchaud/dotfiles/blob/f2f9e78d4fc784643f725c88f7a5a7a077e7f261/zshrc.local?plain=1#L11-L27).
|
|
||||||
|
|
||||||
Another way of doing that would be to use `git rev-parse HEAD`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gh browse zshrc.local:11-27 --commit=$(git rev-parse HEAD)
|
|
||||||
```
|
|
||||||
|
|
||||||
See `gh browse --help` for more details.
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
# Process JSON Output From gh With jq
|
|
||||||
|
|
||||||
The `gh` (GitHub) CLI is useful for accessing data about your profile and
|
|
||||||
projects from the terminal. With the `--json` flag, we can access the data in a
|
|
||||||
structured way which is useful for scripting.
|
|
||||||
|
|
||||||
Here is an example of pulling a list of all my repositories, limiting each
|
|
||||||
entity to just the `nameWithOwner` and `description`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ gh repo list --limit 1000 --json nameWithOwner,description
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"description": "My personal site -- joshbranchaud.com",
|
|
||||||
"nameWithOwner": "jbranchaud/personal-site"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Private repo for the NOTES.md of my TIL repo",
|
|
||||||
"nameWithOwner": "jbranchaud/til-notes-private"
|
|
||||||
},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
If I'm using the `--json` flag, then I can add in the `--jq` flag to apply a
|
|
||||||
`jq` query for additional processing of the output.
|
|
||||||
|
|
||||||
Here I convert it to a series of tuples:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ gh repo list --limit 1000 --json nameWithOwner,description \
|
|
||||||
--jq '.[] | [.nameWithOwner, .description]'
|
|
||||||
[
|
|
||||||
"jbranchaud/personal-site",
|
|
||||||
"My personal site -- joshbranchaud.com"
|
|
||||||
]
|
|
||||||
[
|
|
||||||
"jbranchaud/til-notes-private",
|
|
||||||
"Private repo for the NOTES.md of my TIL repo"
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Then I can add one more pipe to that `jq` query to turn it into _tab-separated
|
|
||||||
values_ using
|
|
||||||
[`@tsv`](https://jqlang.org/manual/v1.5/#format-strings-and-escaping):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ gh repo list --limit 1000 --json nameWithOwner,description \
|
|
||||||
--jq '.[] | [.nameWithOwner, .description] | @tsv'
|
|
||||||
jbranchaud/personal-site My personal site -- joshbranchaud.com
|
|
||||||
jbranchaud/til-notes-private Private repo for the NOTES.md of my TIL repo
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
This is useful because I can then pipe it to another program, such as an `fzf`
|
|
||||||
command like [this repo selector that opens the selected one in the
|
|
||||||
browser](https://github.com/jbranchaud/dotfiles/commit/f964ca10c6c4db3475411c2991dc2f1dfd18c818).
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Rerun Failed Jobs For Current Branch
|
|
||||||
|
|
||||||
I have a branch that I've already opened a PR for. I've made more changes, run
|
|
||||||
the tests, and pushed up the latest to the remote. I know the tests should have
|
|
||||||
been green, but I'm seeing a flickering test fail in CI. I want to retrigger the
|
|
||||||
relevant failed jobs to see if I can get the flickers to pass.
|
|
||||||
|
|
||||||
First, I need to figure out the workflow ID with any failed jobs.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ gh run list --branch "$(git branch --show-current)" --status failure
|
|
||||||
STATUS TITLE WORKFLOW BRANCH EVENT ID ELAPSED AGE
|
|
||||||
X Better comp... Ruby on R... jbranchau... pull_request 38778306948 10m54s about 25 ...
|
|
||||||
```
|
|
||||||
|
|
||||||
This one-liner does that by referencing the current branch (via `git`) and then
|
|
||||||
asking `gh` to list failed workflows associated with that branch.
|
|
||||||
|
|
||||||
Grabbing the `ID` value, I can then ask `gh` to rerun failed jobs for that
|
|
||||||
workflow.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ gh run rerun 38778306948 --failed
|
|
||||||
✓ Requested rerun (failed jobs) of run 38778306948
|
|
||||||
```
|
|
||||||
|
|
||||||
Opening that PR up in the browser, I can see that the specific workflow has been
|
|
||||||
rerun and is currently _in progress_.
|
|
||||||
|
|
||||||
See `gh run list --help` and `gh run rerun --help` for more details.
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# Target Another Repo When Creating A PR
|
|
||||||
|
|
||||||
I have a [`dotfiles` repo](https://github.com/jbranchaud/dotfiles) that I forked
|
|
||||||
from [`dkarter/dotfiles`](https://github.com/dkarter/dotfiles). I'm adding a
|
|
||||||
bunch of my own customizations on a `main` branch while continually pulling in
|
|
||||||
and merging upstream changes.
|
|
||||||
|
|
||||||
The primary remote according to `gh` is `jbranchaud/dotfiles`. 98% of the time
|
|
||||||
that is what I want. However, I occasionally want to share some changes upstream
|
|
||||||
via a PR. Running `gh pr create` as is will create a PR against my fork. To
|
|
||||||
override this on a one-off basis, I can use the `--repo` flag.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gh pr create --repo dkarter/dotfiles
|
|
||||||
```
|
|
||||||
|
|
||||||
This will create a PR against `dkarter:master` from my branch (e.g.
|
|
||||||
[`jbranchaud:jb/fix-hardcoded-paths`](https://github.com/dkarter/dotfiles/pull/373)).
|
|
||||||
|
|
||||||
See `man gh-pr-create` for more details.
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
# Tell gh What The Default Repo Is
|
|
||||||
|
|
||||||
I recently forked [dkarter/dotfiles](https://github.com/dkarter/dotfiles) as a
|
|
||||||
way of bootstrapping a robust dotfile config for a new machine that I could
|
|
||||||
start making customizations to. I'm maintaining a `my-dotfiles` branch and keep
|
|
||||||
things in sync with the original upstream repo.
|
|
||||||
|
|
||||||
When trying to go to *my* fork of the repo
|
|
||||||
([jbranchaud/dotfiles](https://github.com/jbranchaud/dotfiles)) in the web with
|
|
||||||
the `gh` CLI tool, I ran into a weird issue. It was instead opening up to
|
|
||||||
`dkarter/dotfiles`.
|
|
||||||
|
|
||||||
`gh` was under the wrong impression which repo should be considered the default.
|
|
||||||
To clarify things for `gh`, there is a command to set the default repo.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gh repo set-default jbranchaud/dotfiles
|
|
||||||
✓ Set jbranchaud/dotfiles as the default repository for the current directory
|
|
||||||
```
|
|
||||||
|
|
||||||
Now when I run `gh repo view --web`, it opens the browser to my fork of the
|
|
||||||
dotfiles.
|
|
||||||
|
|
||||||
But where does this setting live?
|
|
||||||
|
|
||||||
Opening this repo's `.git/config` file I can see a section for the `origin`
|
|
||||||
remote that includes a new line for `gh-resolved`. This being set to `base`
|
|
||||||
tells `gh` that this remote is the one to treat as the default repo.
|
|
||||||
|
|
||||||
```
|
|
||||||
[remote "origin"]
|
|
||||||
url = git@github.com:jbranchaud/dotfiles.git
|
|
||||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
|
||||||
gh-resolved = base
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
See `gh repo set-default --help` for more details.
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# Check Ruby Version For Production App
|
|
||||||
|
|
||||||
While deploying a fresh Rails app to Heroku recently, I ran into an issue. The
|
|
||||||
`it` block argument wasn't working despite being on Ruby 4.0. Or so I thought.
|
|
||||||
|
|
||||||
Running the following command reported the Ruby version of that Heroku server
|
|
||||||
instance:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ heroku run -- ruby --version
|
|
||||||
Running ruby --version on ⬢ my-app... up, run.3090
|
|
||||||
ruby 3.3.9 (2025-07-24 revision f5c772fc7c) [x86_64-linux]
|
|
||||||
```
|
|
||||||
|
|
||||||
I was on `3.3.9` which must have been the fallback default at the time.
|
|
||||||
|
|
||||||
Though I had set the Ruby version in my `.ruby-version` file, I had neglected to
|
|
||||||
specify it in the `Gemfile` as well. Once I added it to the `Gemfile` and
|
|
||||||
redeployed, my Heroku server instance was running the expected version of Ruby.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ heroku run -- ruby --version
|
|
||||||
Running ruby --version on ⬢ my-app... up, run.5353
|
|
||||||
ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [x86_64-linux]
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: because [I have set `HEROKU_ORGANIZATION` and
|
|
||||||
`HEROKU_APP`](set-default-team-and-app-for-project.md) in my environment
|
|
||||||
(`.envrc`) for the local copy of the app, I don't need to specify those when
|
|
||||||
running the `heroku run` command above.
|
|
||||||
|
|
||||||
See `heroku run --help` for more details.
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# Specify Default Team And App For Project
|
|
||||||
|
|
||||||
Typically when you run commands with the Heroku CLI you'll need to specify the
|
|
||||||
name of the app on Heroku you're targeting with the `--app` flag. However, to
|
|
||||||
first see the names of the apps you may want to run `heroku apps` (or `heroku
|
|
||||||
list`). That will list the apps for your default team.
|
|
||||||
|
|
||||||
If you need to see apps for a different team (i.e. organization), you'll need to
|
|
||||||
specify that team either with the `--team` flag or by setting that as an
|
|
||||||
environment variable.
|
|
||||||
|
|
||||||
Here I do the latter in an `.envrc` file:
|
|
||||||
|
|
||||||
```
|
|
||||||
# Heroku
|
|
||||||
export HEROKU_ORGANIZATION=visualmode
|
|
||||||
```
|
|
||||||
|
|
||||||
Once that is set and the environment reloaded, running `heroku apps` will show
|
|
||||||
the apps specific to that team on Heroku.
|
|
||||||
|
|
||||||
Similarly, if you want to set a default app for your project so that you don't
|
|
||||||
have to always specify the `--app` flag, you can update your `.envrc`
|
|
||||||
accordingly.
|
|
||||||
|
|
||||||
```
|
|
||||||
# Heroku
|
|
||||||
export HEROKU_ORGANIZATION=visualmode
|
|
||||||
export HEROKU_APP=my-app
|
|
||||||
```
|
|
||||||
|
|
||||||
I had a hard time finding official documentation for this which is why I'm
|
|
||||||
writing this up here. I've manually verified this works with my own team and
|
|
||||||
app.
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Allow Number Input To Accept Decimal Values
|
|
||||||
|
|
||||||
Here is a number input element:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<input type="number" id="amount" required class="border" />
|
|
||||||
```
|
|
||||||
|
|
||||||
This renders an empty number input box with up and down arrows which will, by
|
|
||||||
default, increment or decrement the value by **1**.
|
|
||||||
|
|
||||||
Of course, I can manually edit the input typing in a value like `1.25`.
|
|
||||||
|
|
||||||
However, when I submit that via an HTML form, the submission will be prevented
|
|
||||||
and the browser will display a validation error.
|
|
||||||
|
|
||||||
> Please enter a valid value. The two nearest valid values are 1 and 2.
|
|
||||||
|
|
||||||
If I want to be able to input a decimal value like this, I need to change the
|
|
||||||
`step` value. It defaults to `1`, but I could change it to `2`, `10`, or in
|
|
||||||
this case to `0.01`.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<input type="number" step="0.01" id="amount" required class="border" />
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice now that as you click the up and down arrows, the value is incremented
|
|
||||||
and decremented by **0.01** at a time.
|
|
||||||
|
|
||||||
If I want to maintain the step value of `1` while allowing decimal values, I
|
|
||||||
can instead set the `step` value to be `any`.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<input type="number" step="any" id="amount" required class="border" />
|
|
||||||
```
|
|
||||||
|
|
||||||
See the [MDN docs on number
|
|
||||||
inputs](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/number)
|
|
||||||
for more details.
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Hide Overflowing Text For Google Sheets Column
|
|
||||||
|
|
||||||
I imported a big CSV into a new Google Sheets document. This included a
|
|
||||||
"Description" column with many of the descriptions varying between 50 and 80
|
|
||||||
characters. The bottom line is that the description column was flowing over the
|
|
||||||
top of the columns next to it. Instead of expanding the width of that column as
|
|
||||||
far as the largest description, I wanted to hide the _overflow_.
|
|
||||||
|
|
||||||
The way to do this in Google Sheets is to highlight the entire column by
|
|
||||||
clicking on the column grouping. Then under the _Format_ menu item is a
|
|
||||||
_Wrapping_ submenu. The _Clip_ option is what I was looking for because it clips
|
|
||||||
the text that gets shown at the edge of the column.
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
# Filter By Truthy Values With Boolean Function
|
|
||||||
|
|
||||||
The `Boolean` function (not to be confused with the `Boolean` constructor)
|
|
||||||
evaluates any given value to its [boolean
|
|
||||||
coercion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean#boolean_coercion).
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
> Boolean(0)
|
|
||||||
false
|
|
||||||
> Boolean(1)
|
|
||||||
true
|
|
||||||
> Boolean(null)
|
|
||||||
false
|
|
||||||
> Boolean([])
|
|
||||||
true
|
|
||||||
```
|
|
||||||
|
|
||||||
One way that this can be put to use is as a _boolean identity function_ for
|
|
||||||
passing to other functions like `filter`.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
> [0, 1, "", [], "four", null, "six", undefined, 7].filter(Boolean)
|
|
||||||
[ 1, [], 'four', 'six', 7 ]
|
|
||||||
```
|
|
||||||
|
|
||||||
This filters out all the non-truthy values from a list.
|
|
||||||
|
|
||||||
Let's say I'm building a list of nav items that will be rendered to the UI for a
|
|
||||||
specific user. Based on permissions or feature flags, certain nav items may not
|
|
||||||
be available. Those "empty" entries can be filtered out in this way.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
nav_items = [
|
|
||||||
{ label: "Home", href: "/" },
|
|
||||||
isSystemAdmin && { label: "System", "/system" },
|
|
||||||
featureEnabled(user, "api") && { label: "API", "/api" },
|
|
||||||
].filter(Boolean)
|
|
||||||
```
|
|
||||||
|
|
||||||
If any of those conditional nav items evaluate to `false`, then they will be
|
|
||||||
filtered out. The resulting `nav_items` array is a clean list of actual nav
|
|
||||||
items I want to render.
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
# Format A List Of Items By Locale
|
|
||||||
|
|
||||||
The `Intl` module includes a [`ListFormat`
|
|
||||||
object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat)
|
|
||||||
which can be used to format a list of items in a consistent way across locales.
|
|
||||||
|
|
||||||
I've reinvented the wheel of writing a helper function numerous times across
|
|
||||||
projects for formatting a list of items that accounts for formatting based on
|
|
||||||
how many items there are. This built-in function handles that with the added
|
|
||||||
benefit of working across locales.
|
|
||||||
|
|
||||||
Here are lists of three, two, and one items formatted in the `long` styles for
|
|
||||||
US english.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
> const formatter = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' });
|
|
||||||
undefined
|
|
||||||
|
|
||||||
> formatter.format(['Alice', 'Bob', 'Carla'])
|
|
||||||
'Alice, Bob, and Carla'
|
|
||||||
|
|
||||||
> formatter.format(['Coffee', 'Tea'])
|
|
||||||
'Coffee and Tea'
|
|
||||||
|
|
||||||
> formatter.format(['Taco'])
|
|
||||||
'Taco'
|
|
||||||
```
|
|
||||||
|
|
||||||
The difference between `long` and `short` style for a `conjunction` is _and_
|
|
||||||
versus _&_. In addition to the type`conjunction`, you could also use
|
|
||||||
`disjunction` which will do an _or_ instead of an _and_. I'm not sure what
|
|
||||||
you'd use the `unit` type for.
|
|
||||||
|
|
||||||
You could use another locale, such as French, as well:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
> const formatter = new Intl.ListFormat('fr', { style: 'long', type: 'conjunction' });
|
|
||||||
undefined
|
|
||||||
|
|
||||||
> formatter.format(['café', 'thé'])
|
|
||||||
'café et thé'
|
|
||||||
```
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# Get User's Preferred Language From Browser
|
|
||||||
|
|
||||||
A great way to determine a user's preferred language if you aren't able to ask
|
|
||||||
them directly is to look at the language setting for their browser's UI.
|
|
||||||
|
|
||||||
We can get this from the instance of
|
|
||||||
[`Navigator`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator) in the
|
|
||||||
user's JavaScript runtime within the browser.
|
|
||||||
|
|
||||||
My browser's UI is set to US English, which I can verify like so:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
> navigator.language
|
|
||||||
'en-US'
|
|
||||||
```
|
|
||||||
|
|
||||||
This is useful for all sorts of things like [formatting dates for
|
|
||||||
display](basic-date-formatting-without-a-library.md):
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
> const now = new Date();
|
|
||||||
> Intl.DateTimeFormat(navigator.language).format(now)
|
|
||||||
'5/14/2026'
|
|
||||||
```
|
|
||||||
|
|
||||||
Or for [formatting other kinds of units for
|
|
||||||
display](formatting-values-with-units-for-display.md):
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
> const milesFormat =
|
|
||||||
Intl.NumberFormat(navigator.language, { style: "unit", unit: "mile" });
|
|
||||||
> milesFormat.format(1500)
|
|
||||||
"1,500 mi"
|
|
||||||
```
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
# `npm run` Has Some Typo Aliases
|
|
||||||
|
|
||||||
The developers of the `npm` CLI know that sometimes we are trying to run
|
|
||||||
commands in a hurry. It's easy to be trying to type `npm run` and instead type
|
|
||||||
`npm rum` or `npm urn`. No worries though, the command will still work.
|
|
||||||
|
|
||||||
If I run `npm help run`, I'll see a manpage that opens with the following:
|
|
||||||
|
|
||||||
```
|
|
||||||
NPM-RUN(1) NPM-RUN(1)
|
|
||||||
|
|
||||||
NAME
|
|
||||||
npm-run - Run arbitrary package scripts
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
npm run <command> [-- <args>]
|
|
||||||
|
|
||||||
aliases: run-script, rum, urn
|
|
||||||
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice it lists a few _aliases_ including `rum` and `urn`.
|
|
||||||
|
|
||||||
Here are two examples of me running my test suite with `rum` and then `urn`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ npm rum test:run
|
|
||||||
|
|
||||||
> test:run
|
|
||||||
> vitest run
|
|
||||||
|
|
||||||
|
|
||||||
RUN v3.0.7 /Users/lastword/dev/jbranchaud/still
|
|
||||||
|
|
||||||
✓ app/javascript/utils/urlUtils.test.js (6 tests) 2ms
|
|
||||||
✓ app/javascript/utils/clipboardImage.test.js (20 tests) 3ms
|
|
||||||
|
|
||||||
Test Files 2 passed (2)
|
|
||||||
Tests 26 passed (26)
|
|
||||||
Start at 22:07:53
|
|
||||||
Duration 298ms (transform 17ms, setup 0ms, collect 22ms, tests 5ms, environment 270ms, prepare 63ms)
|
|
||||||
|
|
||||||
|
|
||||||
❯ npm urn test:run
|
|
||||||
|
|
||||||
> test:run
|
|
||||||
> vitest run
|
|
||||||
|
|
||||||
|
|
||||||
RUN v3.0.7 /Users/lastword/dev/jbranchaud/still
|
|
||||||
|
|
||||||
✓ app/javascript/utils/urlUtils.test.js (6 tests) 3ms
|
|
||||||
✓ app/javascript/utils/clipboardImage.test.js (20 tests) 3ms
|
|
||||||
|
|
||||||
Test Files 2 passed (2)
|
|
||||||
Tests 26 passed (26)
|
|
||||||
Start at 22:07:58
|
|
||||||
Duration 305ms (transform 20ms, setup 0ms, collect 25ms, tests 6ms, environment 269ms, prepare 61ms)
|
|
||||||
```
|
|
||||||
|
|
||||||
See `npm help run` for more details.
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# Describe Current Changes And Create New Change
|
|
||||||
|
|
||||||
One of the first patterns I learned with `jj` was a pair of commands to
|
|
||||||
essentially "commit" the working copy and start a fresh, new change. So if I am
|
|
||||||
done making some changes, I can add a description to the `(no description)`
|
|
||||||
working copy and then start a new working copy _change_.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ jj describe -m "Add status subcommand to show current status"
|
|
||||||
$ jj new
|
|
||||||
```
|
|
||||||
|
|
||||||
I learned from [Steve](https://steveklabnik.com/) in the [jj
|
|
||||||
discord](https://discord.gg/dkmfj3aGQN) that a shorthand for this pattern is to
|
|
||||||
use the `jj commit` command directly.
|
|
||||||
|
|
||||||
> When called without path arguments or `--interactive`, `jj commit` is
|
|
||||||
> equivalent to `jj describe` followed by `jj new`.
|
|
||||||
|
|
||||||
That means, instead of the above pair of commands, I could have done:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ jj commit -m "Add status subcommand to show current status"
|
|
||||||
```
|
|
||||||
|
|
||||||
That would have had the same result in my case. However, notice the caveats
|
|
||||||
mentioned in the quote above and check out `man jj-commit` for more details on
|
|
||||||
that.
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Squash Changes Into Parent Commit Interactively
|
|
||||||
|
|
||||||
While I have some changes in progress as part of the working copy, I can squash
|
|
||||||
them into the previous / parent commit with the `jj squash` command. Running
|
|
||||||
that command as is will apply all the working copy changes to the parent leaving
|
|
||||||
the current revision empty.
|
|
||||||
|
|
||||||
I can also interactively squash those changes similar in spirit to how I might
|
|
||||||
use `git add --patch` to stage and then amend specific changes into the previous
|
|
||||||
commit with `git`. This can be done with [`jj`](https://github.com/jj-vcs/jj)
|
|
||||||
using `squash` with the `-i` flag.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
jj squash -i # or --interactive
|
|
||||||
```
|
|
||||||
|
|
||||||
This will open up a TUI where I can click around or use keys. Each file in the
|
|
||||||
source revision (in my case, the working copy) will be listed. I can move the
|
|
||||||
cursor between them hitting _space_ to toggle them in or out of the squash
|
|
||||||
selection.
|
|
||||||
|
|
||||||
I can also hit `f` over a given file to toggle _folding_. When folding is on, a
|
|
||||||
diff of the file will be disclosed with checkboxes for toggling individual
|
|
||||||
hunks and lines.
|
|
||||||
|
|
||||||
Once I'm satisfied with my interactive selection, I can hit `c` to confirm and
|
|
||||||
only the selected files and changes will be squashed into the parent.
|
|
||||||
|
|
||||||
See `man jj-squash` for more details.
|
|
||||||
|
|
||||||
[source](https://steveklabnik.github.io/jujutsu-tutorial/real-world-workflows/the-squash-workflow.html)
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# Count Number Of Tokens In A File
|
|
||||||
|
|
||||||
Over time you have accumulated a bunch of small directives, corrections, and
|
|
||||||
project details in your `CLAUDE.md` or `AGENTS.md` file. The file doesn't seem
|
|
||||||
too big, but you are mindful that it is being included in every prompt. How many
|
|
||||||
tokens is it eating from the context window?
|
|
||||||
|
|
||||||
OpenAI's BPE (Byte Pair Encoding) tokenization library,
|
|
||||||
[`tiktoken`](https://github.com/openai/tiktoken), is an open-source Python
|
|
||||||
package. If it is installed on our machine, then we can use it as part of the
|
|
||||||
following one-liner to check a file:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ python -c "import tiktoken, sys; print(len(tiktoken.encoding_for_model('gpt-4o').encode(open(sys.argv[1], 'r', encoding='utf-8').read())))" \
|
|
||||||
AGENTS.md
|
|
||||||
1018
|
|
||||||
```
|
|
||||||
|
|
||||||
I ran this against the `AGENTS.md` file in a team project I'm on. It came out to
|
|
||||||
1018 tokens. This is a very good approximation based on the tokenizer trained
|
|
||||||
for `gpt-4o`. The tokenizers may vary a little from model to model, but the
|
|
||||||
differences for our purposes here are going to be negligible.
|
|
||||||
|
|
||||||
This one-liner gets the "first" argument to the command, reads it in, and runs
|
|
||||||
that string against the tokenizer. The length of the tokenized encoding is then
|
|
||||||
printed.
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
# Generate Image Alt Text Across Various Claude Models
|
|
||||||
|
|
||||||
I sometimes experiment with what LLMs will come up with for _alt text_ for an
|
|
||||||
image to see how it compares to what I would have written. Especially with some
|
|
||||||
of the latest models I find that it is more comprehensive and detailed that I
|
|
||||||
would have been.
|
|
||||||
|
|
||||||
Here is an image that I used [in a recent blog post](https://www.visualmode.dev/parameterize-a-fixture-instead-of-a-test-case-with-pytest):
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
And here are four samples of alt text for that image that I requested from
|
|
||||||
various Claude models via inline prompts to the `claude` CLI:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ claude -p "Produce a concise alt text for the following image: @image.png" \
|
|
||||||
--model opus --effort medium --output-format json \
|
|
||||||
| jq '.result'
|
|
||||||
"Alt text:\n\n> Diagram comparing two test suites. Left, \"Behavioral Tests\": a single column of six test rows, four passing (green check) and two failing (red X). Right, \"Parameterized Behavioral Tests\": a list of three parameters (circle, triangle, diamond) with arrows fanning out to three columns, each rerunning the same six tests tagged with that parameter's shape — the circle column all passing, the triangle column with three failures, the diamond column with one failure."
|
|
||||||
|
|
||||||
❯ claude -p "Produce a concise alt text for the following image: @image.png" \
|
|
||||||
--model sonnet --effort medium --output-format json \
|
|
||||||
| jq '.result'
|
|
||||||
"Alt text: \"Diagram contrasting plain behavioral tests (a single list of pass/fail checks) with parameterized behavioral tests, where one test template is run against multiple parameter sets (circle, triangle, diamond), producing separate pass/fail results for each.\""
|
|
||||||
|
|
||||||
❯ claude -p "Produce a concise alt text for the following image: @image.png" \
|
|
||||||
--model haiku --output-format json \
|
|
||||||
| jq '.result'
|
|
||||||
"Diagram contrasting behavioral tests (list with pass/fail results) vs parameterized behavioral tests (matrix showing same tests run with different parameter shapes, each with pass/fail outcomes)."
|
|
||||||
|
|
||||||
❯ claude -p "Produce a concise alt text for the following image: @image.png" \
|
|
||||||
--model fable --effort medium --output-format json \
|
|
||||||
| jq '.result'
|
|
||||||
"Diagram comparing \"Behavioral Tests\" (one column of six test cards, four passing with green checks, two failing with red X's) against \"Parameterized Behavioral Tests\" (a set of three parameters shown as a purple circle, triangle, and diamond, each fanning out into its own column of six test cards, with the circle column all passing and the triangle and diamond columns containing a mix of passes and failures)."
|
|
||||||
```
|
|
||||||
|
|
||||||
I was surprised at how concise each of these were. When I was about to run each
|
|
||||||
of these, I was expecting the results to be closer to what I saw in [_Include A File With Message To `ant`_](include-a-file-with-message-to-ant.md)
|
|
||||||
|
|
||||||
> A hand-drawn style diagram comparing two testing approaches, split by a
|
|
||||||
> vertical line.
|
|
||||||
>
|
|
||||||
> On the left, under the heading "Behavioral Tests," is a single column of six
|
|
||||||
> rounded rectangular test rows: four outlined in green with green check-mark
|
|
||||||
> icons (passing) and two outlined in red with red X icons (failing), each
|
|
||||||
> containing black scribble lines representing text.
|
|
||||||
>
|
|
||||||
> On the right, under the heading "Parameterized Behavioral Tests," a bracketed
|
|
||||||
> list of three purple parameter symbols — a circle, a triangle, and a diamond —
|
|
||||||
> sits at the top, with arrows pointing down to three separate columns of six
|
|
||||||
> test rows each. Every row in a column is tagged with its corresponding
|
|
||||||
> parameter shape on the right edge. The circle column shows all six rows
|
|
||||||
> passing (green with check marks). The triangle column shows three passing and
|
|
||||||
> three failing (red with X marks). The diamond column shows five passing and
|
|
||||||
> one failing. The illustration conveys that a single behavioral test, when
|
|
||||||
> parameterized, expands into multiple variants whose pass/fail outcomes can
|
|
||||||
> differ per parameter.
|
|
||||||
|
|
||||||
I guess the "Be concise, _but descriptive_" made a difference.
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
# Include A File With Message To `ant`
|
|
||||||
|
|
||||||
The [Anthropic CLI tool](https://github.com/anthropics/anthropic-cli) (`ant`)
|
|
||||||
allows including files, such as images, directly in the message being sent to
|
|
||||||
the model. This is done with the `@` symbol followed by a relative path to the
|
|
||||||
image on the file system.
|
|
||||||
|
|
||||||
I have a file `parameterized-behavioral-tests.png` in my current directory that
|
|
||||||
I'd like to include. In the `content` array of the message I include an object
|
|
||||||
of type `image` along with some `source` metadata. Within `source` the image
|
|
||||||
file is referenced with the `data` field.
|
|
||||||
|
|
||||||
With that set, I then include a `text` object with my prompt asking for alt text
|
|
||||||
of this image.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ ant messages create \
|
|
||||||
--model claude-opus-5 \
|
|
||||||
--max-tokens 1024 \
|
|
||||||
--message '{role: user, content: [
|
|
||||||
{type: image, source: {type: base64, media_type: image/png, data: "@./parameterized-behavioral-tests.png"}},
|
|
||||||
{type: text, text: "Produce a concise, but descriptive alt text for this image."}
|
|
||||||
]}' \
|
|
||||||
--transform 'content.#(type=="text").text' --raw-output
|
|
||||||
|
|
||||||
A hand-drawn style diagram comparing two testing approaches, split by a vertical
|
|
||||||
line.
|
|
||||||
|
|
||||||
On the left, under the heading "Behavioral Tests," is a single column of six
|
|
||||||
rounded rectangular test rows: four outlined in green with green check-mark
|
|
||||||
icons (passing) and two outlined in red with red X icons (failing), each
|
|
||||||
containing black scribble lines representing text.
|
|
||||||
|
|
||||||
On the right, under the heading "Parameterized Behavioral Tests," a bracketed
|
|
||||||
list of three purple parameter symbols — a circle, a triangle, and a diamond —
|
|
||||||
sits at the top, with arrows pointing down to three separate columns of six test
|
|
||||||
rows each. Every row in a column is tagged with its corresponding parameter
|
|
||||||
shape on the right edge. The circle column shows all six rows passing (green
|
|
||||||
with check marks). The triangle column shows three passing and three failing
|
|
||||||
(red with X marks). The diamond column shows five passing and one failing. The
|
|
||||||
illustration conveys that a single behavioral test, when parameterized, expands
|
|
||||||
into multiple variants whose pass/fail outcomes can differ per parameter.
|
|
||||||
```
|
|
||||||
|
|
||||||
This is for [the image toward the top of this post on parameterized tests in
|
|
||||||
pytest](https://www.visualmode.dev/parameterize-a-fixture-instead-of-a-test-case-with-pytest).
|
|
||||||
The description is a bit wordier than I would have liked, but it is spot on. It
|
|
||||||
is both visually descriptive and conveys what is being conceptually illustrated.
|
|
||||||
|
|
||||||
This whole thing was 3800 input tokens, 328 output tokens, and cost ~$0.02.
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
# Translate To Canonical Tags With Small Model
|
|
||||||
|
|
||||||
In [Don't Classify, Hallucinate](https://softwaredoug.com/blog/2026/08/10/hypothetical-classifications),
|
|
||||||
Doug Turnbull discusses a technique for hallucinating classifications for a
|
|
||||||
product and then using MiniLM to translate those classifications to actual
|
|
||||||
product classifications in your system / vocabulary.
|
|
||||||
|
|
||||||
The second step in the process he described seemed most interesting to me, so I
|
|
||||||
wanted to experiment with it.
|
|
||||||
|
|
||||||
First, here is my classification system -- that is, these are all the categories
|
|
||||||
of [TIL posts](https://github.com/jbranchaud/til) that I write.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# from my TIL repo
|
|
||||||
❯ git ls-files '*/*.md' | cut -d/ -f1 | sort -u | paste -sd\| - | sed 's/.*/"&"/'
|
|
||||||
"ack|ansible|astro|aws|bash|brew|chrome|claude-code|clojure|css|cursor|deno|devops|docker|drizzle|elixir|gatsby|git|github|github-actions|go|groq|heroku|html|http|inngest|internet|java|javascript|jj|jq|kitty|linux|llm|mac|math|mise|mongodb|mysql|neovim|netlify|next-auth|nextjs|phoenix|planetscale|pnpm|postgres|prisma|python|rails|react|react_native|react-testing-library|reason|remix|rspec|ruby|sed|shell|sqlite|streaming|tailwind|taskfile|tmux|typescript|unix|vercel|vim|vscode|webpack|workflow|xstate|yaml|zed|zod|zsh"
|
|
||||||
```
|
|
||||||
|
|
||||||
I'll grab that output and use it in the following set of Python REPL steps. Here
|
|
||||||
I need to import
|
|
||||||
[`sentence_transformers`](https://sbert.net/docs/quickstart.html#sentence-transformer)
|
|
||||||
which is "applicable for a wide range of tasks, such as semantic textual
|
|
||||||
similarity, semantic search, clustering, classification, paraphrase mining, and
|
|
||||||
more."
|
|
||||||
|
|
||||||
```python
|
|
||||||
# I initiate this REPL with:
|
|
||||||
# ❯ uv run --with sentence_transformers python
|
|
||||||
>>> from sentence_transformers import SentenceTransformer
|
|
||||||
>>> model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
|
|
||||||
>>> raw_tags = "ack|ansible|astro|aws|bash|brew|chrome|claude-code|clojure|css|cursor|deno|devops|docker|drizzle|elixir|gatsby|git|github|github-actions|go|groq|heroku|html|http|inngest|internet|java|javascript|jj|jq|kitty|linux|llm|mac|math|mise|mongodb|mysql|neovim|netlify|next-auth|nextjs|phoenix|planetscale|pnpm|postgres|prisma|python|rails|react|react_native|react-testing-library|reason|remix|rspec|ruby|sed|shell|sqlite|streaming|tailwind|taskfile|tmux|typescript|unix|vercel|vim|vscode|webpack|workflow|xstate|yaml|zed|zod|zsh"
|
|
||||||
>>> tags = raw_tags.split("|")
|
|
||||||
>>> tag_vecs = model.encode(tags, normalize_embeddings=True)
|
|
||||||
>>> def resolve(fake_tags, threshold=0.5):
|
|
||||||
... fake_vecs = model.encode(fake_tags, normalize_embeddings=True)
|
|
||||||
... scores = fake_vecs @ tag_vecs.T
|
|
||||||
... best, best_score = scores.argmax(1), scores.max(1)
|
|
||||||
... return {tags[i] for i, s in zip(best, best_score) if s >= threshold
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
With that all set up, I take a set of tags for a post like this one that
|
|
||||||
you're reading and see if I can get them to resolve to one or more tags directly
|
|
||||||
from the canonical tag vocabulary.
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> resolve(["Python 3.13", "uv", "ML / LLM / Classification"])
|
|
||||||
{'python', 'llm'}
|
|
||||||
```
|
|
||||||
|
|
||||||
A set of tags with varying structure and specificity can be translated into the
|
|
||||||
relevant canonical tags that I started with.
|
|
||||||
|
|
||||||
I can also experiment a little with the threshold. Where is the line for
|
|
||||||
"Version Control" being associated to "git"?
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> resolve(["Version Control"])
|
|
||||||
set()
|
|
||||||
>>> resolve(["Version Control"], 0.2)
|
|
||||||
{'git'}
|
|
||||||
>>> resolve(["Version Control"], 0.3)
|
|
||||||
{'git'}
|
|
||||||
>>> resolve(["Version Control"], 0.4)
|
|
||||||
{'git'}
|
|
||||||
>>> resolve(["Version Control"], 0.5)
|
|
||||||
set()
|
|
||||||
>>> resolve(["Version Control"], 0.45)
|
|
||||||
set()
|
|
||||||
>>> resolve(["Version Control"], 0.42)
|
|
||||||
{'git'}
|
|
||||||
```
|
|
||||||
|
|
||||||
A quick note on what is happening in the `resolve` function above. We have the
|
|
||||||
normalized embedding vectors for the _fake tags_ and the set of canonical tags.
|
|
||||||
We then compute the dot product of the fake tags embeddings with the
|
|
||||||
_transposed_ canonical tags. This gives us the cosine similarly between all of
|
|
||||||
them which is an indication of how similar each fake tag vector is to each
|
|
||||||
canonical tag vector. The ones above the `0.5` threshold make the cut and that
|
|
||||||
set is returned. We may match one tag, a couple tags, or even no tags.
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
# Access Daily Journal From CLI With HTTP Server
|
|
||||||
|
|
||||||
I use [logseq](https://logseq.com/) as the daily driver for my notes both inside
|
|
||||||
and outside of work. I like the organization provided by the outliner notetaking
|
|
||||||
style.
|
|
||||||
|
|
||||||
I now want to set up some automations that interact with my notes. I originally
|
|
||||||
figured this would involve reading directly from markdown files on disk.
|
|
||||||
However, they recently migrated to a SQLite storage format and I learned that
|
|
||||||
there is an HTTP server you can run for more reliable interactions.
|
|
||||||
|
|
||||||
The HTTP server needs to be enabled. To do this, I did the following (though I'm
|
|
||||||
not sure if _Developer Mode_ is required):
|
|
||||||
|
|
||||||
1. Find the `...` icon to access the app's main menu
|
|
||||||
2. Open _Settings_
|
|
||||||
3. Enable _Developer Mode_ under _Advanced_
|
|
||||||
4. Enable _HTTP API Server_ under _Features_
|
|
||||||
5. Restart the logseq app
|
|
||||||
6. Click the disabled _API_ icon that is in the upper-right next to the
|
|
||||||
navigational arrows
|
|
||||||
7. Create a new _Authorization Token_ and copy the value
|
|
||||||
8. Click _Start Server_ and it will run at `http://127.0.0.1:12315`
|
|
||||||
|
|
||||||
With all that in place, the server is running and ready to accept my first
|
|
||||||
query. I want to get a look at my notes so far today, so I'll run a `curl`
|
|
||||||
request against the `/api` path with the auth token I copied.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ curl -s -X POST http://127.0.0.1:12315/api \
|
|
||||||
-H "Authorization: Bearer $LOGSEQ_API_TOKEN" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"method":"logseq.Editor.getPageBlocksTree","args":["Oct 31st, 2026"]}'
|
|
||||||
[{"updatedAt":1793456696397,"createdAt":1793456670024,"parent":{"id":5943},"children":[],"id":5947,"level":1,"uuid":"6ae5fa1e-afa2-46c9-abbc-abf58b434e3e","fullTitle":"Working on setting up the HTTP server for logseq to see if I can interact with it via the CLI.","content":"Working on setting up the HTTP server for logseq to see if I can interact with it via the CLI.","order":"a0","title":"Working on setting up the HTTP server for logseq to see if I can interact with it via the CLI.","page":{"id":5943}},{"updatedAt":1793456702190,"createdAt":1793456697156,"parent":{"id":5943},"children":[{"updatedAt":1793456702212,"createdAt":1793456702212,"parent":{"id":5948},"children":[],"id":5949,"level":2,"uuid":"6ae5fa3e-0865-4713-9690-c456fb1a37ad","fullTitle":"","content":"","order":"a0","title":"","page":{"id":5943}}],"id":5948,"level":1,"uuid":"6ae5fa39-96bc-4f26-9d5f-2b3b3a366070","fullTitle":"[[6aa01dba-1b28-4540-b205-5254ee37d825]]","content":"[[6aa01dba-1b28-4540-b205-5254ee37d825]]","order":"a1","title":"[[6aa01dba-1b28-4540-b205-5254ee37d825]]","page":{"id":5943},"refs":[{"id":642}]}]%
|
|
||||||
```
|
|
||||||
|
|
||||||
The data we pass as the request body includes the `method` we are running which
|
|
||||||
is "get all the blocks for the specified page"
|
|
||||||
([`getPageBlocksTree`](https://plugins-doc.logseq.com/logseq/Editor/getPageBlocksTree)).
|
|
||||||
The `args` then specify what page we are referring to. In this case, today's
|
|
||||||
daily journal -- `"Oct 31st, 2026"` (👻). The result is that pile of JSON.
|
|
||||||
|
|
||||||
Whenever I get a long line of JSON like that, I like to use `jq` at the very
|
|
||||||
least to pretty-print it or even to dig in a bit.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ curl -s -X POST http://127.0.0.1:12315/api \
|
|
||||||
-H "Authorization: Bearer $LOGSEQ_API_TOKEN" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"method":"logseq.Editor.getPageBlocksTree","args":["Oct 31st, 2026"]}' | jq
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"updatedAt": 1793456696397,
|
|
||||||
"createdAt": 1793456670024,
|
|
||||||
"parent": {
|
|
||||||
"id": 5943
|
|
||||||
},
|
|
||||||
"children": [],
|
|
||||||
"id": 5947,
|
|
||||||
"level": 1,
|
|
||||||
"uuid": "6ae5fa1e-afa2-46c9-abbc-abf58b434e3e",
|
|
||||||
"fullTitle": "Working on setting up the HTTP server for logseq to see if I can interact with it via the CLI.",
|
|
||||||
"content": "Working on setting up the HTTP server for logseq to see if I can interact with it via the CLI.",
|
|
||||||
"order": "a0",
|
|
||||||
"title": "Working on setting up the HTTP server for logseq to see if I can interact with it via the CLI.",
|
|
||||||
"page": {
|
|
||||||
"id": 5943
|
|
||||||
}
|
|
||||||
},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
```
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# Access CoreUtils That Conflict With Unix Utilities
|
|
||||||
|
|
||||||
In [another post about GNU CoreUtils](add-a-bunch-of-cli-utilities-with-coreutils.md) I explained how to
|
|
||||||
install and use some of the provided utilities. The utilities I referenced were
|
|
||||||
`seq` and `realpath` which are novel on MacOS. There are other CoreUtils that
|
|
||||||
would conflict with existing system utilities. To avoid the conflicts, [those
|
|
||||||
utilities are installed with `g`
|
|
||||||
prefix](https://unix.stackexchange.com/a/729136).
|
|
||||||
|
|
||||||
A good example of this is `mv` and `gmv`. These are both utilities for moving
|
|
||||||
files and largely behave the same. They are a few subtle differences though.
|
|
||||||
|
|
||||||
Here is the manpage for the built-in `mv` utility:
|
|
||||||
|
|
||||||
```
|
|
||||||
NAME
|
|
||||||
mv – move files
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
mv [-f | -i | -n] [-hv] source target
|
|
||||||
mv [-f | -i | -n] [-v] source ... directory
|
|
||||||
```
|
|
||||||
|
|
||||||
And here is the manpage for `gmv`:
|
|
||||||
|
|
||||||
```
|
|
||||||
NAME
|
|
||||||
mv - move (rename) files
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
mv [OPTION]... [-T] SOURCE DEST
|
|
||||||
mv [OPTION]... SOURCE... DIRECTORY
|
|
||||||
mv [OPTION]... -t DIRECTORY SOURCE...
|
|
||||||
```
|
|
||||||
|
|
||||||
There are some different forms and flags available. `gmv` for instance supports
|
|
||||||
a `-t` flag which specifies the _target_ directory so that all other listed
|
|
||||||
paths are treated as sources of the move. This makes `gmv` easier to use with
|
|
||||||
`xargs`, for instance.
|
|
||||||
|
|
||||||
Look through `fd '^g' /opt/homebrew/bin/` and you'll notice a bunch of them like
|
|
||||||
`gls`, `gln`, `ghead`, `gwhoami`, `gyes`, etc. You can also look through all of
|
|
||||||
them in the [`coreutils.json` homebrew formula](https://formulae.brew.sh/api/formula/coreutils.json).
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
# Add A Bunch Of CLI Utilities With coreutils
|
|
||||||
|
|
||||||
The [`coreutils`](https://www.gnu.org/software/coreutils/) project is a
|
|
||||||
collection of useful utilities that every operating system ought to have.
|
|
||||||
|
|
||||||
> The GNU Core Utilities are the basic file, shell and text manipulation
|
|
||||||
> utilities of the GNU operating system. These are the core utilities which are
|
|
||||||
> expected to exist on every operating system.
|
|
||||||
|
|
||||||
While many of these utilities are redundant with BSD utilities that MacOS
|
|
||||||
chooses to ship with, there are some differences in the overlapping ons and then
|
|
||||||
many additions from `coreutils`.
|
|
||||||
|
|
||||||
They can be installed with Homebrew:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ brew install coreutils
|
|
||||||
```
|
|
||||||
|
|
||||||
And then you should have some new things available on your path. Take `shuf`, for
|
|
||||||
instance. This utility can shuffle and select items from a file or incoming
|
|
||||||
lines from another command. Here I use it to randomly grab a number between 1
|
|
||||||
and 5 (with the help of `seq`):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ seq 1 5 | shuf -n 1
|
|
||||||
3
|
|
||||||
|
|
||||||
❯ seq 1 5 | shuf -n 1
|
|
||||||
2
|
|
||||||
|
|
||||||
❯ seq 1 5 | shuf -n 1
|
|
||||||
5
|
|
||||||
```
|
|
||||||
|
|
||||||
Or how about some utilities for manipulating file names? Among others there is
|
|
||||||
`realpath`, `basename`, and `dirname`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ realpath README.md
|
|
||||||
/Users/lastword/dev/jbranchaud/til/README.md
|
|
||||||
|
|
||||||
❯ realpath README.md | xargs basename
|
|
||||||
README.md
|
|
||||||
|
|
||||||
❯ realpath README.md | xargs dirname
|
|
||||||
/Users/lastword/dev/jbranchaud/til
|
|
||||||
```
|
|
||||||
|
|
||||||
See the [manual](https://www.gnu.org/software/coreutils/manual/coreutils.html)
|
|
||||||
for many more details.
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Capture Screenshoot To Clipboard From CLI
|
|
||||||
|
|
||||||
MacOS comes with a `screencapture` utility that you can run from the terminal
|
|
||||||
to activate the built-in screenshot functionality on Mac.
|
|
||||||
|
|
||||||
Usually when I am taking a screenshot, I want to do something with it right
|
|
||||||
away. Such as paste it into an application or group chat. The `-c` flag forces
|
|
||||||
the screen capture to go the clipboard.
|
|
||||||
|
|
||||||
I also generally want to capture a specific area of the screen so that the
|
|
||||||
captured image includes the right amount of context and nothing more. The `-i`
|
|
||||||
flag puts you in interactive screen capture mode. That means your cursor will
|
|
||||||
turn into a crosshair that you can use to make a drag selection of the capture
|
|
||||||
area.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ screencapture -ic
|
|
||||||
```
|
|
||||||
|
|
||||||
Select an area to capture, it's now on your clipboard, paste it where you need
|
|
||||||
it.
|
|
||||||
|
|
||||||
Note: The first time you run this command, your terminal program (e.g. iTerm2)
|
|
||||||
may prompt you for the necessary OS permissions in order to capture images of
|
|
||||||
your screen. You'll need to grant those permissions and then rerun the command.
|
|
||||||
|
|
||||||
See `man screencapture` for more details.
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# Clean Up Item Layout In Finder Window
|
|
||||||
|
|
||||||
Sometimes while doing a bunch of manual drag-n-drop of files and folders in a
|
|
||||||
Finder.app window, I'll end up with a visual mess. Compared to other folders,
|
|
||||||
nothing is organized on the grid.
|
|
||||||
|
|
||||||
I can tell Finder.app to clean that up with the _Clean Up_ menu option.
|
|
||||||
|
|
||||||
While focused on the folder that I'm concerned about, I can go to _View_ >
|
|
||||||
_Clean Up_ in the top menu. Everything will snap into place.
|
|
||||||
|
|
||||||
On the specific Finder.app window, there is also a triple-dot actions menu that
|
|
||||||
appears on the top right. The _Clean Up_ action is available there as well.
|
|
||||||
|
|
||||||
There is also a _Clean Up By_ option which is a nice way to organize by some
|
|
||||||
attribute, such as the type (e.g Folder/File and extension).
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# Control Which Monitor App Switcher Appears On
|
|
||||||
|
|
||||||
For the most part when I hit `cmd+tab` (and `cmd+shift+tab`) to switch between
|
|
||||||
apps, the visual switcher UI (which shows a row of the open apps) appears on my
|
|
||||||
main monitor. However, sometimes I will be hitting `cmd+tab` and nothing shows
|
|
||||||
up on my main monitor. I look to the right at my side monitor and there is the
|
|
||||||
app switcher UI.
|
|
||||||
|
|
||||||
Why is it appearing over there all of a sudden?
|
|
||||||
|
|
||||||
The reason is that the app switcher UI is anchored to the same screen where the
|
|
||||||
doc is located. Though the doc defaults to my main monitor, if I access the doc
|
|
||||||
from the side monitor, now it is anchored there.
|
|
||||||
|
|
||||||
To switch it back, I just have to make the doc slide up on my main monitor by
|
|
||||||
running my mouse down to the bottom of that screen.
|
|
||||||
|
|
||||||
The switch up was because I accidentally accessed the doc on my side monitor
|
|
||||||
without realizing.
|
|
||||||
|
|
||||||
[source](https://superuser.com/a/744680)
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Detect How Long A User Has Been Idle
|
|
||||||
|
|
||||||
The `ioreg` utility on MacOS dumps the I/O Kit registry tree. This lets us look
|
|
||||||
at the state of all hardware devices and drivers registered with I/O Kit.
|
|
||||||
Looking specifically at the Human Interface Device subsystem (`IOHIDSystem`), we
|
|
||||||
can find a handful of properties including the `HIDIdleTime`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ ioreg -c IOHIDSystem | awk '/HIDIdleTime/'
|
|
||||||
| | | "HIDIdleTime" = 91831000
|
|
||||||
```
|
|
||||||
|
|
||||||
That value is the number of nanoseconds since a human input device was last
|
|
||||||
interacted with. That is the amount of time the user (me) has been idle.
|
|
||||||
|
|
||||||
I can convert this to seconds, which is the small amount of time between me
|
|
||||||
hitting enter in the terminal and the command finding the idle time.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {printf "%.2f seconds\n", $NF/1000000000}'
|
|
||||||
0.13 seconds
|
|
||||||
```
|
|
||||||
|
|
||||||
I can run this in `watch` to see the elapsed idle time increment.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
watch -n 1 "echo -n 'Idle time: '; ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {printf \"%.1f seconds\\n\", \$NF/1000000000}'"
|
|
||||||
```
|
|
||||||
|
|
||||||
After watching the _idle time_ increment for a bit, I can move the mouse and
|
|
||||||
watch it reset on the next `watch` loop.
|
|
||||||
|
|
||||||
This could be used as part of a script that takes certain actions after the user
|
|
||||||
has been idle for a while, like putting the display to sleep or stopping a time
|
|
||||||
tracker app.
|
|
||||||
|
|
||||||
There is a _lot_ going on in the `ioreg` output and it's hard to make sense of
|
|
||||||
hardly any of it. I found running `ioreg -c IOHIDSystem | less`, searching for
|
|
||||||
`IdleTime`, and browsing from there to be a good starting point.
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
# Inspect Assertions Preventing Sleep
|
|
||||||
|
|
||||||
The `pmset` command is for inspecting and manipulating _Power Management
|
|
||||||
Settings_ on MacOS. The `-g` flag is for _getting_ details. We can get a summary
|
|
||||||
of power assertions with `-g assertions`. These assertions are ways that the
|
|
||||||
system and display are prevented from sleeping.
|
|
||||||
|
|
||||||
A common assertion preventing sleep is the user being active. Another example of
|
|
||||||
an assertion is a program like `caffeinate` that sets a timeout preventing sleep
|
|
||||||
for a fixed period of time.
|
|
||||||
|
|
||||||
Here I activate a 30 minute (1600 second) `caffeinate` session and then I
|
|
||||||
inspect the power management assertions which shows the details of that
|
|
||||||
assertion as well as two others.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ caffeinate -t 1600 &
|
|
||||||
[1] 98217
|
|
||||||
|
|
||||||
❯ pmset -g assertions
|
|
||||||
2025-11-02 13:20:57 -0600
|
|
||||||
Assertion status system-wide:
|
|
||||||
BackgroundTask 0
|
|
||||||
ApplePushServiceTask 0
|
|
||||||
UserIsActive 1
|
|
||||||
PreventUserIdleDisplaySleep 0
|
|
||||||
PreventSystemSleep 0
|
|
||||||
ExternalMedia 0
|
|
||||||
PreventUserIdleSystemSleep 1
|
|
||||||
NetworkClientActive 0
|
|
||||||
Listed by owning process:
|
|
||||||
pid 98217(caffeinate): [0x00045477000194b3] 00:00:03 PreventUserIdleSystemSleep named: "caffeinate command-line tool"
|
|
||||||
Details: caffeinate asserting for 1600 secs
|
|
||||||
Localized=THE CAFFEINATE TOOL IS PREVENTING SLEEP.
|
|
||||||
Timeout will fire in 1597 secs Action=TimeoutActionRelease
|
|
||||||
pid 145(WindowServer): [0x00044f2f00099212] 00:00:00 UserIsActive named: "com.apple.iohideventsystem.queue.tickle serviceID:10009be9e service:AppleUserHIDEventService product:CTRL Keyboard eventType:3"
|
|
||||||
Timeout will fire in 600 secs Action=TimeoutActionRelease
|
|
||||||
pid 80(powerd): [0x00044f2f00019216] 00:22:34 PreventUserIdleSystemSleep named: "Powerd - Prevent sleep while display is on"
|
|
||||||
```
|
|
||||||
|
|
||||||
See `man pmset` and `man caffeinate` for more details.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Launch Some Confetti
|
|
||||||
|
|
||||||
If you have [Raycast](https://www.raycast.com/) installed on your machine, then
|
|
||||||
you have quick access to some confetti via their quick command palette. Trigger
|
|
||||||
the command palette to open, start typing `confetti` until it appears as the
|
|
||||||
focused option, and then hit enter.
|
|
||||||
|
|
||||||
🎉
|
|
||||||
|
|
||||||
We can launch confetti other ways, including programmatically from scripts.
|
|
||||||
|
|
||||||
To do this, we need to first find the _deeplink_ for the Raycast _confetti_
|
|
||||||
program. Trigger the command palette and type out `confetti` again. However,
|
|
||||||
this time instead of hitting enter, hit `Cmd+k` to open other actions. Find the
|
|
||||||
_Copy Deeplink_ option.
|
|
||||||
|
|
||||||
You should now have this on your clipboard:
|
|
||||||
|
|
||||||
```
|
|
||||||
raycast://extensions/raycast/raycast/confetti
|
|
||||||
```
|
|
||||||
|
|
||||||
With this deeplink in hand, we can now trigger confetti other places. The
|
|
||||||
easiest way to do this is to open a terminal and pass that deep link as an
|
|
||||||
argument to `open`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ open raycast://extensions/raycast/raycast/confetti
|
|
||||||
```
|
|
||||||
|
|
||||||
Now you can wrap that up in any old bash script or even just tack it on to the
|
|
||||||
end of a run of your test suite:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ rails test && open raycast://extensions/raycast/raycast/confetti
|
|
||||||
```
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Prevent Sleep With The Caffeinate Command
|
|
||||||
|
|
||||||
MacOS has a built-in utility `caffeinate` that can programatically prevent your
|
|
||||||
machine from sleeping. There are two kinds of sleep that it can prevent via
|
|
||||||
_assertions_.
|
|
||||||
|
|
||||||
> caffeinate creates assertions to alter system sleep behavior.
|
|
||||||
|
|
||||||
The two kinds of sleep behavior are _display sleep_ and _system idle sleep_. An
|
|
||||||
assertion to prevent display sleep can be created with `-d` and system idle
|
|
||||||
sleep with `-i`.
|
|
||||||
|
|
||||||
We can combine those to prevent both and then specify a duration (_timeout_)
|
|
||||||
with `-t` (with a value in seconds).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
caffeinate -d -i -t 600
|
|
||||||
```
|
|
||||||
|
|
||||||
This creates assertions with 10 minute timeouts for both display and system idle
|
|
||||||
sleep.
|
|
||||||
|
|
||||||
The `caffeinate` command is blocking, so if you want to start it in the
|
|
||||||
background, you can do that like so:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
caffeinate -d -i -t 600 &
|
|
||||||
```
|
|
||||||
|
|
||||||
See `man caffeinate` for more details.
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
# Read The Lid Angle Sensor For A MacBook
|
|
||||||
|
|
||||||
MacOS has a bunch of internal HID (Human Interface Device) data that can surface
|
|
||||||
details about all kinds of "devices" that comprise your machine. Some obvious
|
|
||||||
ones are the keyboard and trackpad as well as external mice and keyboards. The
|
|
||||||
battery and power source details are another which is sometimes integrated into
|
|
||||||
tools that display battery status (e.g.
|
|
||||||
[`tmux-battery`](https://github.com/tmux-plugins/tmux-battery)), though it uses
|
|
||||||
`pmset` directly). And many, many more.
|
|
||||||
|
|
||||||
One example I'd never considered is that there is a sensor for the lid angle of
|
|
||||||
the laptop that can tell the system whether the lid is open or closed and how
|
|
||||||
open it is (i.e. at what angle). There is no public interface for this lid angle
|
|
||||||
sensor, but people exploring all the HID devices have found the identifiers that
|
|
||||||
correspond to it (e.g.
|
|
||||||
[`pybooklid`](https://github.com/tcsenpai/pybooklid/blob/main/pybooklid/macbook_lid.py)).
|
|
||||||
|
|
||||||
Here is a minimal script that uses `uv`, `hidapi` (python bindings), and
|
|
||||||
`libhidapi` (shared runtime lib for those bindings):
|
|
||||||
|
|
||||||
```python
|
|
||||||
#!/usr/bin/env -S uv run --quiet --script
|
|
||||||
# /// script
|
|
||||||
# requires-python = ">=3.10"
|
|
||||||
# dependencies = ["hidapi"]
|
|
||||||
# ///
|
|
||||||
"""Print MacBook lid angle in degrees."""
|
|
||||||
import os, sys
|
|
||||||
|
|
||||||
if sys.platform == "darwin":
|
|
||||||
brew = "/opt/homebrew/lib"
|
|
||||||
if os.path.exists(brew):
|
|
||||||
os.environ["DYLD_LIBRARY_PATH"] = f"{brew}:{os.environ.get('DYLD_LIBRARY_PATH','')}"
|
|
||||||
|
|
||||||
import hid
|
|
||||||
|
|
||||||
VENDOR_ID, PRODUCT_ID = 0x05AC, 0x8104
|
|
||||||
USAGE_PAGE, USAGE = 0x0020, 0x008A
|
|
||||||
REPORT_ID = 1
|
|
||||||
|
|
||||||
def read_angle():
|
|
||||||
for info in hid.enumerate(VENDOR_ID, PRODUCT_ID):
|
|
||||||
if info.get("usage_page") == USAGE_PAGE and info.get("usage") == USAGE:
|
|
||||||
d = hid.device()
|
|
||||||
path = info["path"]
|
|
||||||
d.open_path(path if isinstance(path, bytes) else path.encode())
|
|
||||||
try:
|
|
||||||
data = d.get_feature_report(REPORT_ID, 8)
|
|
||||||
if data and len(data) >= 3:
|
|
||||||
return float((data[2] << 8) | data[1])
|
|
||||||
finally:
|
|
||||||
d.close()
|
|
||||||
return None
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
a = read_angle()
|
|
||||||
if a is None:
|
|
||||||
sys.exit("sensor not available")
|
|
||||||
print(f"{a:.0f}")
|
|
||||||
```
|
|
||||||
|
|
||||||
These IDs and usage values are the undocumented values that allow the script to
|
|
||||||
navigate specifically to the lid angle sensor and specifically to the usage page
|
|
||||||
and value that represent the current lid angle reading.
|
|
||||||
|
|
||||||
```
|
|
||||||
VENDOR_ID, PRODUCT_ID = 0x05AC, 0x8104
|
|
||||||
USAGE_PAGE, USAGE = 0x0020, 0x008A
|
|
||||||
REPORT_ID = 1
|
|
||||||
```
|
|
||||||
|
|
||||||
I added [this
|
|
||||||
script](https://github.com/jbranchaud/dotfiles/blob/cbc7196607d1d6b25885f5387ca85b658bd765de/bin/lidangle)
|
|
||||||
to [my dotfiles](https://github.com/jbranchaud/dotfiles) and made it executable
|
|
||||||
(`chmod +x bin/lidangle`) so that I can try it out. I first ran it while it was
|
|
||||||
closed and connected to my external monitor (`0`), then I opened it as far as it
|
|
||||||
could go (`129`), and then I tried angling it close to what I thought was 90
|
|
||||||
degress (`92`, so close).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ lidangle
|
|
||||||
0
|
|
||||||
|
|
||||||
❯ lidangle
|
|
||||||
129
|
|
||||||
|
|
||||||
❯ lidangle
|
|
||||||
92
|
|
||||||
```
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# Reveal Location Of File In Finder.app
|
|
||||||
|
|
||||||
In the terminal I have the path to an image file. I want to open Finder.app to
|
|
||||||
the location of that image file so that I can drag and drop it into a file
|
|
||||||
upload area in the browser.
|
|
||||||
|
|
||||||
Instead of opening a Finder.app window and navigating directory by directory to
|
|
||||||
the location, I can use the `open` command. Using `open` directly with the image
|
|
||||||
file will open the image in Preview.app. I want to reveal the directory that the
|
|
||||||
image file is in within Finder.app. _Reveal_ is the keyword and the `-R` flag
|
|
||||||
does just that.
|
|
||||||
|
|
||||||
Here is an example of this that I actually ran when uploading a screenshot that
|
|
||||||
went into [this blogmark post](https://still.visualmode.dev/blogmarks/255):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ open -R /Users/lastword/images/tiobe-index-graph-march-2026.png
|
|
||||||
```
|
|
||||||
|
|
||||||
See `man open` for more details.
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
# Set Default Search Directory For Finder
|
|
||||||
|
|
||||||
In MacOS's Finder.app, when I click the Search (magnifying glass) icon and type
|
|
||||||
something in, it performs the search across all of "This Mac". This has always
|
|
||||||
really bugged me because I'm usually already in the directory that I want to be
|
|
||||||
specifically searching in.
|
|
||||||
|
|
||||||
A small quality-of-life improvement for me was to update the setting that
|
|
||||||
controls this to search in the current directory instead.
|
|
||||||
|
|
||||||
This can be done via the Finder.app menu at the bottom of the _Advanced_ section
|
|
||||||
in the _Settings_. The three setting options are:
|
|
||||||
|
|
||||||
- Search This Mac
|
|
||||||
- Search the Current Folder
|
|
||||||
- Search the Previous Search Scope
|
|
||||||
|
|
||||||
This can also be controlled from the command line using the `defaults write`
|
|
||||||
command. The specific setting is called `FXDefaultSearchScope` and the above
|
|
||||||
three settings translate to:
|
|
||||||
|
|
||||||
- `SCev` (Search This Mac)
|
|
||||||
- `SCcf` (Search the Current Folder)
|
|
||||||
- `SCsp` (Search the Previous Search Scope)
|
|
||||||
|
|
||||||
I can see the current default setting with `defaults read`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ defaults read com.apple.finder FXDefaultSearchScope
|
|
||||||
SCev
|
|
||||||
```
|
|
||||||
|
|
||||||
I can then change it to the _Search the Current Folder_ option like so:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ defaults write com.apple.finder FXDefaultSearchScope -string "SCcf"
|
|
||||||
```
|
|
||||||
|
|
||||||
All the open Finder windows still hold the original setting. I need to do a
|
|
||||||
`killall Finder` to effectively reload them. Now if I try doing a search, it
|
|
||||||
should default to the current directory instead of _This Mac_.
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
# Convert Arbitrary Number To Probability With Sigmoid
|
|
||||||
|
|
||||||
A sigmoid function is a useful function in statistics and machine learning for
|
|
||||||
converting a number in the range of positive and negative real numbers into a
|
|
||||||
value between 0 and 1. Sigmoid functions can be a bit more diverse than this,
|
|
||||||
but this is a good basic definition.
|
|
||||||
|
|
||||||
Wikipedia defines another characteristic of sigmoid functions:
|
|
||||||
|
|
||||||
> A sigmoid function is any mathematical function whose graph has a
|
|
||||||
> characteristic S-shaped or sigmoid curve.
|
|
||||||
|
|
||||||
This S-shape is because it is asymptotic at the ends allowing it to cover all
|
|
||||||
real numbers in either direction.
|
|
||||||
|
|
||||||
A common sigmoid function and the one used by [PyTorch's `Sigmoid`](https://docs.pytorch.org/docs/2.13/generated/torch.nn.Sigmoid.html)
|
|
||||||
is this exponential form -- `σ(x) = 1 / (1 + exp(-x))`.
|
|
||||||
|
|
||||||
Here is what this looks like plotted on a graph:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
This function can be used any time we want to convert an arbitrary number into a
|
|
||||||
probability. Large negative numbers will approach 0. Large positive numbers will
|
|
||||||
approach 1. Numbers near 0 will settle somewhere in the middle.
|
|
||||||
|
|
||||||
Here are a few examples run through PyTorch's `sigmoid` function:
|
|
||||||
|
|
||||||
```python
|
|
||||||
print("σ(-99) => ", torch.sigmoid(torch.tensor(-99.0)))
|
|
||||||
print("σ(99) => ", torch.sigmoid(torch.tensor(99.0)))
|
|
||||||
print("σ(0.123) => ", torch.sigmoid(torch.tensor(0.123)))
|
|
||||||
print("σ(-2) => ", torch.sigmoid(torch.tensor(-2.0)))
|
|
||||||
print("σ(1) => ", torch.sigmoid(torch.tensor(1.0)))
|
|
||||||
```
|
|
||||||
|
|
||||||
which prints out:
|
|
||||||
|
|
||||||
```
|
|
||||||
σ(-99) => tensor(0.)
|
|
||||||
σ(99) => tensor(1.)
|
|
||||||
σ(0.123) => tensor(0.5307)
|
|
||||||
σ(-2) => tensor(0.1192)
|
|
||||||
σ(1) => tensor(0.7311)
|
|
||||||
```
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
# Generate Permutations Of All Valid 9-ball Racks
|
|
||||||
|
|
||||||
I wanted to produce a full listing of all valid rack arrangements for the game
|
|
||||||
of [9-ball](https://en.wikipedia.org/wiki/Nine-ball). The constraints on how a
|
|
||||||
9-ball rack can be arranged are, first, that the 1 ball must be placed at the
|
|
||||||
head of the diamond and, second, that the 9 ball must be placed at the center of
|
|
||||||
the diamond. After that, all other balls (2 through 8) can be placed in any
|
|
||||||
arrangement.
|
|
||||||
|
|
||||||
Because each of those seven remaining balls can be arranged in distinct
|
|
||||||
orderings where each ball is placed once, this is a
|
|
||||||
[_permutation_](https://en.wikipedia.org/wiki/Permutation) problem.
|
|
||||||
|
|
||||||
> In elementary combinatorics, the k-permutations, or partial permutations, are
|
|
||||||
> the ordered arrangements of k distinct elements selected from a set. When k is
|
|
||||||
> equal to the size of the set, these are the permutations in the previous
|
|
||||||
> sense.
|
|
||||||
|
|
||||||
For this problem, the seven distinct elements can be arranged into `7!` (seven
|
|
||||||
factorial) unique permutations. That is, 5040 permutations.
|
|
||||||
|
|
||||||
I can use [Ruby's `Array#permutations`
|
|
||||||
method](https://docs.ruby-lang.org/en/4.0/Array.html#method-i-permutation) to
|
|
||||||
enumerate these 5040 permutations like so:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
[2,3,4,5,6,7,8].permutation.map do |perm|
|
|
||||||
[1, *perm[0..2], 9, *perm[3..7]]
|
|
||||||
end.to_a
|
|
||||||
=> [[1, 2, 3, 4, 9, 5, 6, 7, 8],
|
|
||||||
[1, 2, 3, 4, 9, 5, 6, 8, 7],
|
|
||||||
[1, 2, 3, 4, 9, 5, 7, 6, 8],
|
|
||||||
[1, 2, 3, 4, 9, 5, 7, 8, 6],
|
|
||||||
[1, 2, 3, 4, 9, 5, 8, 6, 7],
|
|
||||||
[1, 2, 3, 4, 9, 5, 8, 7, 6],
|
|
||||||
[1, 2, 3, 4, 9, 6, 5, 7, 8],
|
|
||||||
...
|
|
||||||
[1, 8, 7, 6, 9, 5, 3, 2, 4],
|
|
||||||
[1, 8, 7, 6, 9, 5, 3, 4, 2],
|
|
||||||
[1, 8, 7, 6, 9, 5, 4, 2, 3],
|
|
||||||
[1, 8, 7, 6, 9, 5, 4, 3, 2]]
|
|
||||||
```
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
# Create Umbrella Task For All Test Tasks
|
# Create Umbrella Task For All Test Tasks
|
||||||
|
|
||||||
When I was first sketching out the [`mise` tasks](https://mise.jdx.dev/tasks/running-tasks.html) for a Rails app, I added
|
When I was first sketching out the [`mise`
|
||||||
the following two tasks. One is for running all the `rspec` tests. The other is
|
tasks](https://mise.jdx.dev/tasks/running-tasks.html) for a Rails app, I added
|
||||||
|
the following two tasks. One is for running all the `rspec` tests. The Other is
|
||||||
for running all the `vitest` (JavaScript) tests.
|
for running all the `vitest` (JavaScript) tests.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
@@ -48,4 +49,5 @@ Running `mise run test:all` won't execute its own command, but because it
|
|||||||
depends on all other `test:*` tasks, the tests will get run through those
|
depends on all other `test:*` tasks, the tests will get run through those
|
||||||
dependencies.
|
dependencies.
|
||||||
|
|
||||||
This task naming pattern also allows for calling all tests with `mise run "test:**"`.
|
This task naming pattern also allows for calling all tests with `mise run
|
||||||
|
"test:**"`.
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
# Look In Ruby Version Dotfile
|
|
||||||
|
|
||||||
Newer versions of [`mise`](https://mise.jdx.dev/dev-tools/) specifically only
|
|
||||||
look for tool versions in `mise.toml` as well as the asdf `.tool-versions` file.
|
|
||||||
A lot of Ruby projects use the `.ruby-version` file to indicate the Ruby version
|
|
||||||
of a project. To continue to use the `.ruby-version` file instead of migrating
|
|
||||||
to `mise.toml`, you need to tell `mise` that you prefer to use the idiomatic
|
|
||||||
version file.
|
|
||||||
|
|
||||||
I added the following line to my
|
|
||||||
[`~/.config/mise/config.toml`](https://github.com/jbranchaud/dotfiles/commit/8edeb7a9c53500e89e88b4079cbd1859ebebcbda)
|
|
||||||
file:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
idiomatic_version_file_enable_tools = ["ruby"]
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, whenever `mise` is looking for the specified Ruby version of a project, it
|
|
||||||
will also look for `.ruby-version`.
|
|
||||||
|
|
||||||
Here is a [full list of idomatic version files supported by
|
|
||||||
`mise`](https://mise.jdx.dev/configuration.html#idiomatic-version-files).
|
|
||||||
|
|
||||||
See
|
|
||||||
[`idiomatic_version_file_enable_tools`](https://mise.jdx.dev/configuration/settings.html#idiomatic_version_file_enable_tools)
|
|
||||||
as well as the [Ruby-specific documentation](https://mise.jdx.dev/lang/ruby.html#ruby-version-and-gemfile-support)
|
|
||||||
for more details.
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
# Override Your Project Mise File
|
|
||||||
|
|
||||||
A project I'm working on has a version-controlled `.mise.toml` file in it. Some
|
|
||||||
changes were made to that recently that introduce some env vars that conflict
|
|
||||||
with my setup. If I make edits to that file, then I have a modified version of
|
|
||||||
`.mise.toml` sitting in my Git working copy.
|
|
||||||
|
|
||||||
```
|
|
||||||
# .mise.toml
|
|
||||||
[env]
|
|
||||||
CONFIG_SETTING = "project"
|
|
||||||
```
|
|
||||||
|
|
||||||
Instead, I can rely on the loading precedence rules of `mise` to override those
|
|
||||||
project settings with my individual settings. I can do that with the
|
|
||||||
`.mise.local.toml` file which is played on top of any `mise` configuration from
|
|
||||||
files further down the precedence chain.
|
|
||||||
|
|
||||||
```
|
|
||||||
# .mise.local.toml
|
|
||||||
[env]
|
|
||||||
CONFIG_SETTING = "override"
|
|
||||||
```
|
|
||||||
|
|
||||||
Assuming I have `mise` setup with my shell environment to automatically load in
|
|
||||||
these files, I can now check what takes precedence:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ echo $CONFIG_SETTING
|
|
||||||
override
|
|
||||||
```
|
|
||||||
|
|
||||||
Make sure `.mise.local.toml` is included in the `.gitignore` file to avoid
|
|
||||||
checking in your personal environment overrides.
|
|
||||||
|
|
||||||
To be sure about what files are loaded and in what order, give `mise cfg` a try.
|
|
||||||
I discuss that in more detail in [List The Files Being Loaded By Mise](list-the-files-being-loaded-by-mise.md).
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
# Pick From Tasks Using Interactive Picker
|
|
||||||
|
|
||||||
In [Add Mise Tasks For Common Workflow
|
|
||||||
Commands](https://www.visualmode.dev/add-mise-tasks-for-common-workflow-commands),
|
|
||||||
I wrote about a set of tasks I added as shortcuts for connecting to the `rails console` in various environments.
|
|
||||||
|
|
||||||
```toml
|
|
||||||
# mise.toml
|
|
||||||
[tasks."console:staging"]
|
|
||||||
description = "Open a Rails console on staging"
|
|
||||||
run = "ssh -t my-app-staging dokku run my-app rails console"
|
|
||||||
|
|
||||||
[tasks."console:prod"]
|
|
||||||
description = "Open a Rails console on production"
|
|
||||||
run = "ssh -t my-app-prod dokku run my-app rails console"
|
|
||||||
```
|
|
||||||
|
|
||||||
When a project is configured with multiple `mise` tasks like this, we can invoke
|
|
||||||
`mise run` without any specific arguments and it will prompt you with an
|
|
||||||
interactive picker. The picker will populate with all the tasks like so:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ mise run
|
|
||||||
Tasks
|
|
||||||
Select a task to run
|
|
||||||
❯ console:prod Open a Rails console on production
|
|
||||||
console:staging Open a Rails console on staging
|
|
||||||
/
|
|
||||||
esc clear filter • enter confirm
|
|
||||||
```
|
|
||||||
|
|
||||||
We can navigate between the options with the arrow keys (and if we exit _filter_
|
|
||||||
mode by hitting `esc`, then `j/k` also work to move down and up). While in
|
|
||||||
_filter_ mode, we can type into the prompt which will filter the list of
|
|
||||||
commands down to just the partial matches.
|
|
||||||
|
|
||||||
Once we're targeting the task we want to run, we hit `enter` and the task is
|
|
||||||
executed.
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Search Through Bin Paths For Tool Locations
|
|
||||||
|
|
||||||
The `mise bin-paths` command will list all the bin paths that are managed by
|
|
||||||
`mise`. When you tell `mise` to install a tool, it installs a specific version
|
|
||||||
at a location where its binaries can be made accessible on the system path.
|
|
||||||
|
|
||||||
While `mise ls` is useful for seeing what is installed by `mise` and at what
|
|
||||||
version, the `bin-paths` command can tell you where those tool installations
|
|
||||||
with their binaries are located.
|
|
||||||
|
|
||||||
Combine this with `grep` or `rg` to narrow down the results to tools by a
|
|
||||||
specific name:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ mise bin-paths | rg 'neovim'
|
|
||||||
/Users/lastword/.local/share/mise/installs/npm-neovim/5.4.0/bin
|
|
||||||
/Users/lastword/.local/share/mise/installs/pipx-neovim-remote/2.5.1/bin
|
|
||||||
/Users/lastword/.local/share/mise/installs/neovim/0.11.6/bin
|
|
||||||
```
|
|
||||||
|
|
||||||
I can then look in one of these directories to see the one or more binaries that
|
|
||||||
they include. For instance, here is what is in the `node` bin path:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
❯ ls /Users/lastword/.local/share/mise/installs/node/22.22.0/bin
|
|
||||||
./ ../ claude@ corepack@ node* npm* npx@
|
|
||||||
```
|
|
||||||
|
|
||||||
See `mise bin-paths --help` for more details.
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# Get Idea Of What Is In A JSON Column
|
|
||||||
|
|
||||||
While digging through some data trying to reacquaint myself with the overall
|
|
||||||
schema and data model, I ran into an issue selecting rows from this
|
|
||||||
`content_resource` table. There was so much text packed in to the `"body"`,
|
|
||||||
`"summary"`, and `"description"` key-value pairs of `fields` JSON column that a
|
|
||||||
simple `select * ... limit 3;` was overwhelming the screen with text and table
|
|
||||||
formatting characters (i.e. `+------+-------`).
|
|
||||||
|
|
||||||
I figured the `fields` JSON followed a reliable structure, at least for records
|
|
||||||
of the same `type`. So, let's start by only grabbing the
|
|
||||||
[`json_keys`](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#function_json-keys)
|
|
||||||
so that I can get a sense of the shape of the JSON.
|
|
||||||
|
|
||||||
```sql
|
|
||||||
select id, json_keys(fields)
|
|
||||||
from content_resource
|
|
||||||
where type = 'post'
|
|
||||||
limit 3;
|
|
||||||
|
|
||||||
+-----+-----------------------------------------------------------------------------------------------------------+
|
|
||||||
| id | json_keys(`fields`) |
|
|
||||||
+-----+-----------------------------------------------------------------------------------------------------------+
|
|
||||||
| 1 | ["body", "slug", "state", "title", "summary", "postType", "visibility", "description", "originalLessonId"] |
|
|
||||||
| 2 | ["body", "slug", "state", "title", "summary", "postType", "visibility", "description", "originalLessonId"] |
|
|
||||||
| 3 | ["body", "slug", "state", "title", "summary", "postType", "visibility", "description", "originalLessonId"] |
|
|
||||||
+-----+-----------------------------------------------------------------------------------------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
For the `post` type, I see the same keys for this sampling of rows. Now I have
|
|
||||||
an idea what keys are present and can start digging in further.
|
|
||||||
|
|
||||||
My next query might look something like this:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
select id, fields->'$.slug', fields->'$.title', fields->'$.state'
|
|
||||||
from content_resource
|
|
||||||
where type = 'post'
|
|
||||||
limit 3;
|
|
||||||
```
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# Jump Between Changes In Current File
|
|
||||||
|
|
||||||
With the [gitsigns.nvim plugin](https://github.com/lewis6991/gitsigns.nvim) for
|
|
||||||
Neovim, I get some handy Git-related capabilities like gutter highlighting of
|
|
||||||
additions, deletions, and changes to lines in the current file. These contiguous
|
|
||||||
sections of modification to the versioned state of a file are called hunks.
|
|
||||||
|
|
||||||
Here are two mappings (in Lua) for gitsigns that allow me to jump to the next
|
|
||||||
(`]h`) or previous (`[h`) hunk in the current file.
|
|
||||||
|
|
||||||
```lua
|
|
||||||
---@type LazyKeysSpec[]
|
|
||||||
M.gitsigns_mappings = {
|
|
||||||
|
|
||||||
-- Navigation
|
|
||||||
{
|
|
||||||
']h',
|
|
||||||
function()
|
|
||||||
if vim.wo.diff then
|
|
||||||
vim.cmd.normal { ']c', bang = true }
|
|
||||||
else
|
|
||||||
require('gitsigns').nav_hunk 'next'
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
desc = 'Next Hunk',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
'[h',
|
|
||||||
function()
|
|
||||||
if vim.wo.diff then
|
|
||||||
vim.cmd.normal { '[c', bang = true }
|
|
||||||
else
|
|
||||||
require('gitsigns').nav_hunk 'prev'
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
desc = 'Prev Hunk',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This is particularly useful when I've just opened a big file and I want to jump
|
|
||||||
directly to active changes in that file.
|
|
||||||
|
|
||||||
I got this mapping directly from [Dorian's
|
|
||||||
dotfiles](https://github.com/dkarter/dotfiles).
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# Run nvim With Factory Defaults
|
|
||||||
|
|
||||||
Most of the fun of using Neovim is tailoring it to your exact needs with custom
|
|
||||||
configurations. Your configuration can be made up of environment variables,
|
|
||||||
`init.lua`/`init.vim`, and user directories on the `runtimepath`.
|
|
||||||
|
|
||||||
Perhaps though, you want to load neovim with its "factory defaults". You want
|
|
||||||
to ignore all your custom config and your _shada_ (shared data) file. I wanted
|
|
||||||
to do just that recently to verify that neovim has the `ft-manpage` plugin
|
|
||||||
enabled by default (as opposed to enabled somewhere in the labryinth of my
|
|
||||||
config files).
|
|
||||||
|
|
||||||
The `--clean` flag does just this. It loads built-in plugins, but none of the
|
|
||||||
user defined config.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ nvim --clean
|
|
||||||
```
|
|
||||||
|
|
||||||
This is different than `nvim -u NONE` which excludes all plugins, including
|
|
||||||
built-in ones.
|
|
||||||
|
|
||||||
See `man nvim` and `:help --clean` for more details.
|
|
||||||
-1
Submodule notes deleted from 897184eb02
@@ -1,23 +0,0 @@
|
|||||||
# See What Databases You Have Access To
|
|
||||||
|
|
||||||
Assuming you have the `pscale` CLI installed and you've authenticated with it,
|
|
||||||
you can run the following to view available databases.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ pscale database list
|
|
||||||
NAME KIND CREATED AT UPDATED AT
|
|
||||||
----------- ------- ------------- -------------
|
|
||||||
bookshelf mysql 3 years ago 3 years ago
|
|
||||||
```
|
|
||||||
|
|
||||||
I'm not very active on my personal account. Planetscale is a multi-tenant SaaS
|
|
||||||
though. I can switch from my personal `org` to another team I have access to.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ pscale org switch another-team
|
|
||||||
```
|
|
||||||
|
|
||||||
And then from there I can run `pscale database list` again to see what databases
|
|
||||||
I have access to from this other organization.
|
|
||||||
|
|
||||||
See `pscale database help` and `pscale org help` for more details.
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Avoid Vulnerabilities In New Package Versions
|
|
||||||
|
|
||||||
It seems like every week there is a new supply chain attack where malicious code
|
|
||||||
is embedded in a popular, widely-used OSS package. This week's is
|
|
||||||
[axios](https://www.stepsecurity.io/blog/axios-compromised-on-npm-malicious-versions-drop-remote-access-trojan).
|
|
||||||
|
|
||||||
The [`pnpm` package manager](https://pnpm.io/) has a nice feature that helps
|
|
||||||
avoid installing these vulnerable package versions in the first place.
|
|
||||||
|
|
||||||
> To reduce the risk of installing compromised packages, you can delay the
|
|
||||||
> installation of newly published versions. In most cases, malicious releases
|
|
||||||
> are discovered and removed from the registry within an hour.
|
|
||||||
|
|
||||||
The [`minimumReleaseAge` config option](https://pnpm.io/settings#minimumreleaseage) tells `pnpm` to not install
|
|
||||||
a dependency (including transitive ones) until it has been released for at least
|
|
||||||
that many minutes.
|
|
||||||
|
|
||||||
For instance, if you wanted to set this to 72 hours, then you'd set this option
|
|
||||||
to `4320` minutes like so:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ pnpm config set minimum-release-age 4320 -g
|
|
||||||
```
|
|
||||||
|
|
||||||
The global flag (`-g`) will set that in your global config location, e.g.
|
|
||||||
`$XDG_CONFIG_HOME/pnpm/rc`. You could also add it specifically to your project
|
|
||||||
in the `pnpm-workspace.yaml` file.
|
|
||||||
|
|
||||||
[source](https://bsky.app/profile/styfle.dev/post/3miekuyeyrs2w)
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Check The Size Of Databases In A Cluster
|
|
||||||
|
|
||||||
The `\l` command in `psql` will list all the databases for the server. The
|
|
||||||
field surfaced by this meta-command are:
|
|
||||||
|
|
||||||
- Name
|
|
||||||
- Owner
|
|
||||||
- Encoding
|
|
||||||
- Locale Provider
|
|
||||||
- Collate
|
|
||||||
- Ctype
|
|
||||||
- ICU Locale
|
|
||||||
- ICU Rules
|
|
||||||
- Access privileges
|
|
||||||
|
|
||||||
If we add a `+`, issuing instead `\l+`, we get three additional fields:
|
|
||||||
|
|
||||||
- Size
|
|
||||||
- Tablespace
|
|
||||||
- Description
|
|
||||||
|
|
||||||
The _Size_ column is the human-formatted size of each database.
|
|
||||||
|
|
||||||
Another way to do this is with some SQL querying the underlying record keeping
|
|
||||||
of the server's database.
|
|
||||||
|
|
||||||
```sql
|
|
||||||
select
|
|
||||||
db.datname as db_name,
|
|
||||||
pg_size_pretty(pg_database_size(db.datname)) as db_size
|
|
||||||
from pg_database db
|
|
||||||
order by pg_database_size(db.datname) desc;
|
|
||||||
```
|
|
||||||
|
|
||||||
Credit to [this StackOverflow
|
|
||||||
answer](https://stackoverflow.com/a/18907188/535590) for how to do this with a
|
|
||||||
SQL query.
|
|
||||||
|
|
||||||
[source](https://www.postgresql.org/docs/current/app-psql.html#APP-PSQL-META-COMMAND-LIST)
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# Compute Median Instead Of Average
|
|
||||||
|
|
||||||
One of the first aggregate functions we might use in PostgreSQL, besides `sum`,
|
|
||||||
is `avg`.
|
|
||||||
|
|
||||||
```sql
|
|
||||||
select avg(book_count) as average_books_read
|
|
||||||
from (
|
|
||||||
select users.id, count(books.id) as book_count
|
|
||||||
from users
|
|
||||||
left join books
|
|
||||||
on books.user_id = users.id
|
|
||||||
where books.read_in_year = 2025
|
|
||||||
group by users.id
|
|
||||||
) as user_book_counts;
|
|
||||||
```
|
|
||||||
|
|
||||||
This computes the average of the set of values which sums them all up
|
|
||||||
and divides by the count. The average (maybe you've heard this also called the
|
|
||||||
_mean_) is not always the best way to understand data, especially when there are
|
|
||||||
outliers.
|
|
||||||
|
|
||||||
Instead, we might want to compute the _median_ value of our set of data. There
|
|
||||||
is no easily identifiable `median` aggregate function. Instead, we can use
|
|
||||||
`percentile_cont` with a value of `0.5`. This gets us the 50th percentile of our
|
|
||||||
set of data which is the definition of the _median_.
|
|
||||||
|
|
||||||
```sql
|
|
||||||
select percentile_cont(0.5) within group (
|
|
||||||
order by book_count
|
|
||||||
) as median_books_read
|
|
||||||
from (
|
|
||||||
select users.id, count(books.id) as book_count
|
|
||||||
from users
|
|
||||||
left join books on books.user_id = users.id and books.read_in_year = 2025
|
|
||||||
group by users.id
|
|
||||||
) as user_book_counts;
|
|
||||||
```
|
|
||||||
|
|
||||||
The full syntax for `percentile_cont` is `percentile_cong(precision) within
|
|
||||||
group (order by ...)` because this is an aggregiate that has to work with an
|
|
||||||
ordered-set of data.
|
|
||||||
|
|
||||||
[source](https://www.postgresql.org/docs/current/functions-aggregate.html)
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user