Backend-agnostic installer with Dockerfile-style layer caching and resumable installs.
Project description
anchored-install (ai)
English | 简体中文
A backend-agnostic installer with Dockerfile-style layer caching and resumable installs.
Why "anchored"? Every step that succeeds is dropped as an anchor — a checkpoint you can't drift back past. A failed re-run resumes from the last anchor instead of casting off from chapter one.
Write your install steps as a plain list of shell commands. anchored-install runs
them one by one and caches each step that succeeds. When a run fails, fix
the problem and re-run — already-succeeded steps are skipped and execution
resumes from the first unfinished step, instead of starting over from
chapter one every time.
- ✅ Resumable — a failed reinstall doesn't repeat everything that already worked.
- ✅ No "is it already installed?" checks — the cache is the state.
- ✅ Backend-agnostic — each line is just a command handed to your shell; if the command works on this machine,
aican run it. - ✅ It's a normal script — keep the native extension (
.shon Linux). The#aimarkers are plain comments, sobash install.shruns the exact same file natively, with or withoutai. - ✅ Native & portable — pure Python standard library, zero dependencies.
Tested on Ubuntu with bash. Other shells/platforms are a planned extension.
Install
pip install anchored-install # provides the `ai` command (and `anchored-install`)
# or, from a checkout:
pip install -e .
Requires Python ≥ 3.8 and a POSIX shell (/bin/bash by default).
Quick start
Write a manifest (e.g. install.sh — use the native shell extension) — it's just
commands, one logical line per step, and runs as a normal bash script too:
echo "==> setting up"
export BUILD_DIR=/opt/myapp
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# Multi-line constructs (if / for / heredoc): wrap them in a block.
#ai >>>
if ! command -v node >/dev/null; then
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
fi
#ai <<<
git clone https://github.com/me/myapp . || git pull
npm ci
# This step runs every time, even when everything else is cached.
#ai: always
echo "installed at $(date)"
Run it:
bash install.sh # plain native run, no caching (the #ai markers are comments)
ai run install.sh # execute with caching; cached steps are skipped
ai status install.sh # show which steps are cached vs pending
ai plan install.sh # dry-run: parsed steps + cache keys, nothing executed
ai clean install.sh # forget cached progress for this manifest
If a step fails, ai stops and tells you where. Fix it, run ai run install.sh
again, and it picks up exactly where it left off.
The file keeps its native extension (
.shon Linux) and stays a valid shell script —aiadds caching/resume on top without a special file format.
How it works
Steps
- Each non-comment logical line is one step (
\continues a line). - Comments (
# ...) and blank lines are ignored and never affect the cache — reformatting comments won't bust anything. #ai >>>…#ai <<<collapses several lines into one step (forif/for/heredocs).#ai: alwaysmarks the next step to run on every invocation;#ai: name <label>labels it.
Layer caching (chained hashes)
Each step's cache key folds in the previous step's key:
key[i] = sha256(key[i-1] + normalized(step[i].text))
So editing step i invalidates step i and everything after it, while
steps 0..i-1 stay cached — exactly Docker's layer model. Appending new steps
at the end leaves all earlier steps cached.
Environment carries across steps (and across cached skips)
Steps run in separate shell invocations, yet cd and export still persist:
after each successful step ai snapshots the delta it made to the
environment and working directory (a Docker-like layer). When a cached step is
skipped, its delta is replayed, so later steps still see the right directory and
variables — even ones set by steps that didn't re-run.
Cache lives under ~/.cache/anchored-install/<manifest-id>/ (0700), one snapshot
file per succeeded step.
CLI reference
ai run <file> [--no-cache] [--from N] [--workdir DIR] [--shell PATH] [--no-env-snapshot]
ai status <file>
ai plan <file>
ai clean <file>
--no-cache— ignore existing cache for this run (still records fresh results).--from N— force re-run from step N (1-based) onward.--workdir DIR— starting directory (default: the manifest's own directory).--shell PATH— shell used to run steps (default:$AI_SHELLor/bin/bash).--no-env-snapshot— run each step as an independent subprocess;cd/exportno longer carry across steps.
Caveats & trade-offs
- Success is trusted. If a step's external effect is undone by hand (you
manually removed an installed package),
aistill considers it done. Useai cleanorai run --no-cacheto rebuild. #ai: alwayssteps re-run, but their text is unchanged, so their cache key (and downstream keys) don't change — downstream steps may still be served from cache. Usealwaysfor effects that don't gate later steps (logging, banners).- Env snapshots touch disk. They can contain exported secrets; the cache dir
is created
0700. Use--no-env-snapshotif you'd rather not persist them. - A standalone step whose final command is a failing
&&/||list (e.g.grep x filewith no match) is treated as a failure — append|| trueif that's intentional.
Not yet (planned extensions)
Parallel steps, remote/container backends, Windows/PowerShell, manifest
include and variable templating. The parser/executor are layered to make these
additive.
Contributing
Contributions are welcome! Please read CONTRIBUTING.md to get set up, and note the Code of Conduct. For questions see SUPPORT.md; to report a vulnerability see SECURITY.md. Release notes live in CHANGELOG.md.
License
MIT © OpenGHz — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file anchored_install-0.1.0.tar.gz.
File metadata
- Download URL: anchored_install-0.1.0.tar.gz
- Upload date:
- Size: 25.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d40b94aaa4ad8c13742f4380fd07fa3edfc18ec4a60366b0a6261afbf1ccfd8c
|
|
| MD5 |
ca87c1197f22df714396bdbeab8de30d
|
|
| BLAKE2b-256 |
12bb32061c43b4d8df85fbf8af6bdeb78669196398c3b6e27cfb005b76fc312a
|
File details
Details for the file anchored_install-0.1.0-py3-none-any.whl.
File metadata
- Download URL: anchored_install-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e05a9c7d155b6746b1bccef50b68e8d78a120bc54ea1e3e0a8ccf0c241dc6af
|
|
| MD5 |
8d54f37b8100c09e881e05617b4b922b
|
|
| BLAKE2b-256 |
3c63afdd7b33e0ea3c6a3071bcbfdc47dd851229a1406001ae4c305f16977b2a
|