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.

creating commands

bash commands

The basics are covered here. 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, read this to find out how to split your code.

Most of my bash commands start with simple aliases (see aliases). You can read more about this way of thinking in here. 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. In case you have some issues, you might want to look at the advanced use cases.

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.

For shortcut aliases that target specific deployment environments, see the environment deployment use case. It also shows how to use get_parameter_source to distinguish between default and explicit values.

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.

To share configuration between a Python group and its bash subcommands through environment variables, see the multi-environment deployment tool. Aliases can also use environment variables through templates – see aliases.

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 looking at the local profile first, then the global profile, then aliases and other resolvers. A local custom command always wins over a global alias with the same name, and a global command always wins over an 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.

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.

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  
alias_to_root.md    
backing_up_documents.md Building a backup system with hierarchical commands, flows, parameters, and per-project configuration CLK__DB,CLKFILENAME,CLKQUALITY,CLK__SOURCE
bash_command.md Creating bash commands, clk_usage, clk_help_handler, source _clk.sh, exit codes, traps  
bash_command_built_in_lib.md Built-in bash helpers: clk_drop_duplicate and other utilities in _clk.sh  
bash_command_from_alias.md Wrapping CLI tools with aliases, then graduating to bash commands  
bash_command_import.md Sharing code between bash commands using clk_import and a lib directory clk_help_handler,clk_import,clk_usage
bash_command_use_option.md Arguments (A:), options (O:), flags (F:), file completion, clk_value, clk_given, clk_true, clk_format_choice A:,CLK__KIND_OF_ANIMAL,CLK__REPEAT,F:,O:,clk_format_choice,clk_given,clk_help_handler,clk_true,clk_usage,clk_value
chaotic_simulator_manager.md Building your own standalone CLI tool on top of clk as a library  
choices.md Restricting user input to predefined values using Choice types  
controlling_a_server_using_an_environment_variable.md Managing server addresses via environment variables and parameters  
creating_extensions.md Creating and sharing extensions (folders of commands and configuration) clk_extension_hello
dealing_with_secrets.md Handling secrets (passwords, tokens) safely in clk commands  
dynamic_parameters_advanced_use_cases.md Advanced dynamic parameters patterns and troubleshooting  
dynamic_parameters_and_exposed_class.md Splitting commands into subcommands with shared config via dynamic parameters and exposed classes  
environment_deployment.md Auto-detecting deployment target from context (e.g. git branch) with explicit overrides, get_parameter_source  
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  
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) A:,clk_help_handler,clk_list_to_choice,clk_usage,clk_value
lib.md Reference for clk.lib Python helpers (download, echo_json, etc.)  
multi_environment_deployment_tool.md Sharing configuration between Python groups and bash subcommands via environment variables  
podcast_automation.md Aliases with templated environment variables for flexible workflows (podcast download example)  
python_command.md Creating Python commands with clk command create python, click decorators  
scrapping_the_web.md Caching web-scraped data locally to avoid redundant requests  
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 A:,CLK____JSON,O:,clk_help_handler,clk_import,clk_list_to_choice,clk_usage,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  
wrapping_a_cloud_provider_cli.md Persisting command options (–profile, –region) with clk parameters to avoid repetition CLK__ARGS,CLKDESTINATION,CLKPATH,CLK__SOURCE

Keyword index