* Let Grok updates through mise take effect Grok's npm launcher runs ~/.grok/bin/grok whenever it exists, and the install script that repoints it at a new release doesn't run under mise, so every machine kept running the release it first unpacked. Updating mise tools now drops a link to an older release and the old binary, and lets the launcher unpack the installed one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep several Grok accounts, the way Claude and Codex do Grok honors GROK_HOME, so an added Grok account gets its own home holding only its login and settings cache, with the CLI binary, sessions, skills, plugins, memory, and config linked back to ~/.grok. The account commands, the add flow (a second account signs in through a private window), the launcher, and a grok shell function all take it like the others, and its identity and plan come from the files Grok writes at login. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show Grok's plan and credits in the agents panel A grok collector reads each account's plan from the settings Grok caches and its credits from the endpoint behind Grok's own /usage view, so Grok gets a section, per-account limits, and autoswitch like Claude and Codex. A signed-in agent with a plan now shows before its first numbers, so a lapsed sign-in has somewhere to say so. Grok's mark joins the assets, and with every agent able to take another account the add screen no longer needs to dim one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document Grok accounts and limits alongside Claude and Codex Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Read Grok's credits the way xAI actually answers The answer nests under config, names a weekly period with its end, and as protobuf JSON leaves the usage percentage out while it's zero. The collector now reads that shape, so a fresh week shows as 0% until it resets rather than as nothing known. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count Grok's prompts and sessions from its session summaries Grok keeps a summary beside each session with when it was last active and how many prompts it had, so its section and the hero's summary get today's prompts and sessions and its active days. It records no token counts there, so none are claimed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Give each Grok limits cache write its own temporary file Two overlapping collector runs wrote the same cache through one .tmp path, so one rename could leave the other's failing and its record not updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Read a single Grok account from GROK_HOME when it's set The launcher and the CLI honor GROK_HOME, but the collector always read ~/.grok, so a Grok signed in only in a custom home showed nothing. With one account, the collector now reads the home the CLI would; with several registered, the primary stays ~/.grok. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop guesses the real Grok credits answer made unnecessary The collector carried fallbacks for fields and shapes guessed from the binary before xAI's actual answer was seen, a numeric timestamp branch nothing writes, the panel's default for prompt stats, and guards that an empty sign-in already covers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the working Grok release until its update is in place The update dropped the link and older binaries before the new release was unpacked and ignored a failed unpack, which could leave every Grok account without a CLI. The old release now stays until the new one is linked, and its link comes back if it never is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count only Grok sessions for today, not prompts A session's summary holds all its prompts and only when it was last active, so a resumed session put its whole history on today. Today now counts the sessions active in it; prompts stay an all-time total. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Reuse the Grok session scan on a limits-only refresh Opening the panel and near-limit checks only need fresh limits, so they reuse a scan up to 15 minutes old, as the Codex collector does; --force still rescans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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="npm:@xai-official/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 "${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
|