How to Update Horizon AIOS
The step-by-step procedure for pulling upstream Horizon AIOS changes into your
install without losing your customizations or data. For why this works (the
framework vs. user-space model), see
$HORIZON_DOCS/system/distribution_and_updates.md.
One-time setup: remotes
You track Horizon AIOS as upstream and keep your own work + backups on origin:
git remote add upstream git@github.com:HorizonBrute/Horizon_AI_OS.git
git remote set-url origin <your-own-private-repo> # your fork / backup repo
Updating (the normal path)
- (Recommended) Back up your data first:
bash python horizon_system/sbin/horizon_aios_backup_user_data.py # memory/handoffs/objectives -> your remote - Pull upstream -- two-lane sync:
bash python horizon_system/sbin/horizon_aios_sync.pyThe official lane overwrites every framework path (everything exceptprojects/,usrbin/,brains/) with the upstream version and commits it. The personal lane leavesprojects/,usrbin/, andbrains/alone unless you opt in. See$HORIZON_DOCS/sync_setup.mdfor lane mechanics and config keys. - If it reports already up to date, you're done. Your user-space files
(
aios_local.conf,.gitignore.user,memory/,handoffs/,objectives/,~/.horizon/,~/.claude/,brains/,*.local.*) were never touched -- upstream doesn't own them.
If a local framework change disappeared after updating
This is expected, not a bug. The official lane is authoritative and overwrites
framework paths (horizon_system/**, the tracked .gitignore, templates, and
other non-personal paths) with the upstream version -- it does not stop to ask.
If a change you made to a framework file vanished after a sync, it was reclaimed
by design. To keep the customization across every future update, move it into the
override layer:
- Recover your change from git history if needed:
bash git log -p -- <the framework file you edited> # find your prior version - Re-express it in the override layer so the official lane never touches it
again --
aios_overrides.md(project),aios_local.conf(machine),.gitignore.user(ignores),settings.local.json(permissions),CLAUDE.local.md(instructions). - If the change genuinely belongs in the framework, contribute it upstream rather than carrying it locally; the official lane will otherwise reclaim it on every run.
For personal paths (projects/, usrbin/, brains/), the personal lane keeps
local by default. If you opted in with SYNC_PERSONAL_FROM_REMOTE=yes and your
personal branch diverged from its remote, the lane keeps local and skips
rather than rewriting; --force-personal is the deliberate override that
overwrites personal paths (and discards local personal changes).
After updating
- If templates or structure changed, re-run bootstrap (idempotent):
bash ./horizon_system/sbin/bootstrap.ps1 # Windows (Administrator) sudo bash horizon_system/sbin/bootstrap.sh # Linux/macOS - Verify health:
python horizon_system/sbin/horizon_aios_doctor.py. - Restart Claude Code and open a new shell so it reloads config.
Rolling back a bad update
Updates never touch your gitignored data (memory/, handoffs/, objectives/),
so a rollback is safe:
git reflog # find the commit from just before the update
git reset --hard <that-commit>
Automating it
horizon_aios_sync.py can run on a schedule (cron / Task Scheduler) via
horizon_aios_setup_sync_schedule.py; configure cadence and lanes in
aios_local.conf (SYNC_AIOS_FROM_REMOTE, AIOS_SYNC_FREQ, AIOS_SYNC_TIME,
AIOS_OFFICIAL_REMOTE, AIOS_OFFICIAL_BRANCH, and the optional personal-lane
keys AIOS_PERSONAL_REMOTE / AIOS_PERSONAL_BRANCH / SYNC_PERSONAL_FROM_REMOTE).
See $HORIZON_DOCS/sync_setup.md.