@padua/cli
v3.3.1
Published
Unified AWS infrastructure management CLI
Readme
Padua CLI
A unified CLI for AWS infrastructure management—authentication, tunneling, and container tools in one place.
Installation
npm install -g @padua/cliPrerequisites
Required:
- Node.js v24 (Active LTS) — see below
- AWS CLI v2
Use Node.js 24 — no build tools needed on any OS:
@padua/cli depends on isolated-vm, which ships prebuilt native binaries
only for Node 24 (the line we pin to). On Node 24 the prebuilt binary loads on
Windows, macOS, and Linux with no compiler involved. The install enforces this
and refuses to run on other Node versions with a clear message, because there
npm would fall back to compiling isolated-vm from source via node-gyp —
which needs a C++ toolchain (Visual Studio Build Tools on Windows) and fails on
machines without one.
Install Node 24 before installing the CLI:
# Windows
winget install OpenJS.NodeJS.LTS # or use nvm-windows: nvm install 24 && nvm use 24
# macOS / Linux (nvm)
nvm install 24 && nvm use 24Why pinned?
isolated-vm6.x publishes prebuilds for Node 22 and 24 only; 7.x requires Node 26. We lock to Node 24 (Active LTS) so installs are prebuilt-only and never touch a compiler. A.nvmrcis provided — runnvm usein the repo.
Optional:
- npm (for CodeArtifact registry authentication)
- Docker (for ECR registry authentication)
- Session Manager Plugin (for
padua tunnelcommand)
Note:
padua initvalidates prerequisites and displays install URLs for any missing tools.
Quick Start
⚠️ WARNING:
padua initwill delete your existing~/.aws/configfile to ensure a clean configuration. A timestamped backup is automatically created at~/.aws/config.backup.<timestamp>. Use the--keep-existingflag to preserve custom non-Padua profiles.
# 1. Initialize configuration (discovers SSO accounts automatically)
padua init
# 2. Login to all services
padua loginThe init command will:
- Check for required prerequisites
- Detect AWS environment variables and warn if present
- Authenticate with AWS SSO
- Discover all accounts and roles you have access to
- Create a timestamped backup of
~/.aws/config - Delete and regenerate
~/.aws/configwith discovered profiles - Generate
~/.padua/padua.config.json
Features
| Category | Feature | Description |
|----------|---------|-------------|
| Auth | SSO Login | AWS SSO authentication and session management |
| | Profiles | Interactive AWS profile selection with shell integration |
| | CodeArtifact | Automatic npm registry authentication |
| | ECR | Docker registry authentication |
| Config | Init | Automatic SSO discovery and profile generation with backup |
| | Status | Health check for all authentication services |
| | Doctor | Configuration validation and diagnostics with fuzzy profile matching |
| Tunnel | RDS | Secure tunnels to RDS/Aurora databases via SSM |
| | LB | Port forwarding to internal ALB via SSM |
| | OpenSearch | Port forwarding to OpenSearch/Elasticsearch domains via SSM |
| Bedrock | Enable | Configure Claude Code to use AWS Bedrock inference (paduafg-production, ap-southeast-2) |
| | Disable | Restore previous Claude config from Bedrock mode |
| | Status | Report current Bedrock env state |
| | Setup | Install pbedrock shell function (bash/zsh/PowerShell) |
| Exec | ECS | Interactive shell in running ECS containers via SSM |
| MCP | Server | Built-in MCP server with 56 tools — GitLab, Atlassian, Grafana, and code execution |
| | Daemon | Background process management via padua login |
| | Diagnostics | MCP health checks via padua doctor |
| | Migration | Token migration from legacy Go server |
MCP Server
@padua/cli v2 includes a built-in MCP (Model Context Protocol) server that exposes 56 tools and 6 resource templates for GitLab, Atlassian, Grafana, and code execution. Any MCP-compatible client — Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, etc. — can call these tools directly.
Setup
padua login # authenticates everything and starts the daemon
padua doctor # verify the server is healthypadua login runs an 8-step flow:
| Step | What happens |
|------|--------------|
| 1. AWS SSO | Authenticate to AWS |
| 2. S3 Config | Download MCP provider configuration to ~/.padua/mcp-providers.json |
| 3. CodeArtifact | Configure npm registry |
| 4. ECR | Configure Docker registry |
| 5. GitLab | OAuth2 PKCE authentication |
| 6. Atlassian | OAuth2 confidential client authentication |
| 7. Grafana | Service-account token authentication. Prompts for a token unless a shared token is set in the grafana provider config (then it just validates, no prompt); skipped entirely when Grafana isn't configured |
| 8. MCP Daemon | Start background HTTP server on port 8919 |
Steps 5-8 are non-blocking — if a provider fails, the rest of Padua still works.
Architecture
┌─────────────────┐ HTTP POST ┌──────────────────────┐
│ Claude Code / │ ──────────────→ │ Padua MCP Daemon │
│ Claude Desktop │ Bearer token │ 127.0.0.1:8919/mcp │
│ Cursor / etc. │ ←────────────── │ │
└─────────────────┘ JSON-RPC │ ┌────────────────┐ │
│ │ GitLab (OAuth) │ │
│ │ 30 tools │ │
│ └────────────────┘ │
│ ┌────────────────┐ │
│ │ Atlassian (OAuth│) │
│ │ 19 tools │ │
│ └────────────────┘ │
│ ┌────────────────┐ │
│ │ Grafana (token) │ │
│ │ 5 tools │ │
│ └────────────────┘ │
└──────────────────────┘- Transport: HTTP with Streamable HTTP transport at
POST /mcp - Auth:
Authorization: Bearer padua-mcp-local(fixed token — the server only binds to localhost) - Tokens: OAuth tokens persisted to
~/.padua/tokens.db(AES-256-GCM encrypted), proactively refreshed before expiry and lazily refreshed on tool calls - Sessions: Multi-session support — multiple Claude Code instances share the daemon concurrently, each with an independent session. Stale sessions are swept after 30 minutes, max 10 concurrent sessions with LRU eviction
- Response format: All tools default to TOON (Token-Oriented Object Notation) for 40-60% token savings on list/search responses. Pass
"format": "json"on any tool call to receive raw JSON instead - Code mode:
call_tool_chainexecutes JavaScript in a secure V8 sandbox with all MCP tools available as synchronous namespaced functions (gitlab.*,jira.*,confluence.*,grafana.*).search_toolsprovides keyword search over all registered tools. The server sendsinstructionsduring initialization that guide LLM clients to prefercall_tool_chainfor multi-step operations automatically
IDE Configuration
Claude Code (~/.claude/settings.json)
Claude Code discovers MCP servers from its settings file. Add the padua server:
{
"mcpServers": {
"padua": {
"type": "url",
"url": "http://127.0.0.1:8919/mcp",
"headers": {
"Authorization": "Bearer padua-mcp-local"
}
}
}
}After adding the config, restart Claude Code or run /mcp to verify the server is connected.
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json)
{
"mcpServers": {
"padua": {
"url": "http://127.0.0.1:8919/mcp",
"headers": {
"Authorization": "Bearer padua-mcp-local"
}
}
}
}Cursor (.cursor/mcp.json)
{
"mcpServers": {
"padua": {
"url": "http://127.0.0.1:8919/mcp",
"headers": {
"Authorization": "Bearer padua-mcp-local"
}
}
}
}Windsurf (~/.windsurf/mcp.json)
{
"mcpServers": {
"padua": {
"serverUrl": "http://127.0.0.1:8919/mcp",
"headers": {
"Authorization": "Bearer padua-mcp-local"
}
}
}
}Any MCP Client (manual HTTP)
curl -X POST http://127.0.0.1:8919/mcp \
-H "Authorization: Bearer padua-mcp-local" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Tool Reference
GitLab — Repository (10 tools)
| Tool | Description |
|------|-------------|
| gitlab_list_projects | List projects accessible to the authenticated user |
| gitlab_get_project | Get project metadata by ID |
| gitlab_get_file | Get file content from a repository |
| gitlab_create_file | Create a new file in a repository |
| gitlab_update_file | Update an existing file in a repository |
| gitlab_list_branches | List branches in a project |
| gitlab_get_branch | Get a single branch by name |
| gitlab_search_code | Search for code across projects |
| gitlab_get_repository_tree | List files and directories in a repository tree |
| gitlab_get_clone_urls | Get clone URLs (SSH and HTTPS) for a project |
GitLab — Issues (4 tools)
| Tool | Description |
|------|-------------|
| gitlab_list_issues | List issues with filtering (project, state, labels, assignee) |
| gitlab_get_issue | Get a single issue by IID |
| gitlab_create_issue | Create a new issue |
| gitlab_update_issue | Update an existing issue (title, description, labels, state) |
GitLab — Merge Requests (11 tools)
| Tool | Description |
|------|-------------|
| gitlab_list_merge_requests | List merge requests with filtering |
| gitlab_get_merge_request | Get a single merge request by IID |
| gitlab_create_merge_request | Create a new merge request |
| gitlab_update_merge_request | Update MR title, description, labels, assignees |
| gitlab_get_merge_request_diffs | Get the diff/changes in a merge request |
| gitlab_list_merge_request_notes | List comments on a merge request |
| gitlab_create_merge_request_note | Add a comment to a merge request |
| gitlab_get_merge_request_approvals | Get approval status and required approvers |
| gitlab_approve_merge_request | Approve a merge request |
| gitlab_merge_merge_request | Merge a merge request |
| gitlab_rebase_merge_request | Rebase a merge request onto its target branch |
GitLab — Pipelines (5 tools)
| Tool | Description |
|------|-------------|
| gitlab_list_pipelines | List CI/CD pipelines for a project |
| gitlab_get_pipeline | Get pipeline details (status, duration, stages) |
| gitlab_list_pipeline_jobs | List jobs within a pipeline |
| gitlab_get_job_log | Get the log output of a CI/CD job |
| gitlab_retry_pipeline | Retry a failed pipeline |
Atlassian — Jira (11 tools)
| Tool | Description |
|------|-------------|
| atlassian_jira_search | Search issues using JQL |
| atlassian_jira_get_issue | Get a single issue by key (e.g., PROJ-123) |
| atlassian_jira_create_issue | Create a new issue (Bug, Story, Task, Epic, etc.) |
| atlassian_jira_update_issue | Update issue fields (summary, description, labels, etc.) |
| atlassian_jira_link_issues | Create a link between two issues (Blocks, Relates, etc.) |
| atlassian_jira_add_comment | Add a comment to an issue (supports Markdown) |
| atlassian_jira_transition_issue | Move an issue to a new status |
| atlassian_jira_list_projects | List accessible Jira projects |
| atlassian_jira_add_worklog | Log time spent on an issue |
| atlassian_jira_get_transitions | Get available transitions for an issue |
| atlassian_jira_get_issue_types | Get available issue types for a project |
Atlassian — Confluence (8 tools)
| Tool | Description |
|------|-------------|
| atlassian_confluence_search | Search Confluence using CQL |
| atlassian_confluence_get_page | Get page content by ID |
| atlassian_confluence_create_page | Create a new page in a space |
| atlassian_confluence_update_page | Update an existing page |
| atlassian_confluence_delete_page | Delete a page |
| atlassian_confluence_list_spaces | List accessible Confluence spaces |
| atlassian_confluence_get_space | Get space details by key |
| atlassian_confluence_search_content | Search page content |
Grafana — Observability (5 tools)
| Tool | Description |
|------|-------------|
| grafana_list_datasources | Lists all Grafana datasources so callers can discover the Loki/Prometheus/Tempo datasource UIDs that the other tools require |
| grafana_query_prometheus | Queries a Prometheus datasource through Grafana; performs an instant query when start/end are omitted, or a range query when both start and end are provided |
| grafana_query_loki | Queries a Loki datasource through Grafana using LogQL and returns log streams for the given time range |
| grafana_loki_label_values | Lists Loki label names (when label is omitted) or the values for a specific label, used to discover available log-filtering dimensions |
| grafana_query_tempo | Queries a Tempo datasource through Grafana; fetches a specific trace by traceId, or searches for traces using TraceQL when traceId is omitted |
Code Mode (2 tools)
| Tool | Description |
|------|-------------|
| call_tool_chain | Preferred for multi-step operations. Execute JavaScript in a secure isolated-vm V8 sandbox with all MCP tools available as synchronous namespaced functions (gitlab.*, jira.*, confluence.*, grafana.*). Supports configurable timeout and memory limit. Use __interfaces or __getToolInterface(name) for tool schema introspection |
| search_tools | Search registered MCP tools by keyword — matches against name and description, returns full schema information |
Resource Templates
Resources provide direct read access to specific entities by URI:
| URI Template | Description |
|--------------|-------------|
| gitlab://project/{projectId} | GitLab project metadata |
| gitlab://project/{projectId}/file/{filePath} | File content from a GitLab repository |
| atlassian://jira/issue/{issueKey} | Jira issue details |
| atlassian://jira/project/{projectKey} | Jira project details |
| atlassian://confluence/page/{pageId} | Confluence page content |
| atlassian://confluence/space/{spaceKey} | Confluence space details |
Server Endpoints
| Endpoint | Method | Auth | Description |
|----------|--------|------|-------------|
| /mcp | POST | Required | MCP protocol (JSON-RPC over Streamable HTTP) |
| /health | GET | Not required | Health check and provider status |
Health check:
curl http://127.0.0.1:8919/healthReturns:
{
"healthy": true,
"status": "ok",
"providers": {
"gitlab": "ready",
"atlassian": "ready",
"grafana": "ready"
},
"uptime": 3600,
"version": "3.2.0"
}Daemon Files
| File | Purpose |
|------|---------|
| ~/.padua/mcp-auth.json | Bearer token, port, PID, start time |
| ~/.padua/mcp-server.pid | Daemon process ID |
| ~/.padua/mcp-providers.json | Provider configuration (downloaded from S3). Add a grafana provider block (with an https-only baseUrl) to enable the Grafana provider and its padua login auth step. Optionally include a read-only/Viewer-scoped token (shared service-account token) so developers skip the login prompt — note it is a shared secret stored in plaintext here (mode 0600) and in S3 |
| ~/.padua/tokens.db | Encrypted OAuth tokens (AES-256-GCM) |
| ~/.padua/encryption.key | Auto-generated encryption key |
| ~/Library/Logs/padua-mcp/server.log | Daemon log (macOS) — upstream API calls, tool errors, token refresh |
| ~/.local/share/padua/logs/server.log | Daemon log (Linux) |
Diagnostics
padua doctorMCP-specific checks:
- Node.js version (>= 20.0.0)
- MCP provider configuration
- Token store integrity
- Encryption key availability
- Port availability
- Daemon health
- GitLab and Atlassian API connectivity
Token Migration
If upgrading from the standalone padua-mcp Go server:
padua doctor --migrate-tokensTroubleshooting
| Issue | Solution |
|-------|----------|
| Daemon not starting | Run padua doctor for diagnostics |
| Port 8919 in use | padua login auto-kills orphaned processes; or set mcp.port in ~/.padua/padua.config.json |
| Token issues | Delete ~/.padua/tokens.db and ~/.padua/encryption.key, then run padua login |
| Legacy daemon running | pkill -f padua-mcp-daemon |
| Tools not appearing | Verify padua login completed steps 5-8; check padua doctor for provider status |
| 401 Unauthorized | Ensure your IDE config includes the Authorization: Bearer padua-mcp-local header; check daemon log for upstream API errors |
| Debugging API errors | Check ~/Library/Logs/padua-mcp/server.log (macOS) or ~/.local/share/padua/logs/server.log (Linux). Set PADUA_MCP_LOG_LEVEL=debug for verbose output |
| MCP reconnection fails | Upgrade to v2.0.15+ — the daemon now handles ungraceful disconnects automatically |
Downgrade to 1.x
npm install -g @padua/cli@1
pkill -f padua-mcp-daemonInit Command
Interactive configuration wizard that discovers all AWS accounts and roles via SSO, then generates AWS CLI profiles.
Basic Usage
padua init # Standard initialization
padua init --keep-existing # Preserve custom non-Padua profiles
padua init --force # Skip confirmation promptsOptions
| Flag | Description |
|------|-------------|
| --force | Overwrite existing config without prompting |
| --keep-existing | Preserve non-Padua profiles in ~/.aws/config |
| --no-browser | Don't auto-open browser for SSO authentication |
| -v, --verbose | Show detailed progress information |
| --no-color | Disable colored output |
Note: --force and --keep-existing are mutually exclusive.
What It Does
- Prerequisite Check - Validates required tools are installed (AWS CLI v2, npm, Docker, Session Manager Plugin)
- Environment Variable Detection - Warns if AWS environment variables are set that may interfere with SSO
- SSO Authentication - Authenticates with AWS SSO or reuses cached token
- Account Discovery - Discovers all AWS accounts and roles available via SSO
- Role Selection - Prompts user to select which role to use for profiles
- Backup Creation - Creates timestamped backup of existing
~/.aws/config - Config Generation - Deletes old config and generates fresh profiles
- Profile Preservation - Optionally merges back custom non-Padua profiles
Backup Behavior
- Location:
~/.aws/config.backup.YYYYMMDD-HHMMSS - Auto-cleanup: Keeps last 5 backups, removes older ones automatically
- Restoration:
cp ~/.aws/config.backup.* ~/.aws/config
Profile Preservation
By default, padua init deletes all existing profiles to ensure a clean state. Use --keep-existing to preserve custom profiles:
padua init --keep-existingHow it works:
- Identifies Padua-managed profiles by
sso_session = paduareference - Preserves all other profiles (custom configurations)
- Merges custom profiles back after generating Padua profiles
Environment Variable Warnings
If AWS environment variables are detected, you'll see:
WARNING: AWS environment variables detected
The following environment variables may interfere with SSO authentication:
AWS_PROFILE=development
AWS_DEFAULT_REGION=us-east-1
To unset (bash/zsh):
unset AWS_PROFILE AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_DEFAULT_REGION
Continue anyway? (y/N)Exit Codes
| Code | Meaning | |------|---------| | 0 | Success | | 1 | General error or mutually exclusive flags | | 2 | Missing required prerequisites | | 4 | Config write failed |
Troubleshooting
"SSO session 'padua' already exists"
- Run with
--forceflag to overwrite
Environment variables interfering
- Unset AWS variables before running init:
unset AWS_PROFILE AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_DEFAULT_REGION
Lost custom profiles
- Check backup:
ls -la ~/.aws/config.backup.* - Restore backup:
cp ~/.aws/config.backup.20260128-143055 ~/.aws/config - Or run
padua init --keep-existingto preserve custom profiles
Login Command
Authenticate to AWS SSO, CodeArtifact (npm), and ECR (Docker) with a single command.
Automatically reads AWS_PROFILE environment variable when no --profile flag is provided (works with paws).
Basic Usage
padua login # Full login (SSO + CodeArtifact + ECR)
padua login --profile staging # Use specific AWS profile
padua login --sso-only # SSO only, skip CodeArtifact and ECROptions
| Flag | Description |
|------|-------------|
| -p, --profile <name> | AWS SSO profile to use |
| --sso-only | Only authenticate to SSO |
| --local | Write CodeArtifact config to project .npmrc instead of global ~/.npmrc |
| -v, --verbose | Show detailed output |
| -q, --quiet | Suppress non-error output |
| --no-color | Disable colored output |
Exit Codes
| Code | Meaning | |------|---------| | 0 | Success (SSO + at least one other service) | | 1 | SSO succeeded but CodeArtifact and ECR both failed | | 2 | SSO failed (other services not attempted) |
What padua login replaces
# Before: 3 separate commands
aws sso login --profile development
aws codeartifact login --tool npm --repository npm-repo --domain my-domain \
--domain-owner 123456789012 --region ap-southeast-2 --profile development
aws ecr get-login-password --region ap-southeast-2 | \
docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-southeast-2.amazonaws.com
# After: 1 command
padua loginExample Output
[1/8] AWS SSO ...
✓ authenticated (profile: paduafg-development)
[2/8] S3 Config ...
✓ downloaded
[3/8] CodeArtifact (npm) ...
✓ configured
[4/8] ECR (Docker) ...
✓ configured
[5/8] GitLab Auth ...
✓ authenticated
[6/8] Atlassian Auth ...
✓ authenticated
[7/8] Grafana Auth ...
✓ authenticated
[8/8] MCP Daemon ...
✓ running (http://127.0.0.1:8919/mcp)
=== Login Results ===
SSO: ✓ OK
S3 Config: ✓ OK
CodeArtifact: ✓ OK
ECR: ✓ OK
GitLab: ✓ OK
Atlassian: ✓ OK
Grafana: ✓ OK
MCP Daemon: ✓ OK
Total: 8/8 services authenticatedConfiguration
Configuration is stored in ~/.padua/padua.config.json (created by padua init):
{
"defaultProfile": "development",
"region": "ap-southeast-2",
"codeartifact": {
"domain": "my-domain",
"domainOwner": "123456789012",
"repository": "npm-repo"
},
"ecr": {
"accountId": "123456789012",
"region": "ap-southeast-2"
}
}Profile Resolution Priority
- CLI flags (
--profile) PADUA_PROFILEenvironment variableAWS_PROFILEenvironment variabledefaultProfilein config file'default'
This means padua status automatically uses the profile set by paws or export AWS_PROFILE=....
Status Command
Check authentication status for all configured services with detailed AWS identity information.
Automatically reads AWS_PROFILE environment variable when no --profile flag is provided (works with paws).
Basic Usage
padua status # Check all services
padua status -p staging # Check with specific profile
padua status -q # Quiet mode (exit code only)Options
| Flag | Description |
|------|-------------|
| -p, --profile <name> | AWS profile to check |
| -q, --quiet | Only output if there are issues |
| --no-color | Disable colored output |
Example Output
AWS SSO
Status: Authenticated
Profile: paduafg-development
Account: 361485743373 (development)
Region: ap-southeast-2
Role: Developers
User: [email protected]
User ID: AROA123456789:[email protected]
CodeArtifact (npm)
Status: Authenticated
Registry: https://paduafg-361485743373.d.codeartifact.ap-southeast-2.amazonaws.com/npm/paduafg/
Expires: 12/4/2025, 7:30:00 PM (in 11 hours)
ECR (Docker)
Status: Authenticated
Registry: 361485743373.dkr.ecr.ap-southeast-2.amazonaws.comExit Codes
| Code | Meaning | |------|---------| | 0 | All services healthy | | 1 | One or more services have issues | | 2 | Configuration not found |
Doctor Command
Validate Padua CLI configuration and diagnose common issues. Helps troubleshoot problems with profiles, authentication, and prerequisites.
Basic Usage
padua doctor # Run all diagnostic checks
padua doctor --verbose # Show detailed diagnostic informationOptions
| Flag | Description |
|------|-------------|
| --fix | Attempt to auto-fix common issues (not yet implemented) |
| -v, --verbose | Show detailed diagnostic information |
| --no-color | Disable colored output |
Diagnostic Checks
The doctor command performs comprehensive validation:
- Config Validation - Verifies
~/.padua/padua.config.jsonexists and contains valid JSON - Config Schema - Validates field formats (account IDs, regions, domains, repositories)
- Profile Validation - Checks if
defaultProfileexists in~/.aws/config, suggests corrections for typos - Prerequisites - Checks AWS CLI, npm, Docker, Session Manager Plugin installation status and versions
- Authentication - Validates SSO, CodeArtifact, and ECR authentication status
- Installation - Compares current CLI version with latest published version on npm
- MCP Server - Node.js version (>= 20.0.0), MCP provider config, token store integrity, encryption key, port availability, daemon health, GitLab and Atlassian API connectivity
Use --migrate-tokens to migrate encrypted tokens from a legacy padua-mcp Go server database.
Example Output
🏥 Padua CLI Doctor
Config Validation
[✓] Config file: Found at ~/.padua/padua.config.json
[✓] Config schema: All fields valid
[✗] Default profile 'development' not found in ~/.aws/config
→ Did you mean 'paduafg-development'?
Prerequisites
[✓] AWS CLI: Installed (2.15.0)
[✓] npm: Installed (10.9.2)
[✓] Docker: Installed (29.1.3)
[⚠] Session Manager Plugin: Not installed
→ Required for tunneling features. Install: https://docs.aws.amazon.com/...
Authentication
[✓] SSO authentication: Authenticated as [email protected]
[✓] CodeArtifact authentication: Authenticated (project .npmrc)
[✓] ECR authentication: Authenticated
Installation
[⚠] CLI version: Current: 1.10.0, Latest: 1.11.0
→ Update with: npm install -g @padua/cli@latest
Summary: 1 error, 2 warningsExit Codes
| Code | Meaning | |------|---------| | 0 | All checks passed | | 1 | Issues or warnings found | | 2 | Config not found or invalid |
Use Cases
Troubleshooting login issues:
# Check why "padua login" fails
padua doctorVerifying setup after installation:
# Ensure all prerequisites are installed
padua doctorFinding profile typos:
# Get suggestions for misspelled profile names
padua doctor
# Example: Suggests 'paduafg-development' if you typed 'development'Profile Command
Interactive AWS profile selection with shell integration.
Basic Usage
padua profile # Interactive selection
padua profile --install # Install/upgrade the paws shell function (idempotent)
padua profile --setup # Output shell function for paws command
padua profile --list-only # List profiles (for scripts)
padua profile --select-only # Select and output name onlyOptions
| Flag | Description |
|------|-------------|
| --install | Install/upgrade the paws shell function in your shell profile (idempotent — safe to re-run) |
| --setup | Output the shell function (manual install; prints the marker-wrapped block) |
| --list-only | Output profile names only (one per line) |
| --select-only | Interactive select, output only the name |
| --no-color | Disable colored output |
Shell Integration (paws)
paws is a shell function that switches AWS profiles by setting AWS_PROFILE in your current shell session. All Padua commands (padua login, padua status, padua tunnel) automatically pick up the active profile.
Installation
Bash / Zsh — one idempotent command installs or upgrades the function:
padua profile --install && source ~/.zshrc # or: source ~/.bashrc--install writes the paws function (and tab completion) to your shell rc
inside managed markers. It is safe to re-run: it replaces the existing block in
place and migrates any older hand-installed block, so you never end up with a
duplicate. After it runs, source the rc file (or open a new terminal).
Upgrading from a previous version? Just run
padua profile --installagain — it replaces the old block and removes any pre-markerpawsyou installed manually. (Versions before 2.5.4 left the interactivepawspicker invisible — it appeared to hang untilCtrl+C;--installpicks up that fix.)
PowerShell — auto-install isn't supported yet; print the block and add it to
your $PROFILE:
padua profile --install # prints the managed block + instructions
# paste the block into $PROFILE, then:
. $PROFILEThe manual padua profile --setup (which prints the function for you to append)
still works for any shell, but --install is preferred for Bash/Zsh.
Usage
paws # Interactive profile selection (arrow keys)
paws <profile-name> # Switch to a specific profile directly
paws clear # Unset all AWS environment variables| Command | Description |
|---------|-------------|
| paws | Opens an interactive list of available SSO profiles |
| paws <name> | Sets AWS_PROFILE to the given profile name |
| paws clear | Unsets AWS_PROFILE, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_DEFAULT_REGION, AWS_REGION, and AWS_DEFAULT_PROFILE |
Tab Completion
Tab completion is included automatically with the shell function. Press Tab after typing paws to see available profiles and the clear subcommand.
Example Workflow
# Switch to development profile
paws paduafg-development
# AWS_PROFILE set to: paduafg-development
# Login using the active profile
padua login
# Check status
padua status
# Clear profile when done
paws clear
# AWS environment variables clearedTunnel Command
Create secure tunnels to AWS resources via SSM Session Manager.
Automatically reads AWS_PROFILE environment variable when no --profile flag is provided (works with paws).
Targets
| Target | Description | System Required |
|--------|-------------|-----------------|
| rds | Tunnel to RDS/Aurora databases | Yes (e.g., roma, padua-iam) |
| lb | Tunnel to internal ALB (host derived per account, e.g. preprod.int.paduasolutions.net:443) | No |
| opensearch | Tunnel to AWS OpenSearch / Elasticsearch domain (port 443 → local 9200) | Yes (used as logical name in output) |
| elasticsearch | Alias for opensearch | Yes |
Basic Usage
# RDS tunnel (requires system argument)
padua tunnel roma rds # Interactive (prompts for port/cluster)
padua tunnel roma rds -p paduafg-development # Use specific profile
# Load balancer tunnel (no system needed)
padua tunnel lb # Interactive (prompts for port, default 8443)
padua tunnel lb --local-port 9443 # Use specific local portOptions
| Flag | Description |
|------|-------------|
| -p, --profile <name> | AWS profile to use |
| --local-port <port> | Local port for the tunnel |
| --cluster <name> | RDS cluster or instance name (RDS only) |
| --domain <name> | OpenSearch domain name (OpenSearch only) — skips interactive selection |
| -v, --verbose | Show detailed output |
| --no-color | Disable colored output |
RDS System Configuration
Different systems use different EC2 instances as tunnel endpoints:
| System | EC2 Tag | Default Port | Default Cluster |
|--------|---------|--------------|-----------------|
| roma | bastion-host | 3306 (MySQL) | roma-backend |
| (others) | ${alias}-jumpbox | 5432 (PostgreSQL) | (none) |
Note: All three tunnel targets (
lb,rds,opensearch) derive the jumpbox EC2 Name tag viaaws sts get-caller-identityand look up the returned account ID in the embeddedPADUA_ACCOUNT_ALIASESmap (src/shared/aws-accounts.ts). The tag is constructed as<alias>-jumpbox(e.g. account361485743373→ aliasdevelopment→ tagdevelopment-jumpbox).romais the only system with an explicit override (bastion-host). If the account ID is not present in the map, the command fails with a clear error — there is no silent fallback.The
lbtarget additionally derives the internal ALB host from the same account, using the per-account sub-domain map mirrored from the infrastructurenetworkinglayer:development→dev.int.paduasolutions.net,preproduction→preprod.int.paduasolutions.net,playground→play.int.paduasolutions.net,production→int.paduasolutions.net(zone apex). Accounts without an internal ALB fail with a clear error rather than tunnelling to the wrong environment (IOPS-1312).
LB Tunnel Usage
The internal ALB uses path-based routing for most services. Once the tunnel is running:
# Path-based services (most services)
curl -k https://localhost:8443/echo/test
curl -k https://localhost:8443/wealth-summaries/healthz
curl -k https://localhost:8443/entity-management/api/v1/status
# Host-based services (permify)
curl -k https://localhost:8443/v1/permissions/check \
-H "Host: permify.dev.int.paduasolutions.net"Example Output (RDS)
Checking port 3306 availability...
✓ Port 3306 is available
Looking up bastion-host instance...
✓ Found instance: i-0abc123def456
Looking up RDS endpoint for roma-backend...
✓ Found endpoint: roma-backend.cluster-xxx.ap-southeast-2.rds.amazonaws.com
Starting tunnel...
System: roma
Profile: paduafg-development
Local port: 3306
Remote: roma-backend.cluster-xxx.ap-southeast-2.rds.amazonaws.com:3306
Via: i-0abc123def456 (bastion-host)
Press Ctrl+C to close the tunnelExample Output (LB)
Checking port 8443 availability...
✓ Port 8443 is available
Looking up jumpbox instance...
✓ Found instance: i-0abc123def456
Starting tunnel...
Profile: paduafg-development
Local port: 8443
Remote: dev.int.paduasolutions.net:443
Via: i-0abc123def456 (development-jumpbox)
Usage (path-based services):
curl -k https://localhost:8443/<service>/path
e.g. curl -k https://localhost:8443/echo/test
Usage (host-based services like permify):
curl -k https://localhost:8443/path -H "Host: <service>.dev.int.paduasolutions.net"
Press Ctrl+C to close the tunnelOpenSearch Tunnel Usage
# Interactive (lists domains, prompts for selection)
padua tunnel logs opensearch
padua tunnel logs opensearch -p paduafg-development
# Skip selection
padua tunnel logs opensearch --domain my-domain
padua tunnel logs opensearch --domain my-domain --local-port 9201
# elasticsearch alias works identically
padua tunnel logs elasticsearch --domain legacy-es-domainThe first positional argument (e.g. logs) is a logical system name shown in output — it does not affect domain discovery. Domains are listed via aws opensearch list-domain-names for the current profile/region.
Endpoint resolution: Endpoints.vpc is preferred. If the domain is public-only, the public Endpoint is used and a warning is printed. If neither exists, the command throws.
Ports: Remote is always 443 (HTTPS). Default local port is 9200.
Curl Examples
# Cluster health
curl -k https://localhost:9200/
# List indices
curl -k https://localhost:9200/_cat/indices?v
# OpenSearch Dashboards (formerly Kibana)
open https://localhost:9200/_dashboards/TLS and SigV4 Notes
-kis required. The domain's TLS certificate is for*.<region>.es.amazonaws.com, notlocalhost.curlrejects the mismatch without-k(or--insecure).- SigV4 over the tunnel breaks IAM signing. AWS SigV4 signs the
Hostheader. The signed host is<domain>.<region>.es.amazonaws.com, but the tunneled request hitslocalhost:9200, so signature verification fails on the AWS side.- Workarounds:
- Use a domain with Fine-Grained Access Control (FGAC) and authenticate with basic auth (
-u user:pass), not IAM. - Or use a domain with an open access policy (no auth) for read-only browse from a VPC.
- If you must use IAM, query the domain directly without a tunnel (from an EC2 in the VPC or via a SigV4-aware proxy).
- Use a domain with Fine-Grained Access Control (FGAC) and authenticate with basic auth (
- Workarounds:
Exec Command
Open an interactive shell in a running ECS container via SSM Execute Command.
Basic Usage
padua exec # Interactive (prompts for cluster/service/task/container)
padua exec -c my-cluster -s my-service # Specify cluster and service
padua exec -c my-cluster -s my-service -t abc123 --container app # Fully non-interactiveOptions
| Flag | Description |
|------|-------------|
| -p, --profile <name> | AWS profile to use |
| -c, --cluster <name> | ECS cluster name |
| -s, --service <name> | ECS service name |
| -t, --task <id> | ECS task ID |
| --container <name> | Container name |
| --command <cmd> | Command to run (default: /bin/bash) |
| -v, --verbose | Show detailed output |
| --no-color | Disable colored output |
Auto-selects when only one option exists at each level (cluster, service, task, container).
Bedrock Command
Configure Claude Code to use AWS Bedrock inference inside the paduafg-production account. All inference stays in ap-southeast-2 (AU data residency), and every bedrock:InvokeModel* call is logged in CloudTrail under paduafg-production.
Prerequisites
- Active
paduafg-productionSSO session (padua login -p paduafg-production) - IAM permissions:
bedrock:ListInferenceProfiles,bedrock:InvokeModel,bedrock:InvokeModelWithResponseStream,bedrock:GetInferenceProfile
Setup (one-time)
# Install pbedrock shell function
eval "$(padua bedrock --setup)"
# Add permanently to your shell profile
padua bedrock --setup >> ~/.zshrc # or ~/.bashrc
source ~/.zshrcDaily Use
pbedrock on # Enable Bedrock mode (discovers profiles, sets 8 env vars)
pbedrock off # Disable Bedrock mode (restores previous env)
pbedrock # Toggle
pbedrock status # Show current stateOr directly:
eval "$(padua bedrock enable --eval -p paduafg-production)"
eval "$(padua bedrock disable --eval)"
padua bedrock statusOptions
| Flag | Description |
|------|-------------|
| -p, --profile <name> | AWS SSO profile (default: paduafg-production) |
| -r, --region <region> | AWS region (default: ap-southeast-2) |
| --config-dir <path> | Custom Claude config directory |
| --eval | Output shell export statements only |
| --allow-non-prod | Allow non-production profiles |
| --setup | Output pbedrock shell function |
| --shell <shell> | Shell type for --setup: zsh, bash, or pwsh |
| -v, --verbose | Verbose output (never dumps env vars) |
| --no-color | Disable colored output |
Security
- Production-only default — non-
paduafg-productionprofiles are rejected unless--allow-non-prodis passed - Region pinned to
ap-southeast-2; inference profile ARNs must start withap-southeast- - All exported values are shell-escaped to prevent injection via
eval $HOMEcontainment guard on the default config directory- Subprocess env hardened via
getSubprocessEnv()whitelist — no secret leakage to child processes - Verbose mode never dumps environment variables
What pbedrock on sets
| Variable | Value |
|----------|-------|
| CLAUDE_CODE_USE_BEDROCK | 1 |
| CLAUDE_CONFIG_DIR | ~/.claude-bedrock |
| CLAUDE_CONFIG_DIR_BEFORE_BEDROCK | Previous CLAUDE_CONFIG_DIR value |
| ANTHROPIC_MODEL | Latest APAC claude-3-5-sonnet profile ID |
| ANTHROPIC_DEFAULT_OPUS_MODEL | Latest APAC claude-opus profile ID |
| ANTHROPIC_DEFAULT_SONNET_MODEL | Latest APAC claude-3-5-sonnet profile ID |
| ANTHROPIC_DEFAULT_HAIKU_MODEL | Latest APAC claude-3-5-haiku profile ID |
| AWS_REGION | ap-southeast-2 |
Planned Features
The following commands are planned for future releases:
padua tunnel ec2 <name> # SSM session to EC2 instanceDevelopment
git clone <repository-url>
cd padua-cli
npm install
npm run build
npm link # Makes 'padua' available globally
npm test # Run tests
npm run test:coverage # Run tests with coverageLicense
MIT
