clk

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

View on GitHub

These use cases illustrate clk features through concrete examples. They show common patterns that emerged from real usage and give hints about when clk might be useful.

There are organised by feature though so you can find easily what you are looking for.

what do you want to do?

If you know what you need but not what clk calls it, start here.

creating commands

bash commands

The basics are covered by checking my server. To get more into how to provide parameters to your command, read that one. If your parameters are too complicated to be simply parsed, follow the idea of this use case.

If you find out that your bash command starts to become quite big, the sms sender puts its helpers in a lib folder and loads them with clk_import.

For an argument that is a day, and that you would rather say than spell out, see finding recent documents.

Most of my bash commands start with simple aliases (see aliases). You can read more about this way of thinking in controlling my music. The standard library section covers the built-in helpers available in bash commands.

python commands

The basics of creating python commands are covered here. For more advanced patterns involving dynamic parameters and exposed classes, see dynamic parameters and exposed classes.

dynamic parameters and exposed classes

To create powerful, dynamic command line tools that provide the best completion possible, see this pattern for writing your commands. The cloud provider CLI wrapper puts it to work: it completes the buckets of the account you are on, then the objects of the bucket you just typed.

commands as first order objects

Sometimes, you create commands not only to be called directly, but to be used as basis to build greater commands.

This example of an ethereum local environment dev tool shows how to plug clk commands as parameters in other commands.

ipfs name publish shows how to use clk bash commands to create the completion for other commands.

aliases

Aliases let you create shortcuts, compose commands, and inject environment variables.

For an example of using aliases with templated environment variables to create flexible workflows, see the podcast automation example.

When a global alias and a local command share the same name, the local command wins – see resolution priority. You can also create aliases that point to another project’s root command for cross-project access.

parameters and configuration

persisting options

You can persist command options so you don’t have to repeat them. The cloud provider CLI wrapper shows how to set defaults globally and override them per-project (see also resolution priority).

environment variables

To control how arguments are evaluated through environment variables, see this use case.

Aliases can also use environment variables through templates – see aliases.

When another python program calls clk, like qutebrowser running a userscript, CLK_FORCE_DEPS keeps the libraries of that program out of clk’s way.

values (semantic defaults)

When you need to set the same option on many commands, consider using values to set semantic defaults. This explains the difference between syntactic (parameters) and semantic (values) configuration, with a comparison to git config.

resolution priority

clk resolves names by walking the profiles from the most specific to the least specific one. The first profile that provides the name wins, be it with a command, a custom command or an alias. Hence a local alias wins over a global command, and a local custom command over a global alias.

Several use cases show this in action from different angles:

projects

A project is a directory with a .clk folder. Commands, aliases, and parameters defined inside are scoped to that directory.

The basics of setting up and using a project. See resolution priority for how local project configuration takes precedence over global settings.

cross-project access

When you work on linked but separate projects and get tired of cd-ing between them, you can create aliases that point to the root command of another project. This lets you reach any command from a sibling project without leaving your current directory, using either global or local aliases depending on how much namespace isolation you want.

flows

Flows let you chain commands in a sequence with declared dependencies.

clk does not want to compete with dedicated flow tools like nodered, but it helps having basic flow handling, like when you have a 3D printing flow. The chaotic simulator manager also uses flows to chain a generate → configure → build → simulate pipeline in a standalone tool. The end-to-end example combines flows with parameters, aliases, and projects.

standard library

clk tries hard to provide most of what you need in a generic command line tool.

The bash library (_clk.sh) provides helpers for creating friendly shell commands, like the clk_drop_duplicate of the albums I played lately.

Choices for providing selection in commands. Caching computation results to disk. Fetching and displaying JSON data with download and echo_json. Handling secrets in commands. Cleaning up what a command set up, with clk.atexit.

The clk.lib reference covers what has been documented so far.

introspection and debugging

The clk describe command helps you explore and document your configuration, showing what aliases, parameters, commands, and extensions are available in any profile (global, local, or extension). This is especially useful when resolution priority makes it unclear which level a setting comes from.

When a command feels slow, use --timestamp, --debug, and --profiling to progressively narrow down the bottleneck, from high-level timing down to function-level detail.

extensions

To distribute your commands as installable packages, see how to create your own extensions. Extensions can be shared across projects and follow the same resolution priority rules. They can also be used to override global parameters, making it easy to toggle between sets of settings (e.g. staging vs production). For deeper customisation, see plugins.

plugins

Plugins let you dynamically monkey-patch clk internals (at your own risk).

We describe here how a command can be added along with modifications to clk’s invoke system. This is almost dark magic, so we don’t actually expect you to need this, but it has been useful in a few very specific situations. For most sharing needs, extensions are a better fit.

