1. Cookbook¶
Common recipes for daily aws-tui use. Each recipe is end-to-end — commands you can copy/paste plus the in-app key sequence.
- Connect to and switch between data sources
- Switch the theme on the fly
- Customize a keybinding
- Resume after a crash
1.1. Connect to and switch between data sources¶
Walks through three setups people hit on day one:
- §1.1–§1.5 — connect to a local MinIO from scratch (the canonical "first s3-compatible endpoint" walkthrough).
- §1.6 — jump between AWS profiles with one keystroke (multi-account flows).
- §1.7 — run several
s3-compatibleendpoints side-by-side.
You have a MinIO running on http://localhost:9000 with the dev
credentials minioadmin / minioadmin. Goal: a minio-local
connection in aws-tui that points at it.
1.1.1. Start MinIO (skip if already running)¶
Quickest path — dev seeded MinIO (recommended for first-time exploration; ships ~5 buckets and ~90 objects so you have content to navigate):
scripts/test-services/s3/up.sh
This wraps docker compose + seed.py and prints the config snippet
to add to <config-dir>/config.toml. Teardown is
scripts/test-services/s3/down.sh (add --purge to wipe the data
volume). See scripts/test-services/README.md for the seeded
dataset and how to extend it.
Plain MinIO (no seed):
docker run --rm -d --name minio \
-p 127.0.0.1:9000:9000 -p 127.0.0.1:9001:9001 \
-e MINIO_ROOT_USER=minioadmin \
-e MINIO_ROOT_PASSWORD=minioadmin \
minio/minio:RELEASE.2025-09-07T16-13-09Z@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e server /data --console-address ":9001"
1.1.2. Store the credentials in the macOS Keychain (recommended)¶
The resolver expects two required keychain entries under ONE service name
(matching the credentials = "keychain:<service>" value in
config.toml): one account named access_key_id and one named
secret_access_key. Temporary credentials may also provide an
optional session_token account. So for a keychain:minio-local
config entry:
# service="minio-local", account="access_key_id"
security add-generic-password \
-s minio-local -a access_key_id -w minioadmin
# service="minio-local", account="secret_access_key"
security add-generic-password \
-s minio-local -a secret_access_key -w minioadmin
# optional, only for temporary credentials
security add-generic-password \
-s minio-local -a session_token -w '<session-token>'
(The Python keyring library aws-tui uses delegates to the macOS
Keychain by default.)
1.1.3. Add via the in-TUI Settings form¶
Open Settings with ,, add an S3-compatible connection, and fill the
form:
| Field | Value |
|---|---|
| Name | minio-local |
| Endpoint URL | http://localhost:9000 |
| Region | us-east-1 |
| Access key ID | minioadmin |
| Secret access key | minioadmin |
| Session token | Optional; only for temporary credentials |
That writes a static entry to config.toml. Note: every launch with
a static-credentials connection emits a warning toast, per the
credential-source preference order documented in
connections.md §1.2;
the recommended path is to migrate to a keychain: source once
you've verified the connection works. To do that, edit your config
file (see docs/platforms.md for the path on each OS)
and change:
[connections.minio-local]
kind = "s3-compatible"
endpoint_url = "http://localhost:9000"
credentials = "keychain:minio-local"
force_path_style = true
verify_tls = false # http:// MinIO -> no cert to verify
1.1.4. Add by editing the file directly¶
If you already have other connections, just append:
[connections.minio-local]
kind = "s3-compatible"
endpoint_url = "http://localhost:9000"
credentials = "static" # tells the resolver to use inline keys below
access_key_id = "minioadmin"
secret_access_key = "minioadmin"
force_path_style = true
verify_tls = false # http:// MinIO → no cert to verify
For multiple S3-compatible services, just add more
[connections.<name>] blocks — the <name> (e.g. minio-local,
r2-prod, b2-archive) becomes the source identifier shown in
the pane's bottom border (s3-compatible · minio-local · localhost:9000).
Region is optional and intentionally not displayed for
s3-compatible connections — MinIO/R2/B2/etc. don't have a
meaningful region, so the pane title shows name · endpoint
instead.
1.1.5. Use it¶
aws-tui
Then in-app, press Shift+S on the focused pane to cycle
through every available source — local → every TOML /
auto-discovered connection → wrap. AWS profiles auto-discovered
from ~/.aws/credentials show up as
aws s3 · {profile} · {region}; TOML s3-compatible entries
show up as s3-compatible · {name} · {endpoint}. Tap
Shift+S until the pane title reads
s3-compatible · minio-local · {endpoint} — the bucket list
should populate immediately.
The dedicated command-palette path (
: connection switch ▸ minio-local) is spec'd but deferred to v0.9 — in v0.8.x:opens the help overlay as a placeholder.Shift+Sis the one-keystroke equivalent today.
1.1.6. Jump between AWS profiles with one keystroke¶
If you have several [profile *] blocks in ~/.aws/config (typical
for orgs with multiple AWS accounts or SSO permission sets), Shift+S
is the fastest way to flip between them. Each press re-mounts the
focused pane on the next profile in the cycle; the pane's bottom
border subtitle (aws s3 · {profile} · {region}) tells you which
identity you're on.
~/.aws/config:
[profile dev]
region = us-east-1
sso_session = my-org
[profile staging]
region = us-east-1
sso_session = my-org
[profile prod]
region = us-west-2
sso_session = my-org
In-app:
- Shift+S → left pane re-mounts on
aws s3 · dev · us-east-1. - Shift+S →
aws s3 · staging · us-east-1. - Shift+S →
aws s3 · prod · us-west-2.
Per-pane independence: put dev on the left and prod on the right,
then c to copy an object between them — CrossFsCopy streams S3→S3
without an intermediate local hop.
The cycle also includes any s3-compatible entries from
config.toml and the local filesystem. Add MinIO / R2 / B2 / Wasabi
connections via the in-app Settings nav page (,) — they join
the cycle immediately, no relaunch.
Expired SSO tokens are detected offline at launch via the SSO cache freshness probe (see connections.md §3); expired or missing SSO profiles are skipped by the boot chain, marked unreachable for the session, and surfaced through a recovery toast while the app mounts local panes instead of hanging. Run
aws sso login --profile <name>and relaunch, or use the explicit retry path when prompted.
1.1.7. Run several s3-compatible endpoints side-by-side¶
There's no fixed limit on how many s3-compatible connections you
can configure. Each one shows up in the swap-source cycle and in
the in-app Settings page. Example config covering a local MinIO, a
Cloudflare R2 production bucket, and a Backblaze B2 archive:
# <config-dir>/config.toml
[connections.minio-local]
kind = "s3-compatible"
credentials = "static"
endpoint_url = "http://localhost:9000"
region = "us-east-1"
access_key_id = "minioadmin"
secret_access_key = "minioadmin"
force_path_style = true
verify_tls = false
[connections.r2-prod]
kind = "s3-compatible"
credentials = "static"
endpoint_url = "https://<account>.r2.cloudflarestorage.com"
region = "auto"
access_key_id = "<r2-key-id>"
secret_access_key = "<r2-secret>"
force_path_style = false
[connections.b2-archive]
kind = "s3-compatible"
credentials = "static"
endpoint_url = "https://s3.us-west-002.backblazeb2.com"
region = "us-west-002"
access_key_id = "<b2-key-id>"
secret_access_key = "<b2-secret>"
force_path_style = false
Then Shift+S cycles through all three (plus your AWS profiles and
local) on the focused pane. If you'd rather edit interactively, open
Settings (,) → "S3-Compatible Connections" section → "+ Add"
to enter the same data through the inline form, or use the per-row
Edit / Delete chips to manage entries already there. Saves are
atomic (tempfile + os.replace) so the config can't end up
half-written.
See docs/connections.md §4
for the full source-cycle semantics and the unreachable-skip behavior.
1.2. Switch the theme on the fly¶
1.2.1. One-off (session-only)¶
Two paths, both fire ThemeChangedMessage and reload the active
stylesheet instantly without a restart:
- Press
tto open the theme picker modal, arrow to the theme you want, hit Enter. - Press
Shift+T(T) to cycle straight to the next theme without the modal — handy when you just want to flip carbon ↔ voidline.
The command-palette path (
:thentheme switch ▸ voidline) is spec'd in the design but not wired in v0.8.x — the palette registers no entries yet, sot/Shift+Tare the working shortcuts.
1.2.2. Persistent¶
# <config-dir>/config.toml
[defaults]
theme = "voidline"
Theme names: carbon (default), voidline, lattice, amber,
solarized-light, github-light, one-light, nord, dracula,
gruvbox-dark. See theming.md §1 for
the full per-theme palette breakdown.
1.2.3. Add a custom theme¶
Copy src/aws_tui/ui/themes/carbon.tcss to
<config-dir>/themes/midnight.tcss, edit the palette tokens,
and pick it from the theme picker (t) like any built-in. See
theming.md for the full token table.
1.2.4. Tweak just one or two colors¶
Drop <config-dir>/theme.tcss and override what you need; the
overlay layers on top of the active built-in:
/* <config-dir>/theme.tcss */
.modal-title { color: #ff3df8; }
Footer { background: #050505; }
1.3. Customize a keybinding¶
v0.8.x status: the composition root reads
[keybindings], validates action ids throughKeymapStore, and logs/falls back to defaults when an overlay is invalid. Runtime dispatch still usesAwsTuiApp.BINDINGS, so user overrides are future-ready config and do not change command chips or live keys until the post-v0.8 input-router work lands.
Future-ready example: rebind copy (pane.copy) from c to y (vim yank).
# <config-dir>/config.toml
[keybindings]
"pane.copy" = "y"
For a fallback list (try Ctrl+K first, fall back to :):
[keybindings]
"app.command_palette" = ["Ctrl+K", ":"]
1.3.1. Disable a default binding¶
Set the action to an empty list:
[keybindings]
"pane.delete" = [] # nope, no quick delete
When the input router lands, an empty [keybindings] value will remove
the keybinding until you edit the config back. In v0.8.x the table is
validated but does not change live dispatch, so d still follows
AwsTuiApp.BINDINGS.
1.3.2. See the active map¶
The full list of action IDs lives in
docs/keybindings.md and is the same set
declared in src/aws_tui/infra/keymap_store.py:DEFAULT_BINDINGS. There
is no --print-bindings CLI flag in v0.8; the launch path enters the
TUI directly.
1.3.3. Unknown action IDs fall back to defaults¶
If you overlay an action id that isn't in KeymapStore.DEFAULT_BINDINGS
(e.g. typo pane.cpy), startup logs the UnknownAction and falls back
to the default keymap. That's deliberate: a bad override should not make
the TUI unlaunchable, and the log still gives maintainers the exact
action id to fix.
1.4. Resume after a crash¶
Long-running transfers leave local journals so interrupted work can be inspected or cleaned up. Full startup resume and explicit S3 multipart replay remain deferred in v0.8.x; this recipe documents the current journal shape plus the planned modal flow.
1.4.1. What gets saved¶
The production transfer path writes a begin line and a terminal
finished or aborted line to <cache-dir>/transfers/<id>.jsonl:
{"kind":"begin","transfer_id":"abc123","source_uri":"local:///x.bin","destination_uri":"s3://bucket/x.bin","bytes_total":104857600,"upload_id":null,"ts":"2026-06-13T23:45:11Z"}
{"kind":"finished","ts":"2026-06-13T23:45:18Z"}
The journal schema can also replay optional part lines and an
upload_id for future explicit-MPU flows, but the current S3 transfer
path delegates multipart internals to boto and does not record those
values.
1.4.2. What happens on next launch¶
v0.8.x writes durable transfer journals, but startup scanning and the
resume modal are not wired yet. The planned modal flow will scan
TransferJournal.find_unfinished() after the connection resolves and
surface entries that lack a terminal record:
2 transfers from a previous session were not finished.
- api-2026-06-13.json (3.4 M / 4.2 M, 82%)
- db-slowq-06-13.csv (279 k / 892 k, 31%)
[abort all] [decide each] [keep for later]
| Choice | What it does |
|---|---|
| abort all | Planned: mark journals aborted, purge them, and call AbortMultipartUpload only for entries that carry an upload_id. The current production transfer path does not record S3 MPU IDs yet, so bucket lifecycle cleanup remains the server-side backstop. |
| decide each | Deferred in v0.8.x: equivalent to keep for later until the per-entry modal lands. |
| keep for later | Planned: no mutation; once startup scanning is wired, the modal will show again on next launch. |
1.4.3. Manual cleanup¶
If you want to nuke the journals without going through the modal:
rm -f "<cache-dir>"/transfers/*.jsonl
For S3 uploads that were interrupted outside aws-tui's normal cancel path, the 1-day MPU abort lifecycle rule is the server-side backstop.
1.4.4. What gets dumped on a crash¶
If aws-tui hits an unhandled exception, it writes
<cache-dir>/crash/<ts>.txt:
aws-tui crash dump
timestamp: 2026-06-14T12:00:00+00:00
exception: TypeError: unsupported operand type(s) for +: ...
== traceback ==
...
== log tail ==
... (last 1000 lines of aws-tui.log)
The crash dump writer is live in v0.8.x. The interactive crash modal below exists as UI scaffolding but is not wired into the unhandled exception path yet:
unexpected error
TypeError: ...
<cache-dir>/crash/2026-06-14T12-00-00.txt
[view trace] [continue] [quit]
The planned continue button is enabled only when the last user action was
read-only (navigation, refresh, filter, palette open). Writes
(delete, copy, move, rename) disable it — you can't safely continue a
write that may have partially executed.