clk

A very opinionated framework to ease the creation of command line interfaces

View on GitHub

When you work on linked but separate projects — say a backend API and a frontend app — changes in one often need to be verified in the other. If they live in separate directories, you end up constantly cd-ing back and forth, losing context along the way.

clk projects scope their commands to directories: aliases, parameters and scripts only activate when you’re inside the project. That’s great for isolation, but painful when you need to jump between two or three repos in a single workflow.

The problem

Let’s set up two projects to see the problem in action.

mkdir -p billing-api/.clk
cd billing-api
clk alias set build echo "Building the API"
New local alias for build: echo 'Building the API'
clk alias set test echo "Running API tests"
New local alias for test: echo 'Running API tests'
cd ..
mkdir -p billing-app/.clk
cd billing-app
clk alias set build echo "Building the frontend"
New local alias for build: echo 'Building the frontend'
clk alias set test echo "Running frontend tests"
New local alias for test: echo 'Running frontend tests'

Each project works fine on its own. But the moment you’re inside billing-app and want to rebuild the API, the command isn’t there.

clk build 2>/dev/null
Building the frontend

You only see the frontend’s build. To reach the API, you’d need --project.

clk --project ../billing-api build 2>/dev/null
Building the API

That works, but typing clk --project ../billing-api every time you switch context gets old fast — especially when you’re going back and forth several times in a row.

Global aliases

This is where an alias to the root command helps. You can create a global alias that points to clk itself, with the --project option baked in. Do this once for each project.

cd ..
clk alias set api clk --project ./billing-api
New global alias for api: clk --project ./billing-api
clk alias set app clk --project ./billing-app
New global alias for app: clk --project ./billing-app

Now every command from both projects is available from anywhere, under api and app. No more cd-ing around.

clk api build 2>/dev/null
Building the API
clk app build 2>/dev/null
Building the frontend
clk api test 2>/dev/null
Running API tests
clk app test 2>/dev/null
Running frontend tests

You changed an endpoint in the API? Rebuild it, then run the frontend tests — all without leaving your terminal.

Subgroups and introspection commands work too. You can inspect either project’s aliases at any time.

clk api alias show build 2>/dev/null
build echo Building the API

Local aliases

The global approach is convenient but pollutes your top-level namespace. If you only need cross-project shortcuts when you’re actually working inside one of the projects, local aliases are a cleaner fit. Each project declares its own shortcut to the sibling, and nothing leaks outside.

First, let’s remove the global aliases.

clk alias unset api
Erasing api alias from global settings
clk alias unset app
Erasing app alias from global settings

Now, inside billing-api, create a local alias that points to the frontend.

cd billing-api
clk alias set app clk --project ../billing-app
New local alias for app: clk --project ../billing-app
cd ..

And inside billing-app, create the reverse shortcut.

cd billing-app
clk alias set api clk --project ../billing-api
New local alias for api: clk --project ../billing-api

From inside billing-app, you can now reach the API the same way as before.

clk api build 2>/dev/null
Building the API
clk api test 2>/dev/null
Running API tests
cd ..

And from inside billing-api, you reach the frontend.

cd billing-api
clk app build 2>/dev/null
Building the frontend
clk app test 2>/dev/null
Running frontend tests

The aliases only exist inside their respective projects, so they won’t clutter your global namespace or show up in unrelated directories.