caml

Build CLI apps from a declarative caml.yaml file.

caml turns well-documented YAML tasks into a runnable CLI. Inspired by make and just, but YAML-driven.

Install

gem install caml

Or in a Gemfile:

gem 'caml'

Quickstart

caml init                # scaffold a starter caml.yaml
caml                     # list tasks
caml hello               # run the starter task

Tasks

A task has a name, a desc, and an execute shell command:

test:
  desc: Run the test suite
  execute: bundle exec rspec

caml and caml help list every task with its description.

Multi-line execute

Pass a list to run multiple steps. Steps run with fail-fast semantics — the first non-zero exit aborts:

setup:
  desc: Install and migrate
  execute:
    - bundle install
    - bin/rails db:migrate

Arguments

Positional arguments substitute into the execute template via {{name}}. Values are shell-escaped:

greet:
  desc: Say hello to someone
  args:
    name:
      desc: Person to greet
      type: string
  execute: echo Hello, {{name}}!
caml greet world
# Hello, world!

Options

Flags with type, optional aliases, default value, and an optional override execute:

build:
  desc: Build the project
  opts:
    target:
      type: string
      default: dist
      aliases:
        - t
      desc: Output directory
    verbose:
      type: boolean
      aliases:
        - v
      desc: Print verbose output
  execute: make build TARGET={{target}}
caml build --target release
caml build -t release -v

Option-driven dispatch

When a boolean option has its own execute, that command runs instead of the task's default:

start:
  desc: Start the app
  opts:
    background:
      type: boolean
      aliases:
        - b
      desc: Run as a daemon
      execute: app start --daemon
  execute: app start
caml start                # app start
caml start --background   # app start --daemon

Aliases

Add shortcut names for a task:

test:
  desc: Run the test suite
  aliases:
    - t
  execute: bundle exec rspec
caml t   # same as caml test

Dependencies

A task can declare prerequisites with needs. Deps run in declared order, each at most once per invocation; failures abort the run:

test:
  desc: Run tests
  execute: bundle exec rspec

lint:
  desc: Check style
  execute: bundle exec rubocop

ci:
  desc: Lint and test
  needs:
    - lint
    - test
caml ci   # runs lint, then test

A task with only needs: and no execute is a pure orchestrator — useful for grouping.

Discovery

caml walks up from the current directory to find a caml.yaml, just like git. You can run it from any subdirectory of your project.

Built-in commands

Command Description
caml init Scaffold a starter caml.yaml
caml --version Print the installed version
caml help [cmd] Show help for a specific task (its args and opts)

License

MIT — see LICENSE.