8 Commands
dxtr edited this page 2026-10-16 22:45:31 +02:00

Commands

stift [OPTION ...] COMMAND [ARGUMENT ...]

stift finds the project's stiftfile in the current directory or the nearest directory above it, and the workspace's stiftwork the same way (see Workspaces).

Command What it does Network
init [NAME] Write a stiftfile for the project here, named by its repository's host and path, or by a URL of it; by default the git remote origin's no
get [--test] URL[@REF] Require a project at a branch, tag or commit, then tidy yes
remove URL Stop requiring a project, then tidy for missing commits
tidy Bring the stiftfile's build list up to date for missing commits
update [URL ...] Move requirements along their branches and tags, then tidy yes
list Print the build list for missing commits
why PROJECT-OR-SYSTEM Print the chains of requirements that bring it in for missing commits
graph Print every requirement for missing commits
download Fetch the build list into the cache yes
vendor Copy the build list into vendor/, which stift then builds from for missing commits
verify [--remote] Check the copies in vendor/, or the cache's checkouts, against their commits; with --remote, the recorded branches and tags too with --remote, or for a tree found nowhere else
setup Print the path of the build list's setup file for missing commits
exec PROGRAM [ARG ...] Run a program with the build list, and exit with its status for missing commits
test [--lisp LISP] [SYSTEM ...] Run test suites, each in a new Lisp for missing commits
build [--lisp LISP] [--compress] [SYSTEM] Build a system as asdf:make does, an executable for one, in a new Lisp; --compress compresses it where the Lisp can (see Building Programs) for missing commits
check [--lisp LISP] Load the .asd files in a Lisp and report the systems the build list lacks for missing commits
work init [DIR ...] Write a stiftwork here, whose members are the projects in DIR ... no
work use DIR ... Make the projects in DIR ... members of the workspace no
work drop DIR ... Stop the projects in DIR ... being members no
work sync Move the members' requirements on each other to the commits their checkouts hold, once pushed yes
clean [--fasls] Empty the cache, or only its fasls no
help Print the help no

get

REF names the commit to require:

  • a branch name, recorded as :branch, at the branch's newest commit;
  • a tag name, recorded as :tag, at the commit the tag points to, the commit beneath it for an annotated tag;
  • refs/heads/NAME or refs/tags/NAME, when a branch and a tag share a name, which stift otherwise refuses;
  • a full or abbreviated commit ID, recorded alone.

Without REF, stift takes the repository's default branch, as git clone does. --test marks a project only the tests need; without it, a project required already keeps its mark. A requirement of the same project replaces the old one in place, and stops being indirect.

Then stift tidies the stiftfile, as stift tidy does, and prints what that changed besides. When a project of the build list requires a later commit of the project, the requirement moves there. Nothing is written when tidying fails, as on requirements that diverge.

A commit can be required only if a branch or tag of its repository reaches it: stift fetches branches and tags, not single commits, which servers need not allow.

remove

stift remove URL removes the project's requirement and tidies the stiftfile. A project the build list still needs, through other projects, stays, as an indirect entry at the commit they require.

tidy

stift tidy reads the stiftfile of each project required, at each commit required, chooses a commit of each project, and writes the stiftfile's build list: an :indirect entry for each project it does not require itself, :test on those only test requirements bring in, no indirect entry nothing needs, and each requirement at the commit chosen. It prints each change, a line each:

added    fakehacker.cc/dxtr/cl-ffi  b7248691986f  branch main  indirect
moved    github.com/someone/foo     1a2b3c4d5e6f..4f0c1a2b3c4d  branch main
removed  example.org/old            9d8e7f6a5b4c  indirect

or The stiftfile is tidy. Choosing Commits has the rules.

update

stift update moves each requirement and replacement along its ref, or, given URLs, only those of the projects named, then tidies:

  • a :branch entry goes to the branch's newest commit;
  • a :tag entry goes to the highest tag of the same major version, among the tags that read as versions, such as v1.2.3 and 1.2.3, whose commit contains the entry's commit;
  • an entry with neither stays where it is: it was pinned on purpose.

It prints each change as tidy does, and for each project that moved, the git log command that shows what changed, in the cache's repository:

moved    github.com/someone/foo  1a2b3c4d5e6f..4f0c1a2b3c4d  branch main
  git -C /home/me/.cache/stift/git/github.com/someone/foo.git log 1a2b3c4d5e6f..4f0c1a2b3c4d

A tag that now points to another commit than the one recorded beside it stops update, as does a branch whose newest commit no longer contains the commit recorded beside it: someone moved the tag, or force-pushed the branch. The message gives both commits, the command that shows the difference, and the stift get URL@REF that accepts the new commit.

list

stift list prints the build list, a project to a line: its identity, its commit, its ref, test when only tests need it, replaced when a :replace chose it, with the repository it comes from, and vendored for a copy in vendor/; or local and the directory; or, for a member of the workspace, workspace and its directory.

download

stift download fetches every commit of the build list the cache lacks, and checks it out, as for working offline or for a CI cache. A project that builds from the copies in its vendor/ needs nothing fetched.

vendor

stift vendor copies each project of the build list into vendor/HOST/PATH/, and records the copies in vendor/projects; while that file exists, and no workspace is in use, stift builds from the copies. It takes the build list from the stiftfile's pins, whatever workspace the project is in. Vendoring describes it.

verify

stift verify checks that each copy in vendor/ holds the files of its commit, modes included, or, without copies, that each checkout in the cache does. With --remote, it also checks over the network that each recorded tag still points to its commit and each recorded branch still contains its commit. It prints what it finds, and exits with 1 when it finds anything. Vendoring describes it.

check

stift check loads the main projects' .asd files in SBCL, or the Lisp --lisp names, with the build list set up, and follows every system's dependencies; Checking Systems describes what it reports. It exits with 1 when a build would fail, and with 0 otherwise.

build

stift build builds a system as asdf:make does, in a new Lisp with the build list, and prints the files it built; Building Programs describes it. It exits with 1 when the build fails, and with 0 otherwise.

work

stift work init, use, drop and sync manage a workspace and move its members' pins on each other; Workspaces describes them. get, update, remove and tidy ignore the workspace.

why

stift why NAME prints the chains of requirements that bring a project into the build list: the shortest through each of the stiftfile's own requirements that leads to it. NAME is a project's identity, URL or name, or the name of a system a project of the build list provides.

graph

stift graph prints every requirement met, as tidy reads them, a line each: the project that requires, with its commit, and the project and commit it requires.

Options

Before the command:

  • -C DIR works as if started in DIR.
  • --offline uses only what the cache holds. A branch or tag cannot be resolved offline, and a commit the cache lacks is an error.
  • --no-workspace leaves the workspace out: the project builds from its pins alone, as CI builds it.
  • -v prints each git command before it runs.
  • --help and --version.

exec takes its options before PROGRAM, and passes everything after it to the program untouched.

Exit status

  • 0 on success; for exec, the program's own status.
  • 1 after an error, whose message on standard error says what went wrong and what to do; for test, when a suite failed; for check, when a build would fail; for verify, when it found anything.
  • 2 when stift does not understand its command line.
  • 130 when Ctrl-C stops stift itself.