Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

shctx

Per-shell context switcher for zsh, bash, and fish. Swap sets of env vars, aliases, and shell functions ("projects") in and out of your current shell, manually or automatically as you cd around.

$ shctx load acme        # env vars, aliases, functions of "acme" are now live
$ cd ~/git/acme-infra    # auto-switches if that dir has a default
$ shctx reset            # back to directory/global defaults

Install

curl -fsSL https://raw.githubusercontent.com/adrsimon/shctx/main/install.sh | sh

This installs the binary to ~/.local/bin, detects your login shell, and adds one line to its rc file inside a # >>> shctx >>> block:

eval "$(shctx init zsh)"     # .zshrc; or init bash in .bashrc
shctx init fish | source     # fish/conf.d/shctx.fish

Set SHCTX_SHELL=zsh|bash|fish before the install to override the detection.

From source: go install github.com/adrsimon/shctx@latest, then add the line for your shell yourself.

Usage

Command Effect
shctx load NAME Load a project into this shell (sticky until reset)
shctx reset Drop the manual load and re-resolve by directory/global default
shctx reload Re-apply the current project after editing its files
shctx current Show the active project
shctx list List all projects
shctx new NAME Scaffold a new project and cd into its directory
shctx rm NAME Delete a project and any defaults pointing to it
shctx default Show the global default and directory mappings
shctx default global NAME Fallback project when no directory matches
shctx default dir NAME Auto-load NAME in the current dir and its subdirs
shctx default global/dir --unset Remove the global default or the current dir mapping

Resolution order: manual load (until reset), then the deepest matching directory default, then the global default, then nothing. Directory matching walks up from $PWD, so a default registered on ~/git/acme also applies in ~/git/acme/front/src. State lives in SHCTX_* env vars, so each terminal has its own independent context.

Projects

A project is a directory under ~/.config/shctx/projects/NAME/:

manifest.toml    # env vars, aliases, PATH entries
functions.zsh    # shell functions, sourced verbatim
functions.bash   # bash variant, optional
functions.fish   # fish variant, optional
functions.sh     # shared fallback (zsh and bash only, fish is not POSIX)
# manifest.toml
path_prepend = ["~/acme/tools/bin"]

[env]
ACME_API = "https://api.acme.dev"

[aliases]
alog = "tail -f /var/log/acme.log"
# functions.zsh
deploy() {
  echo "deploying with $ACME_API"
}

Manifests often hold secrets, so project files are created with 0600 permissions and loose permissions are tightened on load.

Everything a project introduces is torn down when you switch away. Reserved vars (PATH, HOME, EDITOR, PS1, ...) are stripped at load time with a warning. Extend the list via extra_denylist in ~/.config/shctx/config.toml.

Setting PATH wholesale is blocked, but path_prepend and path_append add individual entries on load and remove exactly those entries on switch. A leading ~ is expanded. Don't list a directory that must stay on PATH after the context unloads: teardown removes every occurrence of it.

Development

go test ./...        # unit tests
./scripts/e2e.zsh    # end-to-end test in a real, isolated zsh
./scripts/e2e.bash   # same for bash
./scripts/e2e.fish   # same for fish (needs fish installed)

Releases are built with goreleaser. install.sh pulls shctx_<os>_<arch>.tar.gz from the latest GitHub release and verifies its checksum.

About

Per-shell context switcher for zsh. Swap env vars, aliases, and functions per project, manually or automatically as you cd around.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages