The jarvis-research command¶
jarvis-research is the lifecycle command for a JARVIS install. The installer
(./setup.sh or scripts/jarvis-setup.sh) puts a small launcher on your PATH
at ~/.local/bin/jarvis-research and records your checkout as the managed
install, so you can run day-to-day operations from any directory.
The launcher carries no logic of its own: it finds your most recently installed checkout and hands off to that repository's tracked script. An update therefore ships a newer command along with the rest of the code.
If jarvis-research is not found after an install, make sure ~/.local/bin is
on your PATH, or run ./setup.sh again from your checkout.
Commands¶
| Command | What it does |
|---|---|
update [--to <tag>] [--resume <tag>] [--yes] |
Transactional, database-safe upgrade to the latest published release, or to a specific --to tag. Refuses on a diverged, dirty, or non-main checkout and when the target's images are not yet published. |
status |
Show container status (docker compose ps). |
start |
Start the stack without building (docker compose up -d --no-build). |
stop |
Stop the stack. |
restart |
Restart the stack. |
logs [args] |
Tail service logs; extra arguments pass through to docker compose logs (e.g. logs -f paper_ingestion). |
doctor |
Read-only health, disk, registration, and update-availability check, plus host preflight probes. |
repair |
Bounded, non-destructive recovery: recreate stopped containers (no build, no pull) and restart any unhealthy mandatory service. |
owner status |
Show whether instance ownership comes from the host environment or database and whether it resolves to a live administrator. |
owner set <email> |
Repair a missing or invalid database-managed owner. Refuses host-managed ownership and requires the target email to be typed again. |
restore acknowledge <restore-id> |
After an off-host restore, release outbound-integration quarantine for the exact reviewed restore. Requires the restore ID to be typed again. |
register |
Record the current checkout as the managed install and refresh the launcher. |
uninstall [--dry-run] [--tier N] [--keep-data] [--all] [--yes] |
Tiered, contained teardown of a managed install: stop (1), remove application images (2), delete data volumes (3), or full purge (4). Lead with --dry-run. See Uninstalling. |
version |
Print the command name and the installed JARVIS_VERSION. |
help |
Print usage. |
Run jarvis-research help for the built-in summary. A command can be pointed at
a specific checkout with jarvis-research --repo <dir> <command>.
Ownership recovery¶
Run jarvis-research owner status after upgrading an installation that already
had multiple administrators. Migration 0105 assigns the sole live
administrator automatically, but deliberately leaves a multi-admin choice to
the operator. If the database owner is missing or invalid, use
jarvis-research owner set <admin-email> and type the same email to confirm.
The command accepts only a live administrator and commits the repair atomically.
When OWNER_USER_ID manages ownership, change that host setting and restart
JARVIS instead. A valid database-managed owner transfers ownership in Admin →
User Management, not through the repair command.
Restore acknowledgement¶
An off-host restore quarantines restored outbound integrations until their
credentials have been reviewed. Use the browser progress view or run
jarvis-research restore acknowledge <restore-id> with the exact current
32-character restore ID, then type it again. A missing, stale, or changed review
state is refused and leaves quarantine active. See Backup &
Restore.
Exit codes¶
| Code | Meaning |
|---|---|
0 |
Success. |
1 |
The operation was refused or failed. |
2 |
Usage error (unknown command or option). |
3 |
Environment problem — the Docker daemon is not reachable. |
How update works¶
jarvis-research update is transactional: it verifies the whole target release
before it changes anything, advances your checkout only by a fast-forward, and
records its progress so an interrupted run can resume. It never force-rewrites
your branch.
In order, an update:
- Checks preconditions. The checkout must be registered, its
originmust be the managed JARVIS repository, the Docker daemon must be reachable, and the checkout must be a clean, non-detachedmain(uncommitted changes, a detached HEAD, or a working branch are all refused with guidance). - Selects a target. With no argument it picks the highest published stable
release;
--to <tag>selects a specific tag. - Requires a fast-forward. If your checkout has diverged from the target so that a fast-forward is impossible, the update is refused rather than forced. If you are already on the target, it reports "already up to date".
- Verifies the release is fully published. Every registry-backed image the target needs must already exist; a visible tag whose images are still uploading is refused, so you never advance onto a half-published release.
- Enforces a restore point before a data-changing migration. New migrations between your version and the target are inspected. If any one changes data, the command triggers a backup and accepts it only when its signed manifest names the exact main-database, model-router, and secrets archives for that run and their sizes and checksums match. A missing, unsigned, incomplete, or mismatched point is refused. Additive-only migrations apply on restart and only suggest taking a restore point first.
- Stages images, then advances. The target's Compose files are resolved with this install's active profiles. Every exact registry image in that result, including profile dependencies and target-added services, is pulled before the branch moves. Services explicitly marked for local builds are not sent to a registry. A failed pull leaves the checkout untouched.
- Applies and verifies health. It pins
JARVIS_VERSION, recreates the services (viaupdate.sh), and waits for them to report healthy. On success it clears the pending-transaction record and prints adoctorsummary.
Resuming an interrupted update¶
Each install writes its own small pending-transaction file, so interrupted
updates in two clones cannot overwrite each other. On the first update after
upgrading from an older command, JARVIS moves the former shared record only when
its recorded commits identify this install unambiguously; otherwise it stops and
keeps the record untouched. If a run is interrupted, run
jarvis-research update again — it
resumes deterministically from the recorded phase instead of reporting "up to
date", even when the checkout already points at the target commit. A run that
stopped before advancing the branch restarts cleanly. If you need to drive the
post-advance half explicitly, jarvis-research update --resume <tag> runs only
those remaining steps. The command refuses to resume if the checkout moved to
an unexpected commit.
Rolling back¶
update never rolls back on its own. When an update fails after the images
changed, it prints the exact commands to pin JARVIS_VERSION back to your
previous version and pull those images.
If a data-changing migration already ran, image rollback alone is not
schema-safe — the new database schema stays in place. To return to the
pre-update state, restore the backup taken before the update (the WebUI Backup
panel → Restore, or scripts/restore.sh); that rolls the database back together
with the images. See Backup & Restore.
Release-candidate tags are throwaway¶
An operator who checks out a release candidate with --to <rc-tag> is on a
scratch checkout. Because a release squash-merges its work, the stable tag lands
on a different commit than the rc, so an rc checkout cannot fast-forward to the
stable tag — the diverged-checkout refusal in step 3 fires by design. A normal
jarvis-research update never selects rc tags; it only considers stable
vX.Y.Z releases. To run a stable release after trying a candidate, do a fresh
install rather than trying to update the rc checkout in place.
Updating by hand¶
jarvis-research update is the supported path. Use the lower-level fallback
only when the lifecycle command itself cannot run:
The fallback does not classify migrations, require a signed restore point, or resume a recorded transaction. Take a current restore point first, and use this path only to repair a lifecycle command that cannot run.
Uninstalling¶
jarvis-research uninstall removes an install in four escalating tiers. Each tier
enumerates the exact containers, images, volumes, and files it will remove and
confirms before acting — nothing is removed by a bulk docker … prune. Preview any
teardown first, which mutates nothing:
| Tier | What it removes | Reversible? |
|---|---|---|
1 stop |
Containers and the jarvis network (docker compose down). Data, images, and files are kept. |
Yes — jarvis-research start. |
2 app |
Tier 1 + the JARVIS application images (ghcr.io/limitcycle-oss/jarvis-*) at your pinned version. |
Yes — a reinstall pulls them again. |
3 data |
Tier 2 + the project's named data volumes (docker compose down --volumes): the database, the vector store, and the caches. |
No. Back up first. |
4 purge |
Tier 3 + the pinned third-party images (each confirmed individually), .env, secrets/, shared/, this install's registry line, the jarvis-research launcher (only if no other install remains), and finally the clone directory itself. |
No. |
Flags¶
| Flag | Effect |
|---|---|
--dry-run |
Enumerate everything the chosen tier would remove and exit without changing anything. |
--tier N |
Run tier N (1–4) directly instead of the interactive menu. |
--keep-data |
Cap the run at tier 2, so the data volumes and on-disk files are always preserved. |
--all |
Select tier 4 (full purge). |
--yes |
Skip the ordinary per-tier [y/N] prompt. Requires an explicit --tier N (or --all). |
The destructive gates require typed confirmation¶
--yes and --all skip only the ordinary confirmation. They can never satisfy the
destructive gates, each of which reads a typed confirmation from stdin:
- Tier 3 requires typing the compose project name before any volume is deleted. When the stack is running, an interactive run first offers to take a backup inside the backup service, where the required credentials and storage are available. If you accept and that backup fails or another backup is still in progress, uninstall stops before the typed deletion gate.
- Tier 4 first offers to copy the backup encryption key
(
secrets/backup_encrypt_key.txt) to a path outside the clone. That key is deliberately excluded from backup archives, so deletingsecrets/without it leaves every encrypted off-host backup permanently unrecoverable. If you decline the export you must type an explicit acknowledgement phrase to continue. - Tier 4 confirms each third-party image (postgres, ollama, qdrant, caddy, …) individually, since those images may be shared with other projects on the host.
A run with no controlling terminal (closed stdin) therefore cannot complete tier 3 or tier 4 — the typed gates refuse and the install is left untouched.
When Docker is not running¶
Every tier needs the Docker daemon. If it is unreachable, uninstall refuses with
exit code 3 and prints an inventory of the orphaned containers, volumes, network,
and on-disk files so you can start Docker (then re-run) or clean up by hand. There
is no file-only teardown path.