Skip to content

uw: add claude-set-token subcommand + dev-env activation for OAuth token#169

Merged
lmoresi merged 2 commits intodevelopmentfrom
bugfix/uw-claude-oauth-token
May 5, 2026
Merged

uw: add claude-set-token subcommand + dev-env activation for OAuth token#169
lmoresi merged 2 commits intodevelopmentfrom
bugfix/uw-claude-oauth-token

Conversation

@lmoresi
Copy link
Copy Markdown
Member

@lmoresi lmoresi commented May 4, 2026

Summary

Setting up CLAUDE_CODE_OAUTH_TOKEN on a remote (no-browser) machine currently means: run claude setup-token on a host with a browser, copy the sk-ant-oat01-... token across, export it, then maintain it in ~/.bashrc (or hand-roll a sourced dotfile) and remember to keep it in sync. This PR removes the rc-file dance for users on the UW3 dev pixi env.

Two pieces work together:

  1. scripts/activate-claude-auth.sh — sourced by pixi via [feature.dev.activation] in pixi.toml. If ~/.claude/uw-token exists, exports its contents as CLAUDE_CODE_OAUTH_TOKEN. Scoped to dev pixi envs only — token is not exported in non-dev envs or in shells outside pixi.

  2. ./uw claude-set-token [TOKEN] — accepts the token from arg, stdin (pipe), or interactive prompt (input hidden), validates the sk-ant-oat01- prefix, and writes ~/.claude/uw-token with mode 0600. Has its own --help describing the workflow end-to-end. Listed under Setup: in ./uw --help.

End-to-end on a fresh remote:

./uw claude-set-token         # paste token once
./uw shell                    # token auto-loads
claude                        # just works

Caveats

  • Same security posture as exporting from a shell rc — token on disk in $HOME, mode 0600. We're not improving secret hygiene, just paving the path users were going to walk anyway.
  • Doesn't replace a real secrets manager (1Password CLI, pass, etc.) — users on those will roll their own and that's fine.
  • Per-user, not per-project; this is in ./uw because UW3 is the place contributors hit the friction.

Test plan

  • bash -n uw clean (verified locally)
  • ./uw --help lists claude-set-token under Setup
  • ./uw claude-set-token --help shows the standalone usage block
  • ./uw claude-set-token sk-ant-oat01-VALIDLOOKING… writes ~/.claude/uw-token with mode 0600
  • ./uw claude-set-token notatoken is rejected with the prefix-error message
  • ./uw claude-set-token with no args prompts (input hidden)
  • echo "$TOKEN" | ./uw claude-set-token reads from stdin
  • After writing, ./uw shell (in dev env) shows $CLAUDE_CODE_OAUTH_TOKEN set
  • In a non-dev env, pixi shell -e default does NOT export the token

Underworld development team with AI support from Claude Code

Manual setup of CLAUDE_CODE_OAUTH_TOKEN on a remote machine is fiddly:
run claude setup-token on a browser host, copy the sk-ant-oat01-...
token, then export it from ~/.bashrc on the remote and remember to
keep it in sync. Two pieces work together to remove the rc-file dance:

1. scripts/activate-claude-auth.sh — sourced via [feature.dev.activation]
   in pixi.toml. Auto-exports CLAUDE_CODE_OAUTH_TOKEN from ~/.claude/uw-token
   whenever a dev pixi env is activated. Token is scoped to dev envs only,
   not leaked into non-dev shells or non-pixi sessions.

2. ./uw claude-set-token [TOKEN] — accepts the token from arg, stdin
   (pipe), or interactive prompt (input hidden), validates the
   sk-ant-oat01- prefix, and writes ~/.claude/uw-token with mode 0600.
   Has its own --help describing the flow end-to-end. Listed under
   Setup in ./uw --help.

Net workflow on a fresh remote:
  ./uw claude-set-token         # paste token once
  ./uw shell                    # token auto-loads
  claude                        # just works

Same security posture as exporting from a shell rc — token on disk in
$HOME, mode 0600. Doesn't help users on a real secrets manager.

