Skip to content

spur 0.1.0

Choose a tag to compare

@Danrley-Ruan-Saquetti Danrley-Ruan-Saquetti released this 22 Sep 14:37
· 62 commits to master since this release

0.1.0 - 2026-09-22

First release. spur reads a Spurfile, lists the tasks and runs one per invocation in a single shell. The whole program is one file that depends on sh and awk: no build step and no runtime to install.

The scope is deliberate: spur runs tasks, it does not build software — no dependency graph, no timestamp rebuilds, no pattern rules. It needs a POSIX shell, so on Windows it runs under Git Bash, MSYS2, WSL or Cygwin. The trade-offs that follow are listed in the README under What it costs.

Added

  • The Spurfile language: a line matching ^[A-Za-z0-9_.-]+: opens a task, ## text in the header documents it for --list, and the indented body is
    dedented before it runs, so if, for and heredocs keep their relative shape. Everything before the first task is the preamble, injected at the top of every task that runs.
  • One shell for the whole body, with set -e on: cd persists, variables persist, and stdin stays free, so interactive tasks work.
  • A body that reaches the shell byte for byte. The runner expands nothing, so $IMAGE, $(date), ${x:-y} and $$ arrive intact and there is no template layer to escape.
  • Positional passthrough: spur test -k login -vv hands -k login -vv to the body as "$@". The first word that does not start with - is the task name; everything after it belongs to the task.
  • Spurfile discovery: Spurfile, then spurfile, in the current directory and then upwards to /. Every task runs in the directory that holds the file in use.
  • Chained calls: the assembled script injects a spur function pointing at the runner itself. A recursion guard over SPUR_STACK exits 68, while repeated non-recursive calls are allowed.
  • Runner flags: -f FILE, -C DIR, -l/--list, -n (print the assembled script instead of running it), -x (trace with PS4='$ ', after the preamble), -h/--help and -v/--version. Short flags cannot be grouped.
  • Exit codes in the sysexits range, so they never collide with a task's own, which is propagated unchanged: 64 usage, 65 malformed Spurfile, 66 Spurfile not found, 67 unknown task, 68 recursion.
  • Exported environment: SPUR_BIN, SPUR_ROOT, SPUR_INVOCATION_DIR, SPUR_TASK and SPUR_STACK.
  • Shell diagnostics labelled spur <task>: line N: ..., from $0 on the single sh -c that runs the task.
  • Documentation: README.md as the user-facing contract (the language, the CLI, the exit codes, the make → spur mapping and the known limitations), CONTRIBUTING.md for the testing rules, and an MIT LICENSE.
  • A behavior suite of 48 cases under tests/, run by a dependency-free harness, plus CI running shellcheck -s sh and the suite under sh, dash, bash and busybox ash. Green on this tag.

Install

curl -fsSL https://raw.githubusercontent.com/esliph/spur/v0.1.0/spur \
  -o ~/.local/bin/spur && chmod +x ~/.local/bin/spur

Or download spur from the assets below and chmod +x it. Or vendor it: copy the file into your repository and commit it, and anyone who clones runs ./spur test with nothing installed.