claude-aws-mfa
v1.2.1
Published
AWS MFA credential helper for [Claude Code](https://docs.anthropic.com/en/docs/claude-code). Shows a native dialog to collect AWS credentials and an MFA code, calls STS AssumeRole with automatic duration negotiation, and outputs temporary credentials to s
Readme
claude-aws-mfa
AWS MFA credential helper for Claude Code. Shows a native dialog to collect AWS credentials and an MFA code, calls STS AssumeRole with automatic duration negotiation, and outputs temporary credentials to stdout in the format Claude Code expects.
Install
Requires Bun runtime.
bun install -g claude-aws-mfa@latestConfigure Claude Code
Guided Setup
Run claude-aws-mfa --setup, to access a configuration UI for easy setup of this tool. You will be presented with a checkbox to enable Bedrock via claude-aws-mfa, and fields to customize a few key settings. Specifically, you can pin specific versions of the Anthropic models to use for Opus, Sonnet, and Haiku, in case your Bedrock policy does not allow you access to the latest default models that Claude Code will try to use.
Once you have enabled credential-handling and saved the settings, you can launch Claude Code and begin work. You will automatically prompted for your AWS credentials, and Claude will connect to the specified AWS Bedrock account rather than to the Anthropic servers.
Manual Setup
Add this (plus any addtitional config you prefer) to your Claude Code settings (~/.claude/settings.json, or $CLAUDE_CONFIG_DIR/settings.json if you use per-project profiles):
{
"awsCredentialExport": "claude-aws-mfa",
"env": {
"CLAUDE_CODE_USE_BEDROCK": "1",
"AWS_SHARED_CREDENTIALS_FILE": "/dev/null"
}
}CLI Flags
--cache-session, --auto-mfa, and --single-instance-lock are all on by default; use the --no- prefix to disable one (e.g. --no-cache-session). CLI flags override values saved in the config file.
| Flag | Description |
|------|-------------|
| --setup | Launch the guided setup wizard |
| --cache-session | Cache STS session credentials and reuse them until they expire (default: on) |
| --auto-mfa | Automatically run the configured MFA command and obtain credentials without showing the dialog, requires MFA Command mode (default: on) |
| --single-instance-lock | Prevent multiple concurrent instances from showing overlapping dialogs; subsequent invocations wait for the first to finish and reuse its cached session (default: on) |
| --no-ui | Never show any GUI dialog. Prints credentials JSON to stdout on success, or an error to stderr on failure — useful for scripting or letting an LLM drive the tool during setup/debugging |
How it works
- On first run, seeds the dialog with credentials from your existing AWS config (
~/.aws/credentials, environment variables, SSO, etc.) - Shows a native GUI dialog with fields for region, access key, secret key, MFA ARN, role ARN, and session duration
- Collects the MFA token — either type a 6-digit code directly, or switch to MFA Command mode and provide a shell command that outputs the code (e.g.
op item get --otp …for 1Password CLI) - Calls
sts:AssumeRolewith the MFA token - If the requested session duration is rejected, automatically retries with shorter durations (12h → 6h → 2h → 1h)
- Saves configuration (including MFA mode and command) to
~/.config/claude-aws-mfa.json(mode 0600) for subsequent runs - Outputs temporary credentials as JSON to stdout
On subsequent runs, all fields are pre-populated from the saved config — just enter a fresh MFA code and hit OK. If you use the command mode, the TOTP code is fetched automatically so no manual entry is needed at all.
Claude Code profiles
Claude Code reads its settings from $CLAUDE_CONFIG_DIR when that is set, which tools such as claude-as use to give each project its own credentials. This tool follows suit:
--setupreads and writes$CLAUDE_CONFIG_DIR/settings.json, so a profile can be Bedrock-only while others stay on OAuth.- The config file is scoped per profile —
~/.config/claude-aws-mfa<profile>.json, where<profile>is the config dir path encoded the way Claude encodes project dirs (/and.both become-). Different profiles usually mean different AWS accounts, and a shared cached session would hand a profile credentials for the wrong one. - The default
~/.claudegets no suffix, so existing installs keep using~/.config/claude-aws-mfa.jsonunchanged. - Because the lock is per profile too, two profiles can have a dialog open at once. Every dialog names its profile — in the window title and in a banner under the heading — so you can tell which AWS account a prompt is asking for. The default config dir is named
defaultrather than left unlabelled, so a blank banner never has to be interpreted.
Child processes inherit CLAUDE_CONFIG_DIR, so credential export picks up the right profile automatically. --setup run from an ordinary shell does not — it configures whatever profile the shell is in, normally the default. To set up a specific profile, export the variable first:
CLAUDE_CONFIG_DIR=~/.claude-profiles/work claude-aws-mfa --setupSession caching
With --cache-session (or "cacheSession": true in the config file), temporary credentials are saved to the config file and reused on subsequent runs until they expire. This avoids prompting for MFA on every invocation.
Auto-MFA
With --auto-mfa (or "autoMfa": true in the config file), when a MFA command is configured, credentials are obtained automatically without showing the dialog at all. If the command fails or isn't configured, the dialog is shown as a fallback.
Single-instance lock
With --single-instance-lock (or "singleInstanceLock": true in the config file), only one instance of the tool will show a dialog at a time. Additional invocations will wait for the first to finish and then reuse its cached session (when session caching is also enabled). The lock file is stored alongside the config file (~/.config/claude-aws-mfa.lock, per profile) and is automatically cleaned up after 2 minutes if the holding process crashes.
Authentication failures
Claude Code does not surface a failing command's stderr to the user, so when MFA/STS authentication fails, the error is shown in a native dialog box instead of being written to stderr.
--no-ui mode
With --no-ui, no GUI is ever shown — not even the error dialog above — and the tool never imports the GUI toolkit, so it also works in headless environments without a display. On success, credentials are printed to stdout as usual, keeping stdout cleanly parsable. On failure, an error message is printed to stderr instead (e.g. Missing config: roleArn, mfaCommand if the config is incomplete, or the underlying STS error if authentication itself failed) and the process exits non-zero. This is intended for scripting and for letting an LLM drive the tool directly while setting up or debugging a configuration — full non-interactive operation requires MFA Command mode, since a static "code" mode value can't be re-entered headlessly. The command doesn't need to be a real TOTP generator: for a one-off test or debugging run, mfaCommand can simply be echo <code> with a fresh, not-yet-used code from your authenticator — it only needs to produce a valid code once.
System requirements
The GUI dialog uses webview-bun, which requires:
- macOS: No additional dependencies (uses WebKit)
- Linux:
sudo apt install libwebkitgtk-6.0-4(Debian/Ubuntu) - Windows: Edge WebView2 runtime (included in Windows 11+)
Development
bun install
bun run src/index.ts # run locally
bun test # run testsReleasing
See the Releasing section of CHANGELOG.md for how to publish new versions.
License
MIT
