Hunting singleton imports with ripgrep

A little temporary bash function to speed up my quest to atone for my implicit dependency sins.

A budding-stage note

Last tended Dec 7, 2025 originally posted Dec 7, 2025

The Zoo Design Studio code base is open-source, so that means it is open-sins and I don't have to pretend it's perfect. One of its sins that has frustrated our team is our bad habit of importing system dependencies from a @src/lib/singletons.ts file, rather than being explicit about the dependency chain for a given function. Any primer on dependency injection will tell you why this is bad: difficult to test code, seemingly spooky coupling and implicit dependencies, hair-trigger risk of circular dependencies, et cetera.

I've been hunting down these dependencies (tracked in this issue), but all I want to share here is how I've been able to use ripgrep to search for instances of singleton imports in .ts files. I'm trying to match on lines like these:

// src/lib/resetCameraPosition.ts:3
import { engineCommandManager, settingsActor } from '@src/lib/singletons'

// ...and multine import blocks
//src/menu/register.ts:10-11
  settingsActor,
} from '@src/lib/singletons'

I haven't concerned myself with imports into .tsx files, because I am going to migrate all those imports to use a single React Context containing these singleton instances on it that is populated at the root of the app once I complete this effort of injecting all of them anywhere that isn't under the React lifecycle.

I added the following function to my ~/.zshrc file:

# temporary for ZDS refactor work
# Stands for "hunt singleton imports"
hsi() {
  rg -S -U --multiline-dotall "$1.+?src\/lib\/singletons" -g '**/*.ts' $2
}

Here is a breakdown of what this command does:

  1. -S uses "smart casing", which lets me not ignore casing which appears to be rg's default
  2. the -U flag sets rg to match across multiple lines. It's a shorthand for --multiline that I learned from this post
  3. --multiline-dotall includes \n characters in the . wildcard character matching, which is the critical bit that I learned from that post linked above
  4. $1 lets me pass in the singleton export's name as the first argument to my function and splice it into a regular expression searching for that name followed by any characters (including newlines) followed by the name of that singletons file
  5. -g '**/*.ts' matches only on .ts files, excluding .tsx
  6. $2 was a quick and easy way for me to pass in more flags to rg, such as the -l flag that makes it report only file paths of matches if I want

And I use it like so:

> hsi sceneInfra -l

src/menu/register.ts
src/lib/commandBarConfigs/namedViewsConfig.ts
src/lib/routeLoaders.ts
src/lib/resetCameraPosition.ts
src/lib/layout/defaultActionLibrary.ts

This script is prone to false positives, but if I leave off the -l I can inspect those matches to see if they are real imports. It's helped me cruise through a few PRs to kill each of these little sins one at a time, with many more to come. Hope it helps you somehow, happy coding!