CLI and TUI tool for selecting AWS account/role credentials
Project description
aws-pick
Interactive TUI and Python library for selecting AWS account/role credentials.
Managing dozens of AWS accounts and IAM roles means constantly hunting through config files or retyping ARNs. aws-pick gives you a fast, keyboard-driven terminal UI to search, select, and act on account/role pairs -- and it embeds directly into your own Python tools as a library.
Installation
pip install aws-pick
Requires Python 3.10+.
Key Features
- Interactive TUI -- Full-screen terminal selector built on Textual with keyboard navigation, real-time filtering, and multi-select
- Embeddable library -- One function call (
select_accounts()) drops the TUI into any Python script and returns structured results - Favorites and presets -- Star frequently used roles; save and reload named selection sets
- Environment awareness -- Accounts are auto-classified as production/staging/development with color-coded tags and a confirmation gate before acting on production resources
- Flexible grouping -- View accounts grouped by account name, by role name, or as a flat list -- cycle with a single keystroke
- Selection history -- Tracks recently used account/role pairs with relative timestamps
- Non-interactive mode -- Pass explicit
account_id:role_nameselections for CI/CD pipelines and scripts - Login callbacks -- Hook in your own authentication logic (SSO, STS AssumeRole, etc.) and get structured success/failure results
Quick Start
from aws_pick import select_accounts
result = select_accounts([
{"account_id": "111111111111", "account_name": "prod", "role_name": "Admin"},
{"account_id": "222222222222", "account_name": "dev", "role_name": "Developer"},
{"account_id": "222222222222", "account_name": "dev", "role_name": "ReadOnly"},
])
if not result.cancelled:
for item in result.selected:
print(f"{item['account_name']} -> {item['role_name']}")
This launches the TUI, lets the user pick one or more account/role pairs, and returns the selections as a list of dicts.
Usage Examples
Basic: Embed in a CLI tool
from aws_pick import select_accounts
accounts = load_accounts_from_your_source() # list of dicts
result = select_accounts(accounts, title="Deploy Target")
if result.cancelled:
print("Aborted.")
else:
for item in result.selected:
deploy_to(item["account_id"], item["role_name"])
With login callbacks
Provide an on_login callback to authenticate immediately after selection. The TUI shows a progress screen as each login executes.
from aws_pick import select_accounts, LoginResult
def assume_role(item: dict) -> LoginResult:
try:
session = boto3.Session()
sts = session.client("sts")
sts.assume_role(
RoleArn=f"arn:aws:iam::{item['account_id']}:role/{item['role_name']}",
RoleSessionName="aws-pick",
)
return LoginResult(success=True)
except Exception as e:
return LoginResult(success=False, error=str(e))
result = select_accounts(accounts, on_login=assume_role)
if result.login_results:
print(f"{result.login_results.succeeded}/{result.login_results.total} succeeded")
Non-interactive mode for scripts
Skip the TUI entirely by passing explicit selections. Useful for CI/CD, cron jobs, or wrapping in shell scripts.
from aws_pick import select_accounts
result = select_accounts(
accounts,
interactive=False,
selections=["111111111111:Admin", "222222222222:Developer"],
)
Managing favorites and presets programmatically
from aws_pick import manage_favorites, manage_presets
# Favorites
favs = manage_favorites()
favs.add("111111111111", "Admin")
favs.add("222222222222", "Developer")
print(favs.list()) # [Favorite(...), ...]
favs.remove("111111111111", "Admin")
# Presets (named selection sets)
presets = manage_presets()
presets.save("deploy-prod", [
Favorite(account_id="111111111111", role_name="Admin"),
Favorite(account_id="333333333333", role_name="DeployRole"),
])
print(presets.list_names()) # ["deploy-prod"]
preset = presets.get("deploy-prod")
Keyboard Shortcuts
| Key | Action |
|---|---|
Up / Down |
Navigate items |
Space |
Toggle selection |
Enter |
Confirm selections |
Escape |
Cancel and exit |
/ |
Focus filter bar |
Tab |
Toggle filter / list focus |
a / d |
Select all / Deselect all |
f |
Toggle favorite |
F |
Select all favorites |
g |
Cycle grouping mode |
s / l |
Save / Load preset |
? |
Show help overlay |
API Reference
select_accounts(accounts, *, interactive=True, selections=None, on_login=None, config_dir=None, title="Select Accounts")
Main entry point. Launches the TUI (or runs non-interactively) and returns a SelectionResult.
| Parameter | Type | Description |
|---|---|---|
accounts |
list[dict] |
List of dicts with account_id, account_name, role_name, and optional environment |
interactive |
bool |
True for TUI, False for scripted selection |
selections |
list[str] |
"account_id:role_name" strings (required when interactive=False) |
on_login |
Callable |
Callback receiving a selected dict, returns LoginResult |
config_dir |
str | Path |
Override config directory for favorites/presets/history |
title |
str |
Panel header title in the TUI |
SelectionResult
| Field | Type | Description |
|---|---|---|
selected |
list[dict] |
Selected account/role dicts |
cancelled |
bool |
True if the user pressed Escape |
login_results |
BatchLoginResult | None |
Login outcomes when on_login is provided |
LoginResult
| Field | Type | Description |
|---|---|---|
success |
bool |
Whether login succeeded |
error |
str | None |
Error message on failure |
manage_favorites(*, config_dir=None) / manage_presets(*, config_dir=None)
Factory functions returning FavoritesManager and PresetsManager for programmatic CRUD on persisted favorites and named presets.
CLI
aws-pick also ships a CLI powered by Typer:
aws-pick select # Launch the TUI selector
aws-pick favorites list # List saved favorites
aws-pick preset list # List saved presets
aws-pick history show # Show selection history
Development
git clone https://github.com/troylar/aws-pick.git
cd aws-pick
pip install -e ".[dev]"
Running tests
pytest # All 225+ tests
pytest tests/unit # Unit tests only
pytest tests/integration # Integration + TUI pilot tests
pytest --cov=aws_pick # With coverage
Code quality
ruff check . # Lint
ruff check . --fix # Auto-fix
black . # Format
mypy src/ --strict # Type checking
Code style
- Black with 120-char line length
- Ruff (rules: E, F, I, N, W)
- mypy strict mode
- Type hints on all functions
Contributing
- Open an issue describing the change
- Fork and create a branch:
issue-###-short-description - Write tests (minimum 80% coverage)
- Ensure
pytest,ruff check, andmypy --strictpass - Open a PR referencing the issue (
Closes #123)
Commit format: type(scope): description (#issue)
Roadmap
- AWS SSO / IAM Identity Center integration
- Profile generation (
~/.aws/configwriter) - Plugin system for custom login providers
- Configurable environment patterns
- Export selections to shell environment variables
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aws_pick-0.1.3.tar.gz.
File metadata
- Download URL: aws_pick-0.1.3.tar.gz
- Upload date:
- Size: 79.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6777a454da85a1be47835080848d03313dd61b74b2df82c88320feae2467b25
|
|
| MD5 |
37a1ef0815101a67288e8ee7aac084e6
|
|
| BLAKE2b-256 |
97ee9ae3f9c6db50ac3af37994b76c8d75186216ffaec2061e9f0bed9ee656d4
|
Provenance
The following attestation bundles were made for aws_pick-0.1.3.tar.gz:
Publisher:
publish.yml on troylar/aws-pick
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aws_pick-0.1.3.tar.gz -
Subject digest:
d6777a454da85a1be47835080848d03313dd61b74b2df82c88320feae2467b25 - Sigstore transparency entry: 868382936
- Sigstore integration time:
-
Permalink:
troylar/aws-pick@9e6a72f5631937dcace8f33bbfbc3339c0329cfe -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/troylar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9e6a72f5631937dcace8f33bbfbc3339c0329cfe -
Trigger Event:
release
-
Statement type:
File details
Details for the file aws_pick-0.1.3-py3-none-any.whl.
File metadata
- Download URL: aws_pick-0.1.3-py3-none-any.whl
- Upload date:
- Size: 35.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ca8728d77728f9d292768935f863a2b7386b830a2af79a25c37faa319b2afb5
|
|
| MD5 |
3645d9463f39b64e8f0bc4b2d88c7bef
|
|
| BLAKE2b-256 |
59acfc4b71166b0ae86a3d91eb763d2712e69198c8f879b40554281cd8567bf6
|
Provenance
The following attestation bundles were made for aws_pick-0.1.3-py3-none-any.whl:
Publisher:
publish.yml on troylar/aws-pick
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aws_pick-0.1.3-py3-none-any.whl -
Subject digest:
7ca8728d77728f9d292768935f863a2b7386b830a2af79a25c37faa319b2afb5 - Sigstore transparency entry: 868382948
- Sigstore integration time:
-
Permalink:
troylar/aws-pick@9e6a72f5631937dcace8f33bbfbc3339c0329cfe -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/troylar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9e6a72f5631937dcace8f33bbfbc3339c0329cfe -
Trigger Event:
release
-
Statement type: