Files
omarchycn/bin/omarchy-provision-user
T
David Heinemeier HanssonandGitHub 2cc3510d2a Offer an AI diagnosis when a process crashes (#6746)
* Offer an AI diagnosis when a process crashes

systemd-coredump journals every core dump under a known MESSAGE_ID with the
crashing program, pid, and signal as structured fields. omarchy-crash-watch
follows that stream and raises a "Process crashed: <program>" toast; clicking it
opens omarchy-agent-crash, which briefs the default agent on the crash.

The toast goes through omarchy-notification-send --exec rather than a libnotify
action, because the shell runs clicks from its own omarchy-exec hint and never
emits ActionInvoked. It keeps the default "omarchy-action" app name too, the
only one shouldBypassDnd() lets through -- a crash being the last notification
worth swallowing. It stays quiet until an agent is configured, since a
diagnosis is all it offers.

The method lives in a diagnose-crash skill rather than the prompt, so it is
edited in one place and works with whichever agent is default. It covers
investigating the core, and reporting a confirmed Omarchy bug upstream: scoped
to bugs Omarchy controls, searched for duplicates first, only with the user's
agreement, and signed with the model and harness that produced it.

A migration reaches existing installs, whose skill symlinks and unit enablement
would otherwise sit behind one-time setup paths.

* Let the diagnosis clean up the core it extracted

"Do not modify or delete anything" contradicted the symbolization step right
above it, which writes a core to a temp file and deletes it on exit. Read
literally, the core survives -- and the same section warns it holds passwords
and tokens. The prohibition is about the system, not about your own scratch.

* Do not spend a crash toast on a dead notification server

The shell owns org.freedesktop.Notifications, so its own crash takes the
notification server down with it -- and a shell crash is exactly what you want
told about. The toast was sent once into that gap and the dedupe window was
recorded regardless, so the rest of the crash loop went quiet for a minute and
`journalctl -n 0` never replays what was missed.

It now waits for the restarted shell to reclaim the bus name, as
omarchy-migrate-notify already does, and only a delivered toast starts the
dedupe window.
2026-08-12 18:37:40 +02:00

123 lines
3.6 KiB
Bash
Executable File

#!/bin/bash
# omarchy:summary=Finalize Omarchy user setup (runtime tweaks /etc/skel can't do)
# omarchy:hidden=true
set -euo pipefail
usage() {
cat <<USAGE
Usage: omarchy finalize user [--force] [--first-install]
Runs the per-user setup steps that /etc/skel can't seed:
dev-aware skill symlinks, xdg-user-dirs + gtk bookmarks (need \$HOME),
default browser/mailto, and install/user/all.sh.
For shipped configs see /etc/skel (new users) and omarchy-reinstall-configs
(existing users explicitly resyncing).
--first-install is used by the ISO in the target chroot. It marks shipped
migrations complete for the freshly-created user.
Idempotency marker: ~/.local/state/omarchy/done/finalize-user
USAGE
}
if (( EUID == 0 )); then
echo "Error: run omarchy-provision-user as the user being configured, not as root." >&2
exit 1
fi
force=0
first_install=0
while (($#)); do
case "$1" in
--force)
force=1
shift
;;
--first-install)
first_install=1
force=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
done
state_dir="$HOME/.local/state/omarchy"
mkdir -p "$state_dir"
if omarchy-done check finalize-user && (( force == 0 )); then
echo "User finalization already complete (rerun with --force to refresh)."
exit 0
fi
export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
export OMARCHY_INSTALL="${OMARCHY_INSTALL:-$OMARCHY_PATH/install}"
export OMARCHY_SETUP_CONTEXT="${OMARCHY_SETUP_CONTEXT:-runtime}"
export PATH="$OMARCHY_PATH/bin:$PATH"
if (( first_install )) && [[ $OMARCHY_SETUP_CONTEXT == "runtime" ]]; then
# The ISO chroot doesn't set a context; omarchy-provision-owner runs first-install
# finalization too but with OMARCHY_SETUP_CONTEXT=provision-owner already set.
export OMARCHY_SETUP_CONTEXT=iso-chroot
fi
if [[ -n ${OMARCHY_INSTALL_LOG_FILE:-} && -f $OMARCHY_INSTALL/helpers/logging.sh ]]; then
source "$OMARCHY_INSTALL/helpers/logging.sh"
else
run_logged() {
local script="$1"
bash -eE -c 'source "$1"' bash "$script"
}
fi
# Dev-aware skill symlinks. Cannot live in /etc/skel because OMARCHY_PATH may
# point at a dev checkout (omarchy dev link) where the target differs.
# Loops every skill directory, so shipping a new one needs no edit here.
mkdir -p ~/.agents/skills ~/.claude/skills ~/.codex/skills ~/.pi/agent/skills
for skill in "$OMARCHY_PATH"/default/agents/skills/*/; do
skill=${skill%/}
name=${skill##*/}
ln -sfn "$skill" ~/.agents/skills/"$name"
ln -sfn "$skill" ~/.claude/skills/"$name"
ln -sfn "$skill" ~/.codex/skills/"$name"
ln -sfn "$skill" ~/.pi/agent/skills/"$name"
done
mkdir -p ~/Downloads ~/Pictures ~/Videos ~/.config/gtk-3.0
xdg-user-dirs-update --set TEMPLATES "$HOME"
xdg-user-dirs-update --set PUBLICSHARE "$HOME"
xdg-user-dirs-update --set DESKTOP "$HOME"
rmdir ~/Templates ~/Public ~/Desktop 2>/dev/null || true
touch ~/.config/gtk-3.0/bookmarks
for dir in Downloads Projects Pictures Videos; do
bookmark="file://$HOME/$dir $dir"
grep -qxF "$bookmark" ~/.config/gtk-3.0/bookmarks || echo "$bookmark" >>~/.config/gtk-3.0/bookmarks
done
source "$OMARCHY_INSTALL/user/all.sh"
omarchy-refresh-applications
env -u BROWSER xdg-settings set default-web-browser chromium.desktop
xdg-mime default HEY.desktop x-scheme-handler/mailto
if (( first_install )); then
mkdir -p "$state_dir/migrations"
for migration in "$OMARCHY_PATH"/migrations/*.sh; do
[[ -f $migration ]] && touch "$state_dir/migrations/$(basename "$migration")"
done
fi
omarchy-done mark finalize-user
echo "User finalization complete."