using clk as a library

If you don’t want to use the clk command line tool, you can roll your own. The example builds a standalone csm tool using clk fork and shows how to grow it with your own customizations: auto-discovered internal commands, flow dependencies to chain them, and a custom launcher mechanism that wraps commands with tools like gdb, valgrind, or perf.

end-to-end example

The backing up documents use case shows how to build a complete backup system starting from a simple command. It ties together many features covered above: creating commands, persisted parameters, flow dependencies, aliases, and per-project configuration.

appendix

Documentation Index

Use cases by file

File Description Auto-detected keywords
3D_printing_flow.md Chaining commands into a workflow sequence using flows clk.overloads.get_command
alias_to_root.md Aliases pointing to the root command of a sibling project, to run its commands without cd-ing into it  
backing_up_documents.md Building a backup system with hierarchical commands, flows, parameters, and per-project configuration  
bash_command_use_option.md Arguments (A:), options (O:), flags (F:), file completion, clk_value, clk_given, clk_true, clk_format_choice clk_format_choice,clk_given,clk_true,clk_value
calling_my_mcp_server.md Getting a Cognito token for my MCP server on AgentCore, with its password kept out of files and parameters (clk secret, keyring, netrc, –ask-secret) clk.get_secret,expose_class
chaotic_simulator_manager.md Building your own standalone CLI tool on top of clk as a library clk.lib.format_options,clk.lib.rm,clk.overloads.option,clk.setup.basic_entry_point,clk.setup.main
checking_my_server.md A bash command that says whether my server answers, with its exit code and its cleaning up clk.lib.check_output,clk.lib.safe_check_output
choices.md Restricting user input to predefined values using Choice types clk.lib.call,clk.lib.check_output,clk.types.DocumentedChoice,clk.types.Suggestion
controlling_a_server_using_an_environment_variable.md Managing server addresses via environment variables and parameters  
controlling_my_music.md Controlling my music player with clk, from a simple alias to a bash command clk_drop_duplicate,clk_true,clk_value
controlling_the_audio.md Recording what an application plays, and tearing down the plumbing with clk.atexit clk.atexit.register
creating_extensions.md Creating and sharing extensions (folders of commands and configuration) clk.lib.check_output,clk.lib.makedirs,clk.lib.move,clk.lib.tempdir,clk.lib.temporary_file,clk_extension_hello
dynamic_parameters_and_exposed_class.md Splitting commands into subcommands with shared config via dynamic parameters and exposed classes expose_class
ethereum_local_environment_dev_tool.md Using clk commands as parameters in other commands (Ethereum dev tool example)  
fetching_and_displaying_json_data.md Fetching JSON from APIs and displaying with syntax highlighting, download, echo_json  
finding_recent_documents.md A bash command with a date argument, read written out or spoken clk.lib.natural_delta,clk.lib.natural_time,clk_value
global_workflow_local_implementation.md Defining workflows globally while letting each project supply its own implementation  
ipfs_name_publish.md Using bash commands to create completion for other commands (IPFS example) clk_list_to_choice,clk_value
lib.md Reference for clk.lib Python helpers (download, echo_json, etc.) clk.lib.check_output,clk.lib.download,clk.lib.extract
podcast_automation.md Aliases with templated environment variables for flexible workflows (podcast download example) clk.lib.createfile,clk.lib.makedirs,clk.lib.move,clk.lib.tempdir,clk.types.Suggestion,clk_value
python_command.md Creating Python commands with clk command create python, click decorators  
reading_later_from_qutebrowser.md Calling clk from a qutebrowser userscript, with CLK_FORCE_DEPS so that the PYTHONPATH of the browser does not break it CLK_FORCE_DEPS
scrapping_the_web.md Caching web-scraped data locally to avoid redundant requests clk.core.cache_disk
self_documentation.md Using clk describe to explore aliases, parameters, commands, and extensions across profiles  
send_sms.md Advanced bash parameter parsing and wrapping termux for SMS sending clk_import,clk_list_to_choice,clk_value
setting_default_values.md Using clk value to set semantic defaults across many commands, parameters vs values  
spotting_slow_code.md Using –timestamp to identify slow parts of a command  
using_a_plugin.md Monkey-patching clk internals with the plugin mechanism  
using_a_project.md Using .clk directories for project-scoped commands and configuration CLK_APPNAME,clk_backup
wrapping_a_cloud_provider_cli.md Persisting command options (–profile, –region) with clk parameters to avoid repetition CLK_P_AWS,clk.types.DynamicChoice,expose_class

Keyword index