uw: add claude-set-token subcommand + dev-env activation for OAuth token#169
uw: add claude-set-token subcommand + dev-env activation for OAuth token#169lmoresi merged 2 commits intodevelopmentfrom
claude-set-token subcommand + dev-env activation for OAuth token#169Conversation
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)
There was a problem hiding this comment.
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-tokento 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_TOKENfrom~/.claude/uw-tokenon environment activation. - Wires the activation script into
pixi.tomlunder[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.
| 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" | ||
|
|
There was a problem hiding this comment.
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.
| CLAUDE_CODE_OAUTH_TOKEN="$(cat "$HOME/.claude/uw-token")" | ||
| export CLAUDE_CODE_OAUTH_TOKEN |
There was a problem hiding this comment.
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.).
| 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 |
There was a problem hiding this comment.
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)
|
Minor changes, all tests still pass. Merging |
…et-token Revert #169: park claude-set-token + dev-env OAuth activation
Summary
Setting up
CLAUDE_CODE_OAUTH_TOKENon a remote (no-browser) machine currently means: runclaude setup-tokenon a host with a browser, copy thesk-ant-oat01-...token across,exportit, 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:
scripts/activate-claude-auth.sh— sourced by pixi via[feature.dev.activation]inpixi.toml. If~/.claude/uw-tokenexists, exports its contents asCLAUDE_CODE_OAUTH_TOKEN. Scoped to dev pixi envs only — token is not exported in non-dev envs or in shells outside pixi../uw claude-set-token [TOKEN]— accepts the token from arg, stdin (pipe), or interactive prompt (input hidden), validates thesk-ant-oat01-prefix, and writes~/.claude/uw-tokenwith mode 0600. Has its own--helpdescribing the workflow end-to-end. Listed underSetup:in./uw --help.End-to-end on a fresh remote:
Caveats
$HOME, mode 0600. We're not improving secret hygiene, just paving the path users were going to walk anyway.pass, etc.) — users on those will roll their own and that's fine../uwbecause UW3 is the place contributors hit the friction.Test plan
bash -n uwclean (verified locally)./uw --helplistsclaude-set-tokenunder Setup./uw claude-set-token --helpshows the standalone usage block./uw claude-set-token sk-ant-oat01-VALIDLOOKING…writes~/.claude/uw-tokenwith mode 0600./uw claude-set-token notatokenis rejected with the prefix-error message./uw claude-set-tokenwith no args prompts (input hidden)echo "$TOKEN" | ./uw claude-set-tokenreads from stdin./uw shell(in dev env) shows$CLAUDE_CODE_OAUTH_TOKENsetpixi shell -e defaultdoes NOT export the tokenUnderworld development team with AI support from Claude Code