Underworld development team with AI support from Claude Code (https://claude.com/claude-code)
Copilot AI review requested due to automatic review settings May 4, 2026 23:39
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a smoother workflow for using Claude Code on remote/headless dev machines by persisting a user token in ~/.claude/uw-token and auto-exporting it only when entering Underworld3’s dev pixi environments.

Changes:

  • Introduces ./uw claude-set-token to accept a Claude Code OAuth token (arg/stdin/hidden prompt) and store it with restricted permissions.
  • Adds a dev-only pixi activation script to export CLAUDE_CODE_OAUTH_TOKEN from ~/.claude/uw-token on environment activation.
  • Wires the activation script into pixi.toml under [feature.dev.activation] and exposes the new subcommand in ./uw --help.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
uw Adds claude-set-token subcommand (help text + token capture/validation + write to ~/.claude/uw-token).
scripts/activate-claude-auth.sh New dev-env activation hook to export CLAUDE_CODE_OAUTH_TOKEN from the stored token file.
pixi.toml Registers the activation script for the dev feature so it only applies to dev-feature environments.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread uw
Comment on lines +734 to +748
mkdir -p "$HOME/.claude"
chmod 700 "$HOME/.claude" 2>/dev/null || true

local token_file="$HOME/.claude/uw-token"
if [ -f "$token_file" ]; then
echo -e " ${YELLOW}Overwriting existing token at $token_file${NC}"
fi

# Write atomically with strict perms
(umask 077 && printf '%s' "$token" > "$token_file") || {
echo -e "${YELLOW}Failed to write $token_file${NC}" >&2
return 1
}
chmod 600 "$token_file"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ac0949b. Now refuses to write through a symlink at the destination, and replaces atomically: mktemp a sibling file (created 0600), write the token into it, chmod 600 belt-and-braces, then mv -f into place — atomic on the same filesystem. All failure paths clean up the temp file.

Comment thread scripts/activate-claude-auth.sh Outdated
Comment on lines +12 to +13
CLAUDE_CODE_OAUTH_TOKEN="$(cat "$HOME/.claude/uw-token")"
export CLAUDE_CODE_OAUTH_TOKEN
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ac0949b. Switched to tr -d '[:space:]' < file and only export when the result is non-empty. Comment notes that $(cat file) only strips trailing newlines and is not enough for hand-edited files (\r\n line endings, leading whitespace, etc.).

Comment thread uw Outdated
Comment on lines +709 to +715
read -r token
else
echo -e "${BOLD}Set Claude Code OAuth token${NC}"
echo " Get one with 'claude setup-token' on a machine with a browser."
echo " See './uw claude-set-token --help' for details."
echo ""
read -r -s -p "Token (input hidden): " token
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ac0949b. Added || true to both read invocations (piped and interactive) so EOF no longer kills the script under set -e. Verified: printf "" | ./uw claude-set-token now prints "No token provided." and exits 1, instead of dying silently.

Address Copilot review on PR #169:

1. Atomic write + symlink safety. The original `printf > file` was not
   atomic and would happily follow a pre-existing symlink at the
   destination, clobbering whatever it pointed at regardless of umask.
   Switch to: refuse if the destination is a symlink, then write to a
   sibling temp file via mktemp (chmod 0600) and `mv` it into place
   (atomic on the same filesystem). Cleanup on every failure path.

2. `read` + `set -e`. Bare `read` returns non-zero on EOF (empty pipe
   input or Ctrl-D at the prompt), and with `set -e` in effect at
   script scope that killed the whole script before the "No token
   provided" handler could run. Add `|| true` so the empty-check now
   handles it cleanly. Verified with `printf '' | ./uw claude-set-token`
   → prints the diagnostic and exits 1.

3. Activation script trailing whitespace. `$(cat file)` only strips
   trailing newlines. A manually-edited token file with \r\n endings,
   leading spaces, or extra whitespace would have leaked into
   CLAUDE_CODE_OAUTH_TOKEN and broken auth. Read via
   `tr -d '[:space:]' < file` and only export when the result is
   non-empty.

Underworld development team with AI support from Claude Code (https://claude.com/claude-code)
@lmoresi
Copy link
Copy Markdown
Member Author

lmoresi commented May 5, 2026

Minor changes, all tests still pass. Merging

@lmoresi lmoresi merged commit 4a84d2a into development May 5, 2026
1 check passed
lmoresi added a commit that referenced this pull request May 5, 2026
…et-token

Revert #169: park claude-set-token + dev-env OAuth activation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants