Skip to content
juandavidkincaidPublic

About

A context-aware cd for monorepos. Jump to the git root, to a package by its declared name, or to a tag you defined, with tab completion in zsh and bash.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

12 Commits

Folders and files

Repository files navigation

cdx

A context-aware cd for monorepos.

cdx 3                          # up three directories
cdx :repo                      # the git root
cdx +monorepo                  # wherever your pnpm-workspace.yaml lives
cdx @acme/webapp               # that package, from anywhere in the repo
cdx @acme/webapp/src/components

With tab completion for every form.

Why

cd ../../../ is fine until you are five levels deep in a monorepo and the thing you want is a sibling package. cdx resolves short expressions against where you are standing and against tags you define, then takes you there.

It does not do frecency ranking or fuzzy history. zoxide already does that well, and the two coexist happily.

Install

./install.sh

Copies the binary to ~/.local/bin and adds one line to your shell rc inside a marker-delimited block:

eval "$(cdx init zsh)"

./uninstall.sh reverses it.

The five forms

An argument is an anchor plus an optional path suffix. The suffix is appended once the anchor resolves, so cdx @acme/webapp/src lands in that package's src.

Numeric

cdx 3          # ../../..
cdx 3/packages # ../../../packages

The cdup replacement.

System tags

Built in, always available, never configurable.

tag resolves to
:root /
:user your home directory
:repo nearest ancestor containing .git

Config tags

Tags you define, in a cdx.conf:

{
  "tags": {
    "logs": "/var/log",
    "api": "./apps/api",
    "monorepo": { "findUp": "pnpm-workspace.yaml" }
  }
}
cdx +api
cdx +monorepo

Three ways to write a destination:

  • Absolute path (starts with /), used as-is.
  • Relative path, resolved against the directory holding that cdx.conf, never against your cwd. A tag defined at the repo root means the same thing everywhere beneath it.
  • findUp, which searches upward from your cwd for the named file and lands on the directory containing it. The search stops at the cdx.conf that declared the tag, so a tag can never take you outside the tree its config governs.

Packages

cdx @acme/webapp

Searches from the git root for a package whose declared name matches, reading package.json, go.mod, and Cargo.toml. Directory names are not matched; the name in the manifest is the name.

Gitignored paths are skipped, and the search goes at most 5 levels below the git root.

Why : and +

Because # and $ do not survive the shell. # starts a comment and $name is parameter expansion, so cdx #repo and cdx $tag reach the binary as zero arguments, in zsh and bash alike. : and + pass through untouched, as does @.

Anything else

cdx src
cdx /tmp

Falls through to ordinary path behavior, so cdx is a drop-in replacement for cd.

Configuration

cdx walks up from your cwd collecting every cdx.conf it finds, stopping at $HOME. All of them merge, with the nearest file winning on conflicts.

So a ~/cdx.conf gives you tags that work everywhere, a repo-root cdx.conf adds repo-specific ones, and a leaf cdx.conf can override a tag for one subtree. Each tag keeps resolving relative to its own config file, so merging never changes what a relative path means.

How it works

A compiled binary cannot change its parent shell's directory, so cdx is a binary plus a shell function. The binary prints a path; the function runs cd:

cdx() { local d; d="$(command cdx resolve "$@")" && cd "$d"; }

If resolution fails, nothing is printed, the exit code is nonzero, and you stay exactly where you were.

There is no cache and no background process. Each invocation asks git for the repository's non-ignored manifests and reads them. That means a package you added a second ago completes correctly, with no daemon to restart and no stale index to clear.

Requirements

  • git
  • Go 1.22+ to build

Building

go build ./...
go test ./...

About

A context-aware cd for monorepos. Jump to the git root, to a package by its declared name, or to a tag you defined, with tab completion in zsh and bash.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages