* Apply agent account selection to CLI subprocesses * Fix account dispatch edge cases and remove redundant shell wrappers * Use the current account when launching a new agent session
224 lines
7.3 KiB
Bash
Executable File
224 lines
7.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Sign in to a Claude, Codex, or Grok subscription
|
|
# omarchy:args=[--check] [--events] [--reauth <account>] [claude|codex|grok] [label]
|
|
# omarchy:examples=omarchy agent account add claude | omarchy agent account add Work | omarchy agent account add codex Side
|
|
|
|
set -uo pipefail
|
|
|
|
# --check prints, per provider, whether adding one now would be its first
|
|
# sign-in, an additional account, or not possible yet. --events is for the
|
|
# agents panel: progress arrives as `@@omarchy <event> <detail>` lines mixed
|
|
# into the CLI's own output (which carries codes the panel shows), nothing
|
|
# waits on a terminal, and the result also lands as a notification in case
|
|
# the panel has closed.
|
|
# --reauth <account> signs an account that's already here in again, in its
|
|
# own home, for when its sign-in has lapsed.
|
|
check=false
|
|
events=false
|
|
reauth=""
|
|
while [[ ${1:-} == --* ]]; do
|
|
case "$1" in
|
|
--check) check=true ;;
|
|
--events) events=true ;;
|
|
--reauth)
|
|
reauth="${2:-}"
|
|
shift
|
|
;;
|
|
*) break ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Whether a provider's own home (~/.claude, ~/.codex, ~/.grok) is signed in.
|
|
primary_signed_in() {
|
|
omarchy-agent-account-state list "$1" | jq -e '.[0].accounts | any(.primary and .signedIn)' >/dev/null
|
|
}
|
|
|
|
if [[ $check == "true" ]]; then
|
|
for p in claude codex grok; do
|
|
if primary_signed_in "$p"; then
|
|
echo "$p additional"
|
|
else
|
|
echo "$p first"
|
|
fi
|
|
done
|
|
exit 0
|
|
fi
|
|
|
|
# The provider can be left out when it's your default agent:
|
|
# `omarchy agent account add Work`.
|
|
if [[ ${1:-} != "claude" && ${1:-} != "codex" && ${1:-} != "grok" ]]; then
|
|
default=$(omarchy-default-agent)
|
|
[[ $default == "claude" || $default == "codex" || $default == "grok" ]] && set -- "$default" "$@"
|
|
fi
|
|
|
|
case "${1:-}" in
|
|
claude) provider="claude"; name="Claude"; site="claude.ai"; package="claude"; home_env="CLAUDE_CONFIG_DIR" ;;
|
|
codex) provider="codex"; name="Codex"; site="chatgpt.com"; package="codex"; home_env="CODEX_HOME" ;;
|
|
grok) provider="grok"; name="Grok"; site="x.ai"; package="grok"; home_env="GROK_HOME" ;;
|
|
*)
|
|
echo "Usage: omarchy-agent-account-add [--check] [--events] [--reauth <account>] [claude|codex|grok] [label]" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
label="${2:-}"
|
|
|
|
say() {
|
|
if [[ $events == "true" ]]; then
|
|
printf '@@omarchy status %s\n' "$*"
|
|
else
|
|
echo "$*"
|
|
fi
|
|
}
|
|
|
|
finish() {
|
|
if [[ $events == "true" ]]; then
|
|
printf '@@omarchy done %s\n' "$1"
|
|
omarchy-notification-send -g "$1"
|
|
else
|
|
echo
|
|
echo "$1"
|
|
fi
|
|
}
|
|
|
|
fail() {
|
|
if [[ $events == "true" ]]; then
|
|
printf '@@omarchy error %s\n' "$1"
|
|
omarchy-notification-send -g -u critical "Couldn't add the $name account" "$1"
|
|
else
|
|
echo "$1" >&2
|
|
fi
|
|
exit 1
|
|
}
|
|
|
|
# Cancelling from the panel stops the CLI's login too, and leaves no
|
|
# half-made home behind.
|
|
home=""
|
|
browser=""
|
|
cleanup() {
|
|
[[ -n $browser ]] && rm -f "$browser"
|
|
[[ -n $home && -d $home && $home == */.pending/* ]] && rm -rf "$home"
|
|
}
|
|
trap cleanup EXIT
|
|
trap 'pkill -TERM -P $$; exit 130' TERM INT
|
|
|
|
# Bash holds a trap until a foreground command finishes, and a login waits on
|
|
# the browser for as long as it takes. Running it in the background behind a
|
|
# `wait` lets Cancel stop it at once. It keeps this script's stdin, where the
|
|
# panel sends a pasted code.
|
|
interruptible() {
|
|
"$@" <&0 &
|
|
wait $!
|
|
}
|
|
|
|
if omarchy-cmd-missing "$provider"; then
|
|
say "Installing the $name CLI…"
|
|
if [[ $events == "true" ]]; then
|
|
mise use -g "$package" >/dev/null 2>&1 || fail "Installing the $name CLI didn't finish."
|
|
else
|
|
mise use -g "$package" || exit 1
|
|
fi
|
|
fi
|
|
|
|
# Your main browser is almost certainly signed in to the account you already
|
|
# have, and a login would quietly reuse it. The CLIs open their login page
|
|
# through $BROWSER, so this points it at a private window instead.
|
|
private_browser() {
|
|
browser=$(mktemp "${XDG_RUNTIME_DIR:-/tmp}/omarchy-account-browser.XXXXXX")
|
|
printf '#!/bin/bash\nexec omarchy-launch-browser --private "$1"\n' >"$browser"
|
|
chmod +x "$browser"
|
|
}
|
|
|
|
case "$provider" in
|
|
claude) login_command=(claude auth login) ;;
|
|
codex) login_command=(codex login) ;;
|
|
grok) login_command=(grok login) ;;
|
|
esac
|
|
|
|
# The CLI's own home, whatever this shell has pointed it at.
|
|
login() {
|
|
interruptible env -u CLAUDE_CONFIG_DIR -u CODEX_HOME -u GROK_HOME "OMARCHY_AGENT_${provider^^}_HOME=" "${login_command[@]}"
|
|
}
|
|
|
|
# Signing an account that's already here in again, where it lives: the
|
|
# primary home through the normal browser, an added one through a private
|
|
# window. Its home is never recreated or removed.
|
|
if [[ -n $reauth ]]; then
|
|
if [[ $reauth == ":primary" ]]; then
|
|
account_home="$HOME/.$provider"
|
|
else
|
|
account_home=$(omarchy-agent-account-state homes "$provider" | awk -F'\t' -v id="$reauth" '$1 == id { print $2 }')
|
|
fi
|
|
[[ -n $account_home ]] || fail "No $name account named $reauth."
|
|
|
|
if [[ $account_home == "$HOME/.$provider" ]]; then
|
|
say "Sign in to $name again in the browser window that opens."
|
|
login || fail "The $name sign-in didn't finish."
|
|
else
|
|
say "Sign in again as this account in the private window that opens."
|
|
private_browser
|
|
interruptible env BROWSER="$browser" "$home_env=$account_home" "${login_command[@]}" || fail "The $name sign-in didn't finish."
|
|
fi
|
|
|
|
omarchy-agent-usage-update --force "$provider" >/dev/null 2>&1 &
|
|
finish "Signed in to $name again."
|
|
exit 0
|
|
fi
|
|
|
|
# The first subscription signs in where the CLI always looks, through your
|
|
# normal browser: nothing is signed in there yet that it could be mistaken for.
|
|
if ! primary_signed_in "$provider"; then
|
|
say "Sign in to $name in the browser window that opens."
|
|
if login && primary_signed_in "$provider"; then
|
|
# The first agent signed in on a machine with none chosen becomes the
|
|
# default, so `omarchy agent` and the panel's starter prompts have one to
|
|
# run. A default someone already picked is never touched.
|
|
if [[ -z $(omarchy-default-agent) ]]; then
|
|
mkdir -p "$HOME/.config/omarchy/defaults"
|
|
printf '%s\n' "$provider" >"$HOME/.config/omarchy/defaults/agent"
|
|
fi
|
|
omarchy-agent-usage-update --force "$provider" >/dev/null 2>&1 &
|
|
finish "Signed in to $name."
|
|
else
|
|
fail "The $name sign-in didn't finish."
|
|
fi
|
|
else
|
|
if [[ -z $label && $events == "false" && -t 0 ]]; then
|
|
label=$(gum input --placeholder "Work" --prompt "Name this $name account: ") || exit 130
|
|
fi
|
|
|
|
if [[ $events == "true" ]]; then
|
|
say "Sign in as the account you're adding in the private window that opens."
|
|
else
|
|
cat <<EOF
|
|
|
|
Sign in as the account you're adding in the private window that opens.
|
|
If a private window was already open, close it first, or $site may reuse whoever it has signed in.
|
|
|
|
Don't log out of the $name CLI to do this: logging out revokes the saved sign-in.
|
|
|
|
EOF
|
|
fi
|
|
|
|
home=$(omarchy-agent-account-state begin "$provider") || fail "Couldn't set up a home for the new account."
|
|
|
|
private_browser
|
|
interruptible env BROWSER="$browser" "$home_env=$home" "${login_command[@]}"
|
|
|
|
if account=$(omarchy-agent-account-state register "$provider" "$label" "$home" 2>&1); then
|
|
home=""
|
|
added=$(jq -r '.label + (if .email != "" then " (" + .email + ")" else "" end)' <<<"$account")
|
|
omarchy-agent-usage-update --force "$provider" >/dev/null 2>&1 &
|
|
if [[ $events == "true" ]]; then
|
|
finish "Added $added."
|
|
else
|
|
finish "Added $added."
|
|
echo "Switch to it with: omarchy agent account use $provider $(jq -r .id <<<"$account")"
|
|
fi
|
|
else
|
|
home=""
|
|
fail "$account"
|
|
fi
|
|
fi
|