Skip to content
Valet logo

Valet

Valet is a zero dependency tool that helps you build fast, robust, testable and interactive CLI applications in bash.

Read the docs
Build professional CLI tools
Valet gives you the framework and functions required to build awesome tools, effortlessly, in bash. Get everything you expect from a good CLI software (e.g. git, docker…) in a few lines of bash code and YAML configuration.
Turn your scripts into commands
Valet enables you to easily create commands and parses its arguments and/or options automatically. Exceptions are gracefully handled with the error stack printed to the user.
Interactively execute your commands
Find all your commands in a convenient menu with fuzzy finding capabilities.
Fetch and share extensions
You commands are wrapped into extensions that can easily be shared with coworkers or the internet.
Libraries of pure bash functions
Make your scripts more performant and write code faster by using Valet libraries for string manipulation, yaml, interactive prompt, pure bash I/O and more… You can also extend Valet to create and share your own libraries!
Test your commands
Valet standardizes the way you can test your functions and commands with approval tests approach. Run all your tests in a single command and automate them in CI pipelines.
Clear and standardized help
The properties of your commands (arguments, options, etc…) are used to automatically display a user-friendly documentation.
Made for CI/CD automation
Valet only requires bash, has advanced logging capabilities and can be entirely configured through environment variables, which makes it a great candidate as a core framework to build your CI/CD jobs.
Pure bash, zero dependencies
Simply run the install script which copies Valet and you are good to go, you will only ever need bash! Thanks to bash scripting nature, you can highly customize Valet itself by re-declaring functions to your liking.
Lighting fast on any platform
Valet does not use external commands and avoids forking bash sessions, which makes it super fast, even on Windows bash.

Valet in a gist:

  • In Valet, you create new commands that you can invoke with valet my-command.
  • Each command has properties (a description, a list of arguments and options, and so on…).
  • Each command has an associated bash function that is called when the command is invoked and which contains your logic.
  • Commands are packaged in extensions that can easily be shared and downloaded by other Valet users.
  • You define commands, their properties and functions in .sh files under an extension directory.
  • Valet takes care of building (indexing) the commands, which allows you to quickly find them, parse options, arguments, print their help, etc…
  • In commands, you have access to hundreds of utility functions written in pure bash.
  • You can extend these function libraries by creating your own and share them through an extension.

An interactive menu

Calling valet without arguments lets you interactively search commands, read their documentation and execute them:

Demo interactive-menu

Create a command

Command properties are defined using a simple YAML syntax:

showcase-command1.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env bash
: <<"COMMAND_YAML"
command: showcase command1
function: showcaseCommand1
shortDescription: A showcase command that uses arguments and options.
description: |-
  An example of description.

  You can put any text here, it will be wrapped to fit the terminal width.

  You can ⌜highlight⌝ some text as well.
arguments:
- name: first-arg
  description: |-
    First argument.
- name: more...
  description: |-
    Will be an an array of strings.
options:
- name: -o, --option1
  description: |-
    First option.
  noEnvironmentVariable: true
- name: -2, --this-is-option2 <level>
  description: |-
    An option with a value.
  default: two
examples:
- name: showcase command1 -o -2 value1 arg1 more1 more2
  description: |-
    Call command1 with option1, option2 and some arguments.
COMMAND_YAML
function showcaseCommand1() {
  :
}

Clear and standardized help

With valet command --help or valet help command, you get a beautifully formatted help for your command:

Demo show-help

Automatic parsing of arguments and options

Positional arguments and options are automatically parsed by Valet based on your command definition.

They are made available as local variables in your command function.

See the command implementation
showcase-command1.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/env bash
: <<"COMMAND_YAML"
command: showcase command1
function: showcaseCommand1
shortDescription: A showcase command that uses arguments and options.
description: |-
  An example of description.

  You can put any text here, it will be wrapped to fit the terminal width.

  You can ⌜highlight⌝ some text as well.
arguments:
- name: first-arg
  description: |-
    First argument.
- name: more...
  description: |-
    Will be an an array of strings.
options:
- name: -o, --option1
  description: |-
    First option.
  noEnvironmentVariable: true
- name: -2, --this-is-option2 <level>
  description: |-
    An option with a value.
  default: two
examples:
- name: showcase command1 -o -2 value1 arg1 more1 more2
  description: |-
    Call command1 with option1, option2 and some arguments.
COMMAND_YAML
function showcaseCommand1() {
  command::parseArguments "$@"; eval "${REPLY}"
  command::checkParsedResults

  log::info "First argument: ${firstArg}."
  log::info "Option 1: ${option1}."
  log::info "Option 2: ${thisIsOption2}."
  log::info "More: ${more[*]}."

  # example use of a library function
  # Importing the string library (note that we could also do that at the beginning of the script)
  include string
  local myString="<b>My bold text</b>"
  string::extractBetween myString "<b>" "</b>"
  log::info "Extracted text is: ⌜${REPLY}⌝"

  echo "That's it!"
}
Demo parse-args

Advanced logging

Easily log messages and customize their output on the fly.

See the command implementation
test-log.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env bash
: <<"COMMAND_YAML"
command: test-log
function: testLog
shortDescription: A command that only for testing valet logging functions.
description: |-
  A command that only for testing valet logging functions.
COMMAND_YAML
function testLog() {
  log::errorTrace "This is an error trace message which is always displayed."
  log::trace "This is a trace message."
  log::debug "This is a debug message."
  log::info "This is an info message with a super long sentence. Notice how the line gets wrapped and indented correctly to increase readability."
  log::success "This is a success message."
  log::warning "This is a warning message."$'\n'"With a second line."
  log::error "This is an error message, also shows the callstack with debug level."
  if log::isDebugEnabled; then
    log::printString "The debug mode is activated!"
  fi
  if log::isTraceEnabled; then
    log::printString "The trace mode is activated!"
  fi
}
Demo logging

Test framework

Automate tests for your script using the approval tests approach for assertions:

Demo tests

Libraries of functions

Make your scripts more performant and write code faster by using Valet standard libraries for string manipulation, interactive prompt, pure bash I/O and more…

Use one of the 224 functions coming in standard with Valet! Some examples:

script.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
myFunction() {
  include string interactive

  local myString="field1 field2 field3"
  string::getField myString 1 separator=" "
  echo "The field at index 1 is ${REPLY}"

  if interactive::confirm "Do you want to continue?"; then 
    echo "Yes."
  else
    echo "No."
  fi
}

Getting started


Note

These demo were recorded with the asciinema. The color scheme for the terminal is dracula and the font is JetBrainsMono Nerd Font.