Note
This project was written by AI (Claude Code).
A Git-like CLI/GUI for AWS Parameter Store and Secrets Manager. Familiar commands like show, log, diff, and a staging workflow for safe, reviewable changes.
- Git-like commands:
show,log,diff,ls,create,update,rm - Staging workflow:
edit→status→diff→apply(review changes before applying) - Version navigation:
#VERSION,~SHIFT,:LABELsyntax - Colored diff output: Easy-to-read unified diff format
- Both services: SSM Parameter Store and Secrets Manager
- GUI mode: Desktop application via
--guiflag (built with Wails)
Using Homebrew (macOS/Linux)
# Full version (CLI + GUI)
brew install mpyw/tap/suve
# CLI-only version (no GUI dependencies, recommended for Linux)
brew install mpyw/tap/suve-cliNote
On Linux, suve requires GTK3 and WebKit2GTK for GUI support. Use suve-cli if you only need CLI functionality.
Using Scoop (Windows)
scoop bucket add mpyw https://github.com/mpyw/scoop-bucket.git
scoop install suveLinux (.deb / .rpm)
Download packages from GitHub Releases:
Debian/Ubuntu (.deb):
export VERSION=0.0.0
export ARCH=amd64 # or arm64
export WEBKIT_SUFFIX="" # use "_webkit2_41" for Ubuntu 24.04+
# CLI-only (recommended, no GUI dependencies)
curl -LO "https://github.com/mpyw/suve/releases/download/v${VERSION}/suve-cli_${VERSION}-1_${ARCH}.deb"
sudo dpkg -i "suve-cli_${VERSION}-1_${ARCH}.deb"
# Full version (CLI + GUI, requires GTK3 and WebKit2GTK)
curl -LO "https://github.com/mpyw/suve/releases/download/v${VERSION}/suve${WEBKIT_SUFFIX}_${VERSION}-1_${ARCH}.deb"
sudo dpkg -i "suve${WEBKIT_SUFFIX}_${VERSION}-1_${ARCH}.deb"Note: Ubuntu 22.04/Debian uses webkit2gtk-4.0 (default). Ubuntu 24.04+ uses webkit2gtk-4.1 (set WEBKIT_SUFFIX="_webkit2_41").
Red Hat/Fedora (.rpm):
export VERSION=0.0.0
export ARCH=x86_64 # or aarch64
export WEBKIT_SUFFIX="" # use "_webkit2_41" for Fedora 40+
# CLI-only (recommended, no GUI dependencies)
curl -LO "https://github.com/mpyw/suve/releases/download/v${VERSION}/suve-cli-${VERSION}-1.${ARCH}.rpm"
sudo rpm -i "suve-cli-${VERSION}-1.${ARCH}.rpm"
# Full version (CLI + GUI, requires GTK3 and WebKit2GTK)
curl -LO "https://github.com/mpyw/suve/releases/download/v${VERSION}/suve${WEBKIT_SUFFIX}-${VERSION}-1.${ARCH}.rpm"
sudo rpm -i "suve${WEBKIT_SUFFIX}-${VERSION}-1.${ARCH}.rpm"Note: Fedora 39 and earlier uses webkit2gtk-4.0 (default). Fedora 40+ uses webkit2gtk-4.1 (set WEBKIT_SUFFIX="_webkit2_41").
Using go install (CLI only)
go install github.com/mpyw/suve/cmd/suve@latestNote: go install builds CLI only. GUI requires pre-built assets that are not included in the Go module. For GUI support, use a package manager or build from source.
Using go tool (CLI only, Go 1.24+)
# Add to go.mod as a tool dependency
go get -tool github.com/mpyw/suve/cmd/suve@latest
# Run via go tool
go tool suve param show /my/paramBuilding from Source
For platforms without pre-built packages (e.g., Arch Linux) or if you need the latest development version with GUI:
git clone https://github.com/mpyw/suve.git
cd suveCLI only:
make build
# Binary: bin/suveCLI + GUI (requires Wails CLI and Node.js):
go install github.com/wailsapp/wails/v2/cmd/wails@latest
cd gui && wails build -tags production -skipbindings
# Binary: gui/build/bin/guiBuild dependencies for GUI:
| Platform | Dependencies |
|---|---|
| All | Node.js (for frontend build) |
| macOS | Xcode Command Line Tools |
| Windows | WebView2 Runtime (usually pre-installed) |
Linux build dependencies and webkit2gtk-4.1 support
Linux requires GTK3 and WebKit2GTK:
| Platform | Dependencies |
|---|---|
| Ubuntu 22.04/Debian | sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev |
| Ubuntu 24.04+ | sudo apt install libgtk-3-dev libwebkit2gtk-4.1-dev |
| Fedora 39 | sudo dnf install gtk3-devel webkit2gtk4.0-devel |
| Fedora 40+ | sudo dnf install gtk3-devel webkit2gtk4.1-devel |
| Arch Linux | sudo pacman -S gtk3 webkit2gtk-4.1 |
For webkit2gtk-4.1 (Ubuntu 24.04+, Fedora 40+, Arch Linux), use the webkit2_41 build tag:
cd gui && wails build -tags production,webkit2_41 -skipbindingsTip
Using with aws-vault: Wrap commands with aws-vault exec for temporary credentials:
aws-vault exec my-profile -- suve param show /my/paramuser@host:~$ suve param show /app/config/database-url
Name: /app/config/database-url
Version: 3
Type: SecureString
Modified: 2024-01-15T10:30:45Z
postgres://db.example.com:5432/myapp
user@host:~$ suve param show --raw /app/config/database-url
postgres://db.example.com:5432/myappThe show command displays value with metadata; --raw outputs raw value for piping:
# Use in scripts
DB_URL=$(suve param show --raw /app/config/database-url)
# Pipe to file
suve param show --raw /app/config/ssl-cert > cert.pemView version history, just like git log:
user@host:~$ suve param log /app/config/database-url
Version 3 (current)
Date: 2024-01-15T10:30:45Z
postgres://db.example.com:5432/myapp...
Version 2
Date: 2024-01-14T09:20:30Z
postgres://old-db.example.com:5432/myapp...
Version 1
Date: 2024-01-13T08:10:00Z
postgres://localhost:5432/myapp...Use --patch to see what changed in each version:
user@host:~$ suve param log --patch /app/config/database-urlOutput will look like:
Version 3 (current)
Date: 2024-01-15T10:30:45Z
--- /app/config/database-url#2
+++ /app/config/database-url#3
@@ -1 +1 @@
-postgres://old-db.example.com:5432/myapp
+postgres://db.example.com:5432/myapp
Version 2
Date: 2024-01-14T09:20:30Z
--- /app/config/database-url#1
+++ /app/config/database-url#2
@@ -1 +1 @@
-postgres://localhost:5432/myapp
+postgres://old-db.example.com:5432/myappTip
Add --parse-json to pretty-print JSON values before diffing. This normalizes formatting and sorts keys alphabetically, so you can focus on the actual content changes rather than formatting differences:
suve param log --patch --parse-json /app/config/credentialsCompare previous version with latest (most common use case):
user@host:~$ suve param diff /app/config/database-url~Output will look like:
--- /app/config/database-url#2
+++ /app/config/database-url#3
@@ -1 +1 @@
-postgres://old-db.example.com:5432/myapp
+postgres://db.example.com:5432/myappCompare any two specific versions:
user@host:~$ suve param diff /app/config/database-url#1 /app/config/database-url#3Output will look like:
--- /app/config/database-url#1
+++ /app/config/database-url#3
@@ -1 +1 @@
-postgres://localhost:5432/myapp
+postgres://db.example.com:5432/myappNote
The staging workflow lets you prepare changes locally, review them, and apply when ready—just like git add → git diff --staged → git commit.
For detailed state transition rules, see Staging State Transitions.
Caution
Staged values are stored in plain text at ~/.suve/<ACCOUNT_ID>/<REGION>/stage.json. If you no longer need pending changes, run suve stage reset --all to clear them.
1. Stage changes (opens editor or accepts value directly):
Tip
To use VSCode or Cursor as your editor, set export VISUAL='code --wait' or export VISUAL='cursor --wait' in your shell profile.
user@host:~$ suve stage param add /app/config/new-param "my-value"
✓ Staged for creation: /app/config/new-param
user@host:~$ suve stage param edit /app/config/database-url
✓ Staged: /app/config/database-url
user@host:~$ suve stage param delete /app/config/old-param
✓ Staged for deletion: /app/config/old-param2. Review staged changes:
user@host:~$ suve stage status
Staged SSM Parameter Store changes (3):
A /app/config/new-param
M /app/config/database-url
D /app/config/old-param
user@host:~$ suve stage diffOutput will look like:
--- /app/config/database-url#3 (AWS)
+++ /app/config/database-url (staged)
@@ -1 +1 @@
-postgres://db.example.com:5432/myapp
+postgres://new-db.example.com:5432/myapp
--- /app/config/new-param (not in AWS)
+++ /app/config/new-param (staged for creation)
@@ -0,0 +1 @@
+my-value
--- /app/config/old-param#2 (AWS)
+++ /app/config/old-param (staged for deletion)
@@ -1 +0,0 @@
-deprecated-value3. Apply changes:
user@host:~$ suve stage apply
Applying SSM Parameter Store parameters...
✓ Created /app/config/new-param
✓ Updated /app/config/database-url
✓ Deleted /app/config/old-paramReset if needed:
# Unstage specific parameter
suve stage param reset /app/config/database-url
# Unstage all
suve stage reset --allTip
suve stage apply prompts for confirmation before applying. Use --yes to skip the prompt.
Navigate versions with Git-like syntax.
Note
SSM Parameter Store uses numeric version numbers (1, 2, 3, ...) that auto-increment on each update.
<name>[#VERSION][~SHIFT]*
where ~SHIFT = ~ | ~N (repeatable, cumulative)
| Syntax | Description |
|---|---|
/my/param |
Latest version |
/my/param#3 |
Version 3 |
/my/param~1 |
1 version ago |
/my/param#5~2 |
Version 5 minus 2 = Version 3 |
/my/param~~ |
2 versions ago (~1~1) |
Note
Secrets Manager uses UUID version IDs and staging labels instead of numeric versions.
AWSCURRENT and AWSPREVIOUS are special labels automatically managed by AWS—AWSCURRENT always points to the latest version.
<name>[#VERSION | :LABEL][~SHIFT]*
where ~SHIFT = ~ | ~N (repeatable, cumulative)
| Syntax | Description |
|---|---|
my-secret |
Current (AWSCURRENT) |
my-secret:AWSPREVIOUS |
Previous staging label |
my-secret#abc123 |
Specific version ID |
my-secret~1 |
1 version ago |
Important
When specifying version-only syntax like '#3' or ':AWSPREVIOUS', you must use quotes to prevent shell interpretation of the # (comment) or : characters.
Tip
~ without a number means ~1. You can chain them: ~~ = ~1~1 = ~2
| Service | Aliases |
|---|---|
| SSM Parameter Store | param, ssm, ps |
| Secrets Manager | secret, sm |
| Command | Options | Description |
|---|---|---|
suve param show |
--raw--parse-json (-j)--no-pager--output=<FORMAT> |
Display parameter with metadata |
suve param log |
--number=<N> (-n)--patch (-p)--parse-json (-j)--oneline--reverse--since=<DATE>--until=<DATE>--no-pager--output=<FORMAT> |
Show version history |
suve param diff |
--parse-json (-j)--no-pager--output=<FORMAT> |
Compare versions |
suve param list |
--recursive (-R)--filter=<REGEX>--show--output=<FORMAT> |
List parameters |
suve param create |
--type=<TYPE>--secure--description=<TEXT> |
Create a new parameter |
suve param update |
--type=<TYPE>--secure--description=<TEXT>--yes |
Update an existing parameter |
suve param delete |
--yes |
Delete parameter |
suve param tag |
<KEY>=<VALUE>... |
Add or update tags |
suve param untag |
<KEY>... |
Remove tags |
Staging commands (under suve stage param):
| Command | Options | Description |
|---|---|---|
suve stage param add |
--description=<TEXT> |
Stage new parameter |
suve stage param edit |
--description=<TEXT> |
Stage modification |
suve stage param delete |
Stage deletion | |
suve stage param status |
--verbose (-v) |
Show staged changes |
suve stage param diff |
--parse-json (-j)--no-pager |
Compare staged vs AWS |
suve stage param apply |
--yes--ignore-conflicts |
Apply staged changes |
suve stage param reset |
--all |
Unstage changes |
suve stage param tag |
<KEY>=<VALUE>... |
Stage tag additions |
suve stage param untag |
<KEY>... |
Stage tag removals |
| Command | Options | Description |
|---|---|---|
suve secret show |
--raw--parse-json (-j)--no-pager--output=<FORMAT> |
Display secret with metadata |
suve secret log |
--number=<N> (-n)--patch (-p)--parse-json (-j)--oneline--reverse--since=<DATE>--until=<DATE>--no-pager--output=<FORMAT> |
Show version history |
suve secret diff |
--parse-json (-j)--no-pager--output=<FORMAT> |
Compare versions |
suve secret list |
--filter=<REGEX>--show--output=<FORMAT> |
List secrets |
suve secret create |
--description=<TEXT> |
Create new secret |
suve secret update |
--description=<TEXT>--yes |
Update existing secret |
suve secret delete |
--force--recovery-window=<DAYS>--yes |
Delete secret |
suve secret restore |
Restore deleted secret | |
suve secret tag |
<KEY>=<VALUE>... |
Add or update tags |
suve secret untag |
<KEY>... |
Remove tags |
Staging commands (under suve stage secret):
| Command | Options | Description |
|---|---|---|
suve stage secret add |
--description=<TEXT> |
Stage new secret |
suve stage secret edit |
--description=<TEXT> |
Stage modification |
suve stage secret delete |
--force--recovery-window=<DAYS> |
Stage deletion |
suve stage secret status |
--verbose (-v) |
Show staged changes |
suve stage secret diff |
--parse-json (-j)--no-pager |
Compare staged vs AWS |
suve stage secret apply |
--yes--ignore-conflicts |
Apply staged changes |
suve stage secret reset |
--all |
Unstage changes |
suve stage secret tag |
<KEY>=<VALUE>... |
Stage tag additions |
suve stage secret untag |
<KEY>... |
Stage tag removals |
| Command | Options | Description |
|---|---|---|
suve stage status |
--verbose (-v) |
Show all staged changes |
suve stage diff |
--parse-json (-j)--no-pager |
Compare all staged vs AWS |
suve stage apply |
--yes--ignore-conflicts |
Apply all staged changes |
suve stage reset |
--all |
Unstage all changes |
suve respects the TZ environment variable for date/time formatting:
# Show times in UTC
TZ=UTC suve param show /app/config
# Show times in Japan Standard Time
TZ=Asia/Tokyo suve param show /app/configAll timestamps are formatted in RFC3339 format with the local timezone offset applied. If TZ is not set, the system's local timezone is used. Invalid timezone values fall back to UTC.
suve uses standard AWS SDK configuration:
Authentication (in order of precedence):
- Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN) - Shared credentials file (
~/.aws/credentials) and config (~/.aws/config)- Use
AWS_PROFILEto specify which profile to load (default:default)
- Use
- IAM role (EC2, ECS, Lambda)
Region:
AWS_REGIONorAWS_DEFAULT_REGIONenvironment variable~/.aws/configfile
Warning
Ensure your IAM role/user has appropriate permissions:
- SSM:
ssm:GetParameter,ssm:GetParameters,ssm:GetParameterHistory,ssm:PutParameter,ssm:DeleteParameter,ssm:DescribeParameters,ssm:AddTagsToResource,ssm:RemoveTagsFromResource - SM:
secretsmanager:GetSecretValue,secretsmanager:ListSecretVersionIds,secretsmanager:ListSecrets,secretsmanager:CreateSecret,secretsmanager:PutSecretValue,secretsmanager:UpdateSecret,secretsmanager:DeleteSecret,secretsmanager:RestoreSecret,secretsmanager:TagResource,secretsmanager:UntagResource
# Run tests
make test
# Run linter
make lint
# Build CLI (without GUI)
make build
# Build with GUI support
go build -tags production -o bin/suve ./cmd/suve
# Run E2E tests (requires Docker)
make e2e
# Coverage (unit + E2E combined)
make coverage-allTo test against localstack instead of real AWS:
# Start localstack
SUVE_LOCALSTACK_EXTERNAL_PORT=4566 docker compose up -d
# Run commands with localstack
AWS_ENDPOINT_URL=http://127.0.0.1:4566 \
AWS_ACCESS_KEY_ID=dummy \
AWS_SECRET_ACCESS_KEY=dummy \
AWS_DEFAULT_REGION=us-east-1 \
suve param ls
# GUI with localstack
AWS_ENDPOINT_URL=http://127.0.0.1:4566 \
AWS_ACCESS_KEY_ID=dummy \
AWS_SECRET_ACCESS_KEY=dummy \
AWS_DEFAULT_REGION=us-east-1 \
suve --gui
# Stop localstack
docker compose downImportant
Dummy credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) are required to prevent the SDK from attempting IAM role credential fetching.
MIT License

