Portable backup, sync, and migration for AI agents.
License: MIT ALF Spec: 1.0.0-rc.2
This repository contains the ALF core library and framework-specific adapters for the agent-life project. It produces the alf command-line tool — a single binary that can export, import, and sync AI agent data across frameworks using the Agent Life Format (ALF).
agent-life provides backup, sync, and migration for AI agents. An agent accumulates memory, identity, credentials, and workspace files over months of use — all locked inside one framework's proprietary storage. agent-life captures that data in a neutral, open format (ALF) and enables disaster recovery, incremental cloud sync, and cross-framework migration.
Main repositories:
| Repository | Description | Visibility |
|---|---|---|
| agent-life-data-format | ALF specification and JSON schemas | Public |
| agent-life-adapters (this repo) | Core library, CLI tool, and framework adapters | Public |
| agent-life-service | Hosted sync API, storage, Lambdas | Public |
| agent-life-web | Marketing site and hosted CLI / format docs | Public |
┌──────────────────────────────────┐
│ This Repository │
│ │
┌──────────────┐ │ ┌──────────┐ ┌─────────────┐ │
│ OpenClaw │─export──▶│ │ adapter- │──▶│ │ │ ┌──────────────┐
│ Workspace │◀─import──│ │ openclaw │ │ alf-core │ │ │ Sync API │
└──────────────┘ │ └──────────┘ │ (library) │ │ │ (agent-life │
│ │ │──┼──▶│ -service) │
┌──────────────┐ │ ┌──────────┐ │ read/write │ │ └──────┬───────┘
│ ZeroClaw │─export──▶│ │ adapter- │──▶│ .alf files │ │ │
│ Workspace │◀─import──│ │ zeroclaw │ │ │ │ ┌──────▼───────┐
└──────────────┘ │ └──────────┘ └─────────────┘ │ │ Data Store │
│ │ │ └──────────────┘
│ ┌─────▼──────┐ │
│ │ alf-cli │ │
│ │ (binary) │ │
│ └────────────┘ │
└──────────────────────────────────┘
The alf-core crate is also imported by agent-life-service as a git dependency. The service uses it to validate incoming snapshots, parse manifests, extract memory records for indexing, and apply deltas during compaction. One library, two compilation targets: native binary (CLI) and Lambda ARM64 (service).
agent-life-adapters/
├── Cargo.toml # Workspace root
├── LICENSE # MIT
├── README.md
│
├── alf-core/ # Shared library crate
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs # Public API surface
│ ├── adapter.rs # Adapter trait (export/import interface)
│ ├── archive.rs # ZIP archive handling; AlfReader, AlfWriter (.alf is a ZIP)
│ ├── manifest.rs # Manifest parsing, generation, attachment index
│ ├── memory.rs # MemoryRecord types, JSONL partition I/O
│ ├── identity.rs # Identity layer types (structured + prose)
│ ├── principals.rs # Principal and communication preference types
│ ├── credentials.rs # CredentialRecord, EncryptionMetadata (types; crypto in crypto/)
│ ├── crypto/ # VaultKey, AEAD encrypt/decrypt, VaultPayload envelope
│ ├── partition.rs # Time-based partition assignment, PartitionReader/Writer
│ ├── delta.rs # Delta computation and application
│ ├── rebuild.rs # Merge snapshot + deltas for restore/compaction
│ ├── restore.rs # High-level restore helpers (used by CLI / tooling)
│ └── validation.rs # Schema validation; lenient vs --strict-crypto for credentials
│
├── alf-cli/ # CLI binary crate
│ ├── Cargo.toml
│ └── src/
│ ├── main.rs # Entrypoint (clap argument parsing, --human flag)
│ ├── adapter.rs # Runtime adapter selection and dispatch
│ ├── api_client.rs # Sync service API client
│ ├── config.rs # ~/.alf/config.toml management
│ ├── context.rs # Runtime context for help (config + state summary)
│ ├── output.rs # JSON-first output helpers (json, progress, human_mode)
│ ├── state.rs # ~/.alf/state/{agent_id}.toml sync state
│ ├── vault_key.rs # Resolve vault key from flags / env / default paths
│ └── commands/
│ ├── mod.rs # Command dispatch
│ ├── add.rs # alf add — track an arbitrary workspace file for sync
│ ├── check.rs # alf check — environment diagnostics, workspace auto-discovery
│ ├── export.rs # alf export — dispatch to runtime adapter
│ ├── help.rs # alf help — overview, status, files, troubleshoot
│ ├── import.rs # alf import — dispatch to runtime adapter
│ ├── login.rs # alf login — store API key in ~/.alf/config.toml
│ ├── purge.rs # alf purge — delete cloud agent + local state pointers
│ ├── restore.rs # alf restore — download and import
│ ├── sync.rs # alf sync — push deltas/snapshots to sync service API
│ ├── validate.rs # alf validate — schema validation (--strict-crypto optional)
│ └── vault.rs # alf vault — keygen, add, encrypt, decrypt, list, delete
│
├── adapter-openclaw/ # OpenClaw adapter crate (library)
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs # Adapter trait implementation
│ ├── export.rs # Read OpenClaw workspace → ALF archive
│ ├── import.rs # ALF archive → write OpenClaw workspace
│ ├── memory_parser.rs # Parse MEMORY.md and daily logs → MemoryRecords
│ ├── identity_parser.rs # Parse SOUL.md, IDENTITY.md → Identity
│ └── principals_parser.rs # Parse USER.md → Principals
│
├── adapter-zeroclaw/ # ZeroClaw adapter crate (library)
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs # Adapter trait implementation
│ ├── export.rs # Read ZeroClaw workspace (SQLite + markdown) → ALF archive
│ ├── import.rs # ALF archive → write ZeroClaw workspace
│ ├── config_parser.rs # Parse config.toml (memory backend, identity, credential hints)
│ ├── identity_parser.rs # Parse identity (AIEOS/OpenClaw formats) → ALF Identity
│ ├── principals_parser.rs # Parse USER.md → Principals
│ ├── markdown_parser.rs # Parse memory markdown files → MemoryRecords
│ └── sqlite_extractor.rs # Read memories table + embeddings → MemoryRecords
│
├── adapter-hermes/ # Hermes (Nous Research) adapter crate (library)
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs # Adapter trait implementation
│ ├── export.rs # Read HERMES_HOME → ALF archive (allowlisted raw/)
│ ├── import.rs # ALF archive → write HERMES_HOME (+ rebuild state.db)
│ ├── config_parser.rs # Parse config.yaml (personalities, system prompt) + redact
│ ├── curated_parser.rs # Parse memories/MEMORY.md (§-entries) → MemoryRecords
│ ├── identity_parser.rs # SOUL.md + config personalities → Identity (prose)
│ ├── principals_parser.rs # memories/USER.md → Principals
│ ├── session_extractor.rs # Read state.db sessions → episodic MemoryRecords
│ ├── session_rebuilder.rs # Rebuild state.db from records on import (FTS via triggers)
│ └── skills.rs # Non-bundled skills → ALF artifacts (attachments.json)
│
├── scripts/
│ ├── install.sh # Quick-install script (curl | sh)
│ ├── test_install.sh # Install test runner (Docker + native)
│ ├── test_install/ # Install test infrastructure
│ │ ├── mock_server.py # HTTP mock server (simulates GitHub Releases)
│ │ ├── run_tests.sh # Core test cases (35+ tests)
│ │ ├── Dockerfile.ubuntu # Ubuntu 24.04 test image
│ │ ├── Dockerfile.alpine # Alpine 3.19 test image
│ │ ├── Dockerfile.debian # Debian 12 test image
│ │ ├── Dockerfile.alpine-nochecksum # Alpine with no sha256sum/shasum
│ │ └── fixtures/ # Fake binaries + SHA256 checksums
│ └── ... # generate_synthetic_data.py, generate_fixtures.sh, etc.
│
├── .github/
│ └── workflows/
│ ├── build.yml # Build alf CLI for Linux (x64, arm64), macOS (x64, arm64), Windows (x64)
│ ├── test-install.yml # Install script tests (Linux Docker + macOS native)
│ ├── lifecycle-nollm.yml # Lifecycle harness, no-LLM/no-backend tier (zero secrets)
│ └── release.yml # Build, release, upload to S3 with SHA256 checksums
│
└── tests/ # Top-level integration tests (if present)
The foundation crate that all other components depend on. Provides:
Type system. Rust structs with serde Serialize/Deserialize for every ALF type defined in the specification:
Manifest— archive metadata, format version, agent identity reference, layer checksums, partition index (§4.3)MemoryRecord— typed memory entries with content, temporal metadata, entities, tags, source provenance, token counts, relational links (§3.1)Identity— agent identity with structured fields and prose blocks, capability portability annotations, personality traits, AIEOS extensions passthrough (§3.2)Principal— user and stakeholder profiles with communication preferences and work context (§3.3)CredentialRecord— encrypted credential entries with service metadata, capability grants, rotation tracking, optionaldescription,CredentialType::Account(§3.4)Attachment— artifact index entries with three-tier classification: included, included (artifact), referenced-only (§3.1.9)DeltaManifest— incremental sync bundle metadata with base sequence, changed layers, partition-level operations (§4.3.1)
ALF archive I/O. Read and write .alf files (ZIP archives with a defined internal structure):
AlfWriter— streaming builder API. Create manifest, add memory records to time-based partitions (JSONL), set identity/principals/credentials (JSON), add artifact files, produce a valid ZIP.AlfReader— open an.alffile, parse the manifest, iterate memory partitions as a streaming JSONL reader (memory-efficient for large archives), read identity/principals/credentials, extract artifacts.DeltaWriter/DeltaReader— same interface for.alf-deltaincremental bundles.
Memory partitioning. Implements the time-based quarterly partitioning scheme (§4.1.1):
- Assigns records to partitions based on
observed_attimestamp - Tracks partition seal status (sealed partitions are immutable)
- Generates partition filenames (
memory/2025-Q4.jsonl,memory/2026-Q1.jsonl)
Artifact tier classification. Implements the three-tier workspace artifact model (§3.1.9):
- Tier 1 (always included): raw source files, small config files →
raw/{runtime}/ - Tier 2 (included if under threshold): workspace artifacts →
artifacts/ - Tier 3 (reference only): large generated files → reference in attachment index, not in archive
- Configurable
artifact_size_threshold(default: 10 MB)
Schema validation. Validates ALF archives against the JSON schemas in agent-life-data-format:
- Validates each layer (manifest, memory records, identity, principals, credentials, attachments)
- Warns on unknown enum values without rejecting (forward compatibility per §8.2)
- Credential crypto: lenient mode warns on legacy
algorithm: "none"rows; callers (CLI:alf validate --strict-crypto) can require real ciphertext - Reports validation errors with JSON path and human-readable messages
Delta computation. Computes and applies incremental deltas:
- Diff two snapshots to produce a delta (for adapters that don't track changes natively)
- Apply a sequence of deltas to a snapshot to produce an updated snapshot (for compaction)
- Partition-level operations: add records, seal partition, update identity/principals/credentials
A single binary (alf) that provides all end-user operations. Built with clap for argument parsing.
JSON-first output. All commands output structured JSON to stdout by default. Progress messages go to stderr. This makes the CLI directly consumable by agents and scripts — pipe stdout to jq, parse it in Python, or feed it to another tool. Use the global --human flag (or set ALF_HUMAN=1) to switch stdout back to human-readable colored text.
Global flag:
alf [--human] <command> [args...]
Commands:
alf check --runtime <runtime> [--workspace <path>]
Pre-flight environment diagnostic. Discovers the agent workspace (auto-detects from ~/.openclaw/openclaw.json if -w is omitted), checks for expected resources (SOUL.md, memory files, etc.), verifies ALF config and API key, and reports readiness to sync. Outputs a structured CheckResult with issue codes and per-issue suggestion text (guidance, not a guaranteed shell command). This is the recommended first command for agents to run.
alf export --runtime <runtime> --workspace <path> [--output <path>]
Export an agent's complete state from a framework workspace to an .alf file. The runtime flag selects the adapter (openclaw, zeroclaw, hermes). Reads native files, translates to ALF, validates against schemas, and writes the archive. Layer 4 is the agent's ALF vault (~/.alf/vault/credentials.json) copied in verbatim — already ciphertext, so export reads no vault key. See docs/vault-key-management.md.
alf add <path> --runtime <runtime> --workspace <path>
Track an arbitrary workspace file so sync includes it. ALF never auto-walks a workspace — the agent opts each file in explicitly. The tracked set is recorded in <workspace>/.alf-include.json (itself synced, so it travels on restore); tracked files round-trip byte-identically under raw/openclaw/. Deleting a tracked file and running alf sync prunes it and appends a note to .alf-sync-log.md.
alf import --runtime <runtime> --workspace <path> <alf-file> [--vault-key-file …]
Import an .alf file into a framework workspace. Creates or populates the workspace with memory, identity, principals, and artifacts translated to the target runtime's native format. Layer 4 vault records are written back to ~/.alf/vault/credentials.json (still encrypted); a vault key is needed only to decrypt a legacy archive's runtime-keystore credentials.
alf sync --runtime <runtime> --workspace <path> [--recover] [--force-first-sync]
Incremental sync to the cloud. Computes a delta since the last sync point (or uploads a full snapshot on first sync), pushes it to the agent-life service API. Stores the last-synced sequence number locally in ~/.alf/state/{agent_id}.toml. Sync carries the agent's ALF vault into the snapshot verbatim and takes no vault-key flags. Credential (Layer 4) changes ride deltas (diffed by id); a change to a file tracked via alf add instead triggers a fresh snapshot (a non-destructive rollover), since opaque files can't ride a delta. See docs/how_alf_syncs.md §6.1.
alf restore --runtime <runtime> --workspace <path> [-a|--agent <agent-id>] [--vault-key-file …]
Download the latest snapshot (plus any uncompacted deltas) from the service and import into a workspace. If --agent is omitted and exactly one agent is tracked in ~/.alf/state/, that agent is used. Used for disaster recovery or migration to a new machine. Same vault behavior as alf import.
alf vault <subcommand> …
Layer 4 vault tooling: keygen, add, encrypt, decrypt, list, delete. The vault is ~/.alf/vault/credentials.json. See docs/cli-reference.md and alf vault --help.
alf purge --runtime <runtime> --workspace <path> [-a|--agent <agent-id>]
Delete the cloud agent registration and local sync state files for that agent (does not delete workspace content by default beyond what restore/import wrote).
alf help [topic]
Show explorable help. With no topic: overview (commands, where files live, current status). Topics: status, files, troubleshoot, or a command name (export, import, sync, restore, purge, validate, vault, login, check) for delegated --help. The hidden --json flag on alf help is a deprecated no-op (JSON is the default for status).
alf login [-k|--key <api-key>]
Store an API key for the agent-life service in ~/.alf/config.toml. Interactive login (device flow) is not implemented yet — run alf login --key <api-key> (get a key at https://agent-life.ai/settings/api-keys).
alf validate <alf-file> [--strict-crypto]
Validate an .alf or .alf-delta file against the ALF JSON schemas. Reports errors and warnings. Pass --strict-crypto in CI when every credential record must carry real ciphertext (legacy algorithm: "none" becomes an error).
Configuration (~/.alf/config.toml):
[service]
api_url = "https://api.agent-life.ai"
api_key = "alf_..."
[defaults]
runtime = "openclaw" # used when -r is omitted (default: openclaw)
workspace = "/home/user/.openclaw/workspace" # used when -w is omitted-r/-w are optional on every command — when omitted they fall back to these [defaults]
(precedence: CLI flag › [defaults] › openclaw for runtime; workspace errors if neither is set).
Set ALF_HOME to relocate alf's whole tree off $HOME: when set, ~/.alf (config, sync
state, vault) and ~/.openclaw resolve under $ALF_HOME (e.g. ALF_HOME=/data → config at
/data/.alf/config.toml). Unset falls back to $HOME (%USERPROFILE% on Windows) — the
original behavior. Useful when an agent process rewrites $HOME.
Sync state is stored per agent in ~/.alf/state/{agent_id}.toml (last_synced_sequence, last_synced_at) and snapshot files as ~/.alf/state/{agent_id}-snapshot.alf. See alf help files for the full layout, and docs/how_alf_syncs.md for the canonical reference on the sync data model, branch logic, ephemeral-runtime corner cases (E1–E8), and the operator runbook for recovery (alf sync --recover).
Translates between OpenClaw's native file-based workspace and the ALF format.
Export reads:
| OpenClaw File | ALF Layer | Mapping |
|---|---|---|
SOUL.md |
Identity (§3.2) | Preserved as persona prose; not the canonical display name source |
IDENTITY.md |
Identity (§3.2) | Name / **Name:** sets the canonical display name; rest merged as prose |
AGENTS.md |
Identity — sub-agent roster (§3.2.4) | Each agent entry → sub-agent with name, role, delegation scope |
USER.md |
Principals (§3.3) | Parsed into primary principal with profile, preferences, work context |
MEMORY.md |
Memory records (§3.1) | Each entry → MemoryRecord with type classification, entity extraction |
logs/daily/*.md |
Memory records (§3.1) | Daily log entries → memory records with observed_at from filename |
| Workspace files | Artifacts (§3.1.9) | Classified into tiers; Tier 1–2 included in archive, Tier 3 referenced |
auth-profiles.json (and related) |
Credentials (§3.4) | credential_map: with a resolved vault key, API keys / tokens are encrypted into CredentialRecord payloads; without a key, metadata-only rows (<not-exported>) |
Import writes the reverse mapping: ALF layers → OpenClaw workspace files.
Raw source preservation. The original OpenClaw files are always included verbatim in the archive under raw/openclaw/. This ensures zero information loss even if the structured parsing misses nuances — the raw files can always be re-parsed by a future, improved adapter.
Translates between ZeroClaw's SQLite-based storage, markdown memory files, and config and the ALF format.
Export reads:
| ZeroClaw Source | ALF Layer | Mapping |
|---|---|---|
SQLite memories table |
Memory records (§3.1) | sqlite_extractor: type mapping from ZeroClaw types → ALF memory_type, embeddings, temporal metadata |
Memory markdown files (e.g. memory/, archive/) |
Memory records (§3.1) | markdown_parser: sections → MemoryRecords with classification (session, daily, generic), observed_at from filenames |
config.toml |
Identity (§3.2) | Agent name, role, capabilities; config_parser + identity_parser (AIEOS or OpenClaw format) |
config.toml + auth_profiles.json (secrets) |
Credentials (§3.4) | credential_map: with a resolved vault key, secrets are encrypted; without a key, metadata-only placeholders |
AIEOS extensions. ZeroClaw uses the AIEOS identity schema, which defines fields not present in ALF's core schema (e.g., emotional_model, reasoning_style). These are preserved in the aieos_extensions passthrough object, ensuring no information loss during round-trip. Promoted fields (name, role, capabilities) are mapped to ALF's first-class fields for cross-runtime compatibility.
Raw source preservation. The original SQLite database file is included under raw/zeroclaw/ for lossless recovery.
Translates between a Hermes (Nous Research) profile (HERMES_HOME, default ~/.hermes; named profiles under ~/.hermes/profiles/<name>/) and the ALF format. One profile = one agent = one .alf.
Export reads:
| Hermes source | ALF mapping | Notes |
|---|---|---|
memories/MEMORY.md (§-entries) |
Memory records (§3.1) | One semantic record per entry; content-derived UUIDv5 id, stable under Hermes's constant rewriting |
state.db (sessions / messages / FTS5) |
Memory records (§3.1) | One episodic record per session; the full structured session in raw_source_format for lossless rebuild |
SOUL.md + config.yaml personalities |
Identity (§3.2) | Prose identity (identity.prose); no structured fields fabricated |
memories/USER.md |
Principals (§3.3) | Primary human principal — prose + best-effort structured fields |
skills/<category>/<name>/** |
Artifacts (§3.1.9) | Non-bundled skills only (.bundled_manifest); SKILL.md + small assets in artifacts/, large assets by reference |
~/.alf/vault |
Credentials (§3.4) | The shared ALF vault, packed verbatim; ~/.hermes/.env keys are detected and flagged for vaulting (D4) |
Import restores the verbatim raw/hermes/ text and rebuilds state.db from the session records — replaying the source database's own schema and letting Hermes's triggers repopulate the FTS5 + trigram indexes, so a real Hermes opens the result. Project-local context files (AGENTS.md) are captured only when tracked with alf add --external (§3.2 operating instructions).
Raw source preservation. raw/hermes/ holds the durable text/config (SOUL.md, memories/*.md, redacted config.yaml, non-bundled skills/, cron). The state.db binary (rebuilt from records), .env (secrets live encrypted in Layer 4), and admin dirs (checkpoints/, state-snapshots/, backups/, logs/) are excluded.
The alf binary is compiled for 5 platform targets and attached to GitHub Releases:
| Platform | Target Triple | Binary Name |
|---|---|---|
| Linux x86_64 | x86_64-unknown-linux-musl |
alf-linux-amd64 |
| Linux ARM64 | aarch64-unknown-linux-musl |
alf-linux-arm64 |
| macOS ARM64 | aarch64-apple-darwin |
alf-darwin-arm64 |
| macOS x86_64 | x86_64-apple-darwin |
alf-darwin-amd64 |
| Windows x86_64 | x86_64-pc-windows-msvc |
alf-windows-amd64.exe |
Quick install:
curl -sSL https://agent-life.ai/install.sh | shThe install script detects the platform and downloads the correct binary to /usr/local/bin/alf (or ~/.local/bin/alf without root). SHA256 checksum verification is mandatory by default. A hash mismatch always aborts the install (exit 4) and cannot be overridden. If verification cannot be performed — the .sha256 file is missing or empty, or no sha256sum/shasum tool is available — the script also exits 4 by default; set ALF_ALLOW_UNVERIFIED=1 to opt out of that case (not recommended), which then reports "checksum_verified":false and a populated warnings array in the JSON output.
From source (requires Rust 1.75+):
cargo install --git https://github.com/agent-life/agent-life-adapters.git alf-cliOpenClaw skill usage: The binary is invoked directly by the agent. JSON-first output means agents can parse command results from stdout without scraping text. No runtime dependencies, no package manager, no Node.js.
Prerequisites: Rust 1.75+ (for async trait support), cargo.
git clone https://github.com/agent-life/agent-life-adapters.git
cd agent-life-adapters
cargo build --releaseThe alf binary is at target/release/alf.
Running tests:
cargo test # All crates
cargo test -p alf-core # Core library only
cargo test -p adapter-openclaw # OpenClaw adapter onlyCross-compilation (requires cargo-zigbuild or cross):
cargo zigbuild --release --target x86_64-unknown-linux-musl
cargo zigbuild --release --target aarch64-unknown-linux-muslThe adapter interface is a Rust trait. To add support for a new framework:
- Create a new crate in the workspace:
adapter-yourframework/ - Implement the
Adaptertrait fromalf-core:
pub trait Adapter {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn export(&self, workspace: &Path, output: &Path) -> Result<ExportReport> {
self.export_with_options(workspace, output, ExportOptions::default())
}
fn export_with_options(
&self,
workspace: &Path,
output: &Path,
options: ExportOptions<'_>,
) -> Result<ExportReport>;
fn import(&self, alf_file: &Path, workspace: &Path) -> Result<ImportReport> {
self.import_with_options(alf_file, workspace, ImportOptions::default())
}
fn import_with_options(
&self,
alf_file: &Path,
workspace: &Path,
options: ImportOptions<'_>,
) -> Result<ImportReport>;
}ExportOptions / ImportOptions carry an optional vault_key for Layer 4 encrypt-on-export and decrypt-on-import.
- Register the adapter in
alf-cli/src/adapter.rs - Add fixture workspaces and round-trip tests
See the ALF specification §6 (Adapter Interface) for the full adapter contract, and §10 for required test cases.
Unit tests (alf-core): Writer/reader round-trip for every ALF type. Schema validation against the canonical JSON schemas. Partition logic (time-based assignment, seal status). Tier classification edge cases.
Integration tests (adapters): Fixture-based round-trip testing when fixture workspaces are present (e.g. fixtures/openclaw-full/, fixtures/zeroclaw-full/). Each adapter can export to .alf, import back, and diff the resulting workspace against the original (zero information loss).
Synthetic Integration test: To test against perfectly valid randomized schema data, generate the synthetic test data first before running tests:
pip3 install --user -r scripts/requirements.txt
python3 scripts/generate_synthetic_data.py
cargo test -p alf-cli --test integration_testsE2E integration testing with fixtures: The scripts/generate_fixtures.sh script creates and mutates an OpenClaw fixture workspace under scripts/fixtures/. Use it to drive multi-step sync sequences and to test restore against real workspace data. (The ZeroClaw synthetic fixture was retired in WP2 — it encoded the wrong DB schema; real-install ZeroClaw coverage now lives in the lifecycle harness.)
Commands:
| Invocation | Purpose |
|---|---|
./scripts/generate_fixtures.sh |
Generate the baseline (round 0) openclaw-workspace with a fixed agent ID. |
./scripts/generate_fixtures.sh --mutate N |
Apply mutation round 1, 2, or 3. Mutations are cumulative (round 2 includes round 1’s changes) and idempotent. |
./scripts/generate_fixtures.sh --reset |
Delete fixtures and regenerate baseline from scratch. |
./scripts/generate_fixtures.sh --status |
Show current mutation round and workspace stats (file counts). |
Requirements: bash, python3. Paths are relative to the repo root; run from the project root.
Testing multiple sync sequences: Each sync should advance the sequence number (0 → 1 → 2 …). Use fixtures and mutations to simulate changes between syncs:
- Build the CLI:
cargo build(orcargo build --release). Use./target/debug/alfor./target/release/alf, or install soalfis onPATH. - Generate baseline:
./scripts/generate_fixtures.sh. - First sync (sequence 0):
alf sync -r openclaw -w scripts/fixtures/openclaw-workspace.
Confirm output shows “Snapshot uploaded (sequence: 0)” (or “Delta uploaded” if state already existed). - Apply mutations and sync again:
./scripts/generate_fixtures.sh --mutate 1
then run the samealf synccommands. The second sync should upload a delta and report sequence 1. Repeat with--mutate 2, then sync again (sequence 2), and so on. - Inspect state:
alf help statusshows tracked agents andlast_synced_sequence;~/.alf/state/{agent_id}.tomlstores the sequence and last sync time.
This validates that the CLI and service advance sequences correctly and that deltas are applied between snapshots.
Testing the restore command: After one or more successful syncs, restore downloads the latest snapshot (and any deltas) and imports into a workspace:
- Ensure at least one agent is synced (e.g. run the sync sequence above).
- Restore to a new directory:
alf restore -r openclaw -w /tmp/restored-openclaw
If multiple agents are tracked, pass-a <agent-id>. Usealf help statusto list agent IDs. - Confirm output reports “Restore complete” and the restored agent name, memory count, and sequence.
- Verify the restored workspace: check that
SOUL.md,MEMORY.md,memory/*.md, and other expected files exist under the restore path and that content matches what was in the synced workspace (or diff key files).
You can repeat restore to a fresh directory to simulate disaster recovery or migration to a new machine.
Cross-runtime tests: Export from OpenClaw fixture → import to ZeroClaw workspace → verify all data is present and correctly mapped. And vice versa. These tests validate the core migration value proposition per spec §10.3.
Schema compliance: Every .alf file produced by any adapter is validated against the JSON schemas before the test passes.
CI: cargo test + cargo clippy + cargo fmt --check on every push. Cross-compilation smoke test on release tags (build all 5 targets, verify binaries are non-zero size).
The install script (scripts/install.sh) has its own isolated test suite that runs against a local mock HTTP server — no real GitHub or S3 calls, no network required.
Entry point:
./scripts/test_install.sh # All tests: Docker (Linux) + native (macOS if on macOS)
./scripts/test_install.sh --linux # Linux only, runs all three Docker containers
./scripts/test_install.sh --macos # macOS native only
./scripts/test_install.sh --quick # Ubuntu container only (fastest, ~15 seconds)Requirements: python3, docker (for Linux tests), curl.
How it works: The runner starts a Python mock server (scripts/test_install/mock_server.py) that simulates GitHub Releases — it serves fake alf binaries and .sha256 checksum files from scripts/test_install/fixtures/. The fake binaries are shell scripts that respond to --version, so no real Rust build is needed. Install script tests run inside Docker containers (Ubuntu 24.04, Debian 12, Alpine 3.19, plus an Alpine variant with no sha256sum/shasum) as a non-root user, exercising each distro's /bin/sh implementation (dash on Ubuntu/Debian, busybox ash on Alpine).
What is tested:
| Category | Tests |
|---|---|
| Happy path | Binary installed, stdout is valid JSON with ok:true, version, path, checksum_verified |
| Version resolution | Mock GitHub API returns v0.0.0-test; auto-discovered without ALF_VERSION set |
| Version pin | ALF_VERSION=v0.0.0-test skips API call, uses pinned tag |
| Custom install dir | ALF_INSTALL_DIR=/tmp/custom → binary lands at the right path |
| Non-root install | Runs as non-root (no writable /usr/local/bin) → installs to ~/.local/bin, PATH warning in stderr |
| Platform detection | uname shim injects Linux/x86_64, Linux/aarch64, Darwin/x86_64, Darwin/arm64 → correct binary name selected |
| Unsupported OS | FreeBSD → exit code 2 |
| Unsupported arch | Linux/riscv64 → exit code 2 |
| Download failure | Version not found on mock server (HTTP 404, both primary and backup) → exit code 3 |
| Checksum mismatch | Mock server returns a wrong hash → exit code 4 |
| Checksum unavailable | Mock server 404s for .sha256 → exit code 4 by default; ALF_ALLOW_UNVERIFIED=1 → exit 0 with checksum_verified:false and a warning |
| Empty checksum | Mock server returns an empty .sha256 body → exit code 4 |
| No checksum tool | Alpine image with no sha256sum/shasum → exit code 4; ALF_ALLOW_UNVERIFIED=1 → exit 0 with a warning |
| JSON stdout | Success: stdout is parseable JSON. Failure: stdout is also parseable JSON with ok:false |
| Stderr progress | Progress messages (Installing…, ✓ Checksum verified) go to stderr, not stdout |
| Quiet mode | ALF_QUIET=1 → stderr is completely empty, stdout still has JSON |
| Post-install verify | Installed binary is executable, alf --version contains "alf" |
| Shell compat (Docker) | Full suite passes on dash (Ubuntu/Debian) and busybox ash (Alpine) |
Manual smoke test (no Docker):
# Start mock server
python3 scripts/test_install/mock_server.py 18432 scripts/test_install/fixtures &
# Run tests natively
INSTALL_SH=scripts/install.sh sh scripts/test_install/run_tests.sh 18432 localhostCI: .github/workflows/test-install.yml runs on every push or PR touching scripts/install.sh, scripts/test_install.sh, or scripts/test_install/**. Two parallel jobs: Linux (Docker, ubuntu-latest) and macOS (native, macos-latest).
Main pipeline (scripts/integration_walkthrough.py) is both an end-to-end functional test and an educational tool for new contributors. It walks through the complete agent lifecycle — connectivity, create agent, snapshot, deltas, restore, point-in-time restore, simulated data loss, recovery, and cleanup — with explanations at each step of what is happening and where data lives (API, Neon, S3).
Vault-focused (scripts/integration_walkthrough_for_vault.py) covers Layer 4: zero-knowledge boundary, on-disk vs cloud representation, snapshot upload with credentials.json, optional alf vault list, and cleanup. Same .env variables as the main script.
Workspace coverage (scripts/integration_walkthrough_for_workspace.py) covers Layer 5 (WP3 — alf add): how an agent explicitly opts arbitrary files into sync (ALF never auto-walks a workspace), where the tracked-file whitelist and removal log live (.alf-include.json / .alf-sync-log.md, both synced so they travel on restore), and how a change to a tracked file triggers a fresh snapshot (a non-destructive rollover) while memory-only changes still ride deltas. Drives the real alf CLI against the live service and verifies each effect in Neon + S3. Same .env variables as the main script.
Real-install lifecycle harness (tests/lifecycle/driver.py) supersedes the retired memory walkthrough: it runs the Z1–Z13 lifecycle against a real framework install (official installer, hardened version pin) in Docker with the locally built alf injected, in automated and --interactive modes, with backend inspection (⊙ API/S3/Neon) and a no-LLM seeding tier that runs with zero secrets in CI. See tests/lifecycle/README.md for the runbook.
Unlike the Rust E2E tests (which verify API contracts), the service-backed walkthroughs also query Neon and S3 directly at each step, so you can see the actual database rows and blob objects that the Lambdas create.
# Install dependencies (one time)
pip install requests psycopg2-binary boto3 python-dotenv
# Interactive mode — pauses at each step with colored explanations
python3 scripts/integration_walkthrough.py
# Batch mode — no pauses, for CI or scripted runs
python3 scripts/integration_walkthrough.py --no-pause
# Vault walkthrough (separate test agent UUID)
python3 scripts/integration_walkthrough_for_vault.py --no-pause
# Workspace-coverage walkthrough (WP3 — alf add; separate test agent UUID)
python3 scripts/integration_walkthrough_for_workspace.py --no-pause
# Real-install lifecycle harness (supersedes the retired memory walkthrough)
python3 tests/lifecycle/driver.py --framework zeroclaw --llm none --backend none --ci --stages Z1-Z3,Z13
# Custom report path
python3 scripts/integration_walkthrough.py --report results/report.mdThe walkthroughs read the same .env variables as the Rust E2E tests (API_BASE_URL, API_KEY, NEON_DATABASE_URL) plus S3_BUCKET_NAME and AWS_REGION for direct infrastructure verification.
Main script — step overview (see script for authoritative ordering):
| # | Step | What it does | What it verifies |
|---|---|---|---|
| 0 | Connectivity | Pings API, Neon, and S3 | All three backends are reachable |
| 1 | CLI sync model | Explains ~/.alf/state/ cursor + delta base |
(conceptual) |
| 2 | Create agent | POST /agents | Agent row exists in Neon with sequence=0 |
| 3 | Upload snapshot | PUT /agents/:id/snapshot | Snapshot row in Neon, blob in S3, agent pointers updated |
| … | Deltas / restore / PIT / cleanup | … | … |
Each step checks three layers: API response, direct Neon query (bypassing RLS), and direct S3 HEAD/LIST. On completion, a markdown report is written with pass/fail status and per-step latencies.
MIT — see LICENSE.
- ALF Specification — the full format specification
- agent-life-data-format — specification source and JSON schemas
- agent-life.ai — project website
- docs/cli-reference.md —
alfcommand reference (JSON schemas, flags, errors) - docs/vault-key-management.md — ALF vault key vs runtime keys, export/import behavior
- docs/how_alf_syncs.md — sync state machine and recovery