██
██
██ _ ____ _ _____
██ / \ | _ \ | | | ____|
██ / _ \ | | | || | | _|
██ / ___ \ | |_| || |___ | |___
▄██▄ /_/ \_\|____/ |_____||_____|
██████
▀████▀
Edit S3, Google Cloud Storage, and Azure Blob Storage files directly from your terminal. One command.
ladle s3://mybucket/config.json
ladle gs://mybucket/config.json
ladle az://mycontainer/config.jsonDownload, edit in your favorite editor, diff, confirm, upload — all in one shot. No manual download/upload, no web console, no scripts.
- One command to edit —
ladle s3://bucket/fileopens, edits, diffs, and uploads - Metadata too —
ladle --meta s3://bucket/fileedits ContentType, CacheControl, etc. as YAML - Any terminal editor — vim, emacs, nano — set
EDITORor--editor - Safe by default — colored diff + confirmation before every upload
- Pipe & redirect — works in shell pipelines and scripts with auto-detection
- Browse & filter — interactive TUI browser with vim-style
/search
$ ladle s3://myapp/config.json
Downloading s3://myapp/config.json ...
Temp file: /tmp/ladle-123/config.json
(your editor opens, you make changes, save and close)
File: s3://myapp/config.json
--- original
+++ modified
@@ -1,3 +1,3 @@
{
- "debug": false,
+ "debug": true,
"port": 8080
}
Upload changes? [y/N]: y
Uploading to s3://myapp/config.json ...
Done.
$ ladle --meta s3://myapp/index.html
Fetching metadata for s3://myapp/index.html ...
(editor opens with YAML)
# s3://myapp/index.html
ContentType: text/html
CacheControl: max-age=3600
Metadata:
author: alice
(change CacheControl, save and close)
--- original
+++ modified
@@ -2,3 +2,3 @@
ContentType: text/html
-CacheControl: max-age=3600
+CacheControl: max-age=86400
Metadata:
Update metadata? [y/N]: y
Done.
Metadata updates use the S3 CopyObject API — no re-upload of file content.
ladle detects shell redirection so you can use it in pipelines and scripts — no interactive editor needed.
# Download to local file
ladle s3://myapp/config.json > config.json
# Upload from local file (shows diff, asks confirmation)
ladle s3://myapp/config.json < config.json
# Skip confirmation
ladle --yes s3://myapp/config.json < config.json
# Preview changes without uploading
ladle --dry-run s3://myapp/config.json < config.json
# Export / import metadata as YAML
ladle --meta s3://myapp/index.html > meta.yaml
ladle --meta s3://myapp/index.html < meta.yaml
# Transform and re-upload
ladle s3://myapp/config.json | jq '.debug = true' | ladle --yes s3://myapp/config.json
# List objects/buckets (one URI per line; directories keep trailing /).
# Redirect or pipe so stdout is non-TTY — a bare terminal opens the TUI browser instead.
ladle s3://myapp/config/ > objects.txt # objects + subdirectories under config/
ladle s3:// | grep myapp # all buckets, as s3://<bucket>/
# List an object's versions (tab-separated: id, modified, size, latest, delete-marker)
ladle --versions s3://myapp/config.json > versions.tsvWhen stdout is redirected, a directory URI (or bare scheme) prints a listing and --versions prints version history, instead of opening the interactive TUI.
When stdin is redirected, confirmation reads from /dev/tty. Use --yes to skip in non-interactive environments. If the object doesn't exist yet, stdin upload creates it as a new object.
$ ladle s3://myapp/
██ _ ___ _ ____
██ /_\ | _ \| | | __|
▄▄██▄ / _ \| | || |__| _|
██████_/ \_\___/|____|____|
▀██▀ v1.0.0
s3://myapp
> 📁 config/
📁 static/
📝 index.html 2.1 KB 2026-02-19 02:08
📝 readme.md 1.3 KB 2026-02-19 02:08
..
/ index▏
↑/↓ navigate ←/→ collapse/expand enter select - up / filter esc×2 quit
↑/↓navigate,←/→expand/collapse directories/to filter — incremental search across expanded treeEnterto edit a file, then return to the browser→on a file to open the context menu-to go up a directory
Press → on a file to open the context menu:
s3://myapp
📁 config/
📁 static/
> 📝 index.html 2.1 KB 2026-02-19 02:08
📝 readme.md 1.3 KB 2026-02-19 02:08
..
╭──────────────────╮
│ index.html │
│ > Edit │
│ Edit metadata │
│ Download to... │
│ Copy to... │
│ Move to... │
│ Versions │
│ Delete │
╰──────────────────╯
↑/↓ navigate enter select esc/← close
| Action | Description |
|---|---|
| Edit | Open the file in your editor |
| Edit metadata | Edit ContentType, CacheControl, etc. as YAML |
| Download to... | Download to a local directory (tab completion supported) |
| Copy to... | Copy to another key in the same bucket |
| Move to... | Move to another key in the same bucket |
| Versions | View version history and restore a previous version (S3 / GCS / Azure Blob versioning) |
| Delete | Delete the object (with confirmation) |
View and restore previous versions of objects (requires versioning enabled — S3 bucket versioning, GCS object versioning, or Azure Blob versioning).
# Open version history directly
ladle --versions s3://myapp/config.json ██ _ ___ _ ____
██ /_\ | _ \| | | __|
▄▄██▄ / _ \| | || |__| _|
██████_/ \_\___/|____|____|
▀██▀ v1.0.0
s3://myapp
╭──────────────────────────────────────╮ ╭──────────────────────────────────╮
│ Versions: config.json │ │ Preview │
│ > aB3dE6fG7h1i 2026-02-27 10:30 │ │ { │
│ 812 B (current) │ │ "debug": true, │
│ kL9mN0pQ2r3s 2026-02-26 14:15 │ │ "port": 8080, │
│ 795 B │ │ "host": "0.0.0.0" │
│ tU4vW5xY6z7a 2026-02-25 09:00 │ │ } │
│ 780 B │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
╰──────────────────────────────────────╯ ╰──────────────────────────────────╯
↑/↓ navigate enter restore ctrl-d/u scroll preview esc back esc×2 quit
The version view shows a list of versions on the left with a content preview on the right. Use ↑/↓ to navigate versions, Ctrl-d/Ctrl-u to scroll the preview, and Enter to restore a selected version.
You can also access version history from the browser's context menu by selecting Versions on any file.
ssm:// edits AWS Systems Manager Parameter Store parameters with the same
edit → diff → confirm flow. Parameter Store has no buckets: the whole path after
the scheme is the parameter name, normalized to a single leading slash, so
ssm://myapp/db and ssm:///myapp/db both mean /myapp/db.
# Edit a parameter value in your editor
ladle ssm:///myapp/prod/db-url
# Read / write via pipes (agent- and script-friendly)
ladle ssm:///myapp/prod/db-url > value.txt # read value to stdout
echo -n 'postgres://new/db' | ladle --yes ssm:///myapp/prod/db-url
# Create a new parameter (defaults to String; use --type for others)
echo -n 's3cret' | ladle --yes --type SecureString ssm:///myapp/prod/api-token
# List a path (directories keep a trailing slash); --recursive for the whole tree
ladle ssm:///myapp/prod/
ladle ssm:///myapp/ --recursive
# Version history (tab-separated: version, mtime, type, modified-by, LATEST)
ladle --versions ssm:///myapp/prod/db-url
# Parameter attributes as YAML (type, tier, keyId, description, dataType)
ladle --meta ssm:///myapp/prod/db-password
ladle --meta ssm:///myapp/prod/db-password > meta.yamlSecureString values are never exposed by default. Any operation that would
reveal plaintext — editing, piping the value out, or diffing an update — refuses
unless you pass --reveal:
ladle --reveal ssm:///myapp/prod/db-password # decrypt and edit
ladle --reveal ssm:///myapp/prod/db-password > secret # decrypt to stdoutNotes:
- On write, the original KMS key (
keyId) and other attributes are preserved. - Editing a SecureString's metadata re-writes the parameter (SSM has no
metadata-only API), so
--metaon a SecureString also needs--reveal. - A SecureString value can still be updated non-interactively without
--revealby using--yes, which skips the (plaintext) diff (e.g.echo -n "$SECRET" | ladle --yes ssm:///myapp/prod/db-password). - Piping into a new parameter creates a
Stringunless you pass--type(String|StringList|SecureString), so secrets aren't stored in cleartext by accident. - Temp files are created
0600in a private directory and removed on exit.
Required IAM actions (scopable to the parameter / path ARN):
ssm:GetParameter (read), ssm:GetParametersByPath (list & browse),
ssm:GetParameterHistory (metadata & --versions), ssm:PutParameter (write),
and ssm:DeleteParameter (browser delete / move); plus kms:Decrypt /
kms:Encrypt on the key for SecureString.
Interactive directory URIs open the same TUI browser as S3 (tree navigation,
/ filter, and a context menu for edit / metadata / versions / download /
copy / move / delete). A name that is actually a namespace (has children but is
not itself a parameter) opens the browser too, so a missing trailing slash still
works. When stdout is redirected/piped, a listing is printed instead. In the
browser, SecureString values are masked in the version-preview pane unless
--reveal is set.
brew install jingu/tap/ladlego install github.com/jingu/ladle/cmd/ladle@latestDownload the binary for your platform from Releases.
ladle --profile production s3://bucket/file.html
ladle --region ap-northeast-1 s3://bucket/file.html
ladle --endpoint-url http://localhost:9000 s3://bucket/file.html # MinIO
ladle --no-sign-request s3://public-bucket/file.htmlladle supports Google Cloud Storage via the gs:// scheme:
ladle gs://bucket/path/to/file.html
ladle gs://bucket/path/to/ # file browser mode
ladle --project myproject gs:// # list bucketsCredentials are resolved via Application Default Credentials (ADC):
GOOGLE_APPLICATION_CREDENTIALSpointing at a service account key filegcloud auth application-default login- the attached service account when running on GCP (GCE, Cloud Run, GKE, etc.)
gcloud auth application-default login
ladle gs://bucket/file.htmlListing buckets (ladle gs://) requires a project ID, set via --project or the
GOOGLE_CLOUD_PROJECT environment variable. Use --no-sign-request for public
buckets, and --endpoint-url (or STORAGE_EMULATOR_HOST) to target the
fake-gcs-server emulator.
ladle supports Azure Blob Storage via the az:// scheme, where the container
maps to the bucket and the blob maps to the key:
ladle --account myaccount az://container/path/to/file.html
ladle az://container/path/to/file.html # with AZURE_STORAGE_ACCOUNT set
ladle az:// # list containersThe storage account and credentials are resolved in this priority order:
AZURE_STORAGE_CONNECTION_STRING— full connection string- account name (
--accountorAZURE_STORAGE_ACCOUNT) +AZURE_STORAGE_KEY— shared key - account name +
AZURE_STORAGE_SAS_TOKEN— SAS token - account name + Azure AD (
DefaultAzureCredential, e.g.az loginor Managed Identity)
export AZURE_STORAGE_ACCOUNT=myaccount
export AZURE_STORAGE_KEY=... # or
export AZURE_STORAGE_CONNECTION_STRING=... # or just `az login` for Azure AD
ladle az://container/file.htmlUse --endpoint-url to target the Azurite emulator.
| Flag | Short | Description |
|---|---|---|
--meta |
Edit object metadata instead of file content | |
--versions |
Show version history for a file (S3 / GCS / Azure Blob versioning) | |
--editor |
Editor command (overrides env vars) | |
--yes |
-y |
Skip confirmation prompt |
--dry-run |
Show diff without uploading | |
--force |
Force editing of binary files | |
--reveal |
Decrypt and expose SecureString values (ssm://) |
|
--recursive |
List parameters recursively (ssm://) |
|
--type |
Type when creating a new ssm:// parameter (String|StringList|SecureString) |
|
--profile |
AWS named profile | |
--region |
AWS region | |
--account |
Azure storage account name (or AZURE_STORAGE_ACCOUNT) |
|
--project |
GCP project ID for bucket listing (or GOOGLE_CLOUD_PROJECT) |
|
--endpoint-url |
Custom endpoint URL (MinIO, LocalStack, Azurite, fake-gcs-server, etc.) | |
--no-sign-request |
Do not sign requests | |
--install-completion |
Generate shell completion script (bash|zsh|fish) |
ladle selects an editor in this order:
--editorflagLADLE_EDITORenvironment variableEDITORenvironment variableVISUALenvironment variablevi(fallback)
# bash
ladle --install-completion bash >> ~/.bashrc
# zsh
ladle --install-completion zsh >> ~/.zshrc
# fish
ladle --install-completion fish > ~/.config/fish/completions/ladle.fishladle ships an Agent Skill that teaches AI coding agents how to read, edit, and inspect cloud storage objects with ladle (using pipe mode so it works non-interactively).
# Install for Claude Code (user-global: ~/.claude/skills/ladle/SKILL.md)
ladle skill install
# Install into the current project (.claude/skills/ladle/SKILL.md)
ladle skill install --project
# Overwrite an existing install
ladle skill install --force
# Print the skill to stdout
ladle skill show- Cloudflare R2 (
r2://) backend - Multi-file batch editing
ladle comparefor diffing two remote files
MIT