TUI Showcase
A visual tour of the ORAS .NET CLI’s interactive terminal interface — powered by Spectre.Console.
Every screen below is a faithful reproduction of real TUI output. Launch it yourself with oras (no arguments).
Dashboard
The main entry point when you run oras with no arguments in an interactive terminal. Shows connected registries, auth status, and a quick-actions menu.
██████╗ ██████╗ █████╗ ███████╗
██╔═══██╗██╔══██╗██╔══██╗██╔════╝
██║ ██║██████╔╝███████║███████╗
██║ ██║██╔══██╗██╔══██║╚════██║
╚██████╔╝██║ ██║██║ ██║███████║
╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝
OCI Registry As Storage │ v0.3.0 • Interactive Terminal UI
─────────────────────────────────────────────
╭── Connected Registries ──────────────────────────────────────╮
│ │
│ Registry Status │
│ ──────────────────────────────────────────── │
│ ghcr.io ● Authenticated │
│ localhost:5000 ● Authenticated │
│ myregistry.azurecr.io ○ No credentials │
│ │
╰──────────────────────────────────────────────────────────────╯
Select an action:
❯ Browse Registry
Browse Repository Tags
Login
Artifacts
───
Quit
Version 0.3.0 highlights:
- Unicode Block Art Banner — Hand-crafted ORAS logo with brand colors (O=#D04485 pink, R=#5EBAB4 teal, A=#FCFCFD white, S=#CCF575 lime)
- Rich Color Scheme — Cyan headers, green success indicators, yellow warnings
- Unicode Status Symbols —
✔(success),✗(error),ℹ(info),⚠(warning) for rich terminal rendering - Registry Status —
● Authenticated(green) /○ No credentials(grey) for all registries (auths, credHelpers, and credsStore) - UTF-8 Output — Console output encoding explicitly set to UTF-8 to prevent garbled characters
- Artifacts Sub-Menu — Push, Pull, Copy, Tag, Backup, Restore grouped under a dedicated “Artifacts” menu entry
- Cyclic Navigation — All menus wrap around (↓ from last item → first, ↑ from first → last)
- Non-Selectable Separators —
───line before Quit/Back visually separates exit actions (usesAddChoiceGroup) - In-Memory Caching — Fast repeat operations with cache indicators
- Fully Interactive Workflows — No more “use CLI” messages; all operations have complete TUI flows
How to launch:
# Auto-launches when stdin is a TTY and no arguments are provided
oras
Registry Browser
Hierarchical, searchable repository and tag browser. Select a registry from stored credentials or enter a new URL, then drill into repositories and tags.
✔ Connected to ghcr.io
Repositories in ghcr.io (Total: 12):
Type to search...
❯ Enter repository name...
myorg/webapp
myorg/api-service
myorg/ml-model
myorg/helm-charts
myorg/signatures
myorg/sbom-store
team/frontend
team/backend
team/infra-configs
demo/hello-oras
(Move up and down to reveal more options)
When a registry doesn’t support the catalog API (like ghcr.io, ECR, or Docker Hub’s non-public repositories), the registry browser shows a helpful message:
ℹ This registry does not support repository listing (e.g., ghcr.io)
Enter repository name...
(Type a repository path like "oras-project/oras")
Even when the catalog is available, you can always select “Enter repository name…” to jump directly to a specific repository without browsing the full list.
After selecting a repository:
Tags for myorg/webapp (Total: 8):
Type to search...
❯ latest
v2.1.0
v2.0.0
v1.5.3
v1.5.2
v1.0.0
sha-a1b2c3d
nightly-20260305
Back to repository list
How to launch:
# Browse from the dashboard
oras
# → Select "Browse Registry"
# Or jump directly to a registry
oras --registry ghcr.io
Direct Repository Browse
Skip the registry browser and jump straight to a repository’s tags. Perfect for browsing specific repositories on registries that don’t support the catalog API.
Enter full reference (e.g., ghcr.io/oras-project/oras):
ghcr.io/oras-project/oras
After entering a full reference:
Tags for ghcr.io/oras-project/oras (Total: 15):
Type to search...
❯ latest
v1.2.1
v1.2.0
v1.1.0
v1.0.5
v1.0.0
sha-a1b2c3d
nightly-20260305
(Move up and down to reveal more options)
How to launch:
# From the dashboard
oras
# → Select "Browse Repository Tags"
# → Enter: ghcr.io/oras-project/oras
# Or jump directly with flags
oras --registry ghcr.io --repository oras-project/oras
Copy, Backup & Restore
Three powerful workflows for managing artifacts across local and remote storage.
Copy Artifact
Copy OCI artifacts between registries with live progress tracking.
Copy Workflow:
Enter source reference:
ghcr.io/myorg/webapp:v2.1.0
After entering the source:
✔ Source: ghcr.io/myorg/webapp:v2.1.0
Enter destination reference:
docker.io/myorg/webapp:v2.1.0
During copy:
Copying ghcr.io/myorg/webapp:v2.1.0 → docker.io/myorg/webapp:v2.1.0
✔ sha256:a3ed95 config.json ━━━━━━━━━━━━━━━━━━━━ 100% 1.5 KB --
✔ sha256:e1b2f3 app-binary.tar.gz ━━━━━━━━━━━━━━━━━━━━ 100% 45.6 MB --
sha256:c4d5e6 static-assets.tar.gz ━━━━━━━━━━━━━━━░░░░░ 78% 12.3 MB 24.5 MB/s 0:03
Copying ━━━━━━━━━━━━━━░░░░░░ 66% 2/3 blobs
Include referrers (signatures, SBOMs)? [y/N] y
✔ Copied with 1 referrer
Backup Artifact
Save registry artifacts to a local OCI layout directory or tar archive.
Backup Workflow:
Enter reference to backup:
ghcr.io/myorg/webapp:v2.1.0
After entering the reference:
Backing up ghcr.io/myorg/webapp:v2.1.0
✔ sha256:a3ed95 config.json ━━━━━━━━━━━━━━━━━━━━ 100% 1.5 KB --
✔ sha256:e1b2f3 app-binary.tar.gz ━━━━━━━━━━━━━━━━━━━━ 100% 45.6 MB --
✔ sha256:c4d5e6 static-assets.tar.gz ━━━━━━━━━━━━━━━━━━━━ 100% 15.8 MB --
Backup ━━━━━━━━━━━━━━━━━━━━ 100% 3/3 blobs
After completion:
╭─ Backup Summary ──────────────────────────────────────────────╮
│ │
│ ✔ Backup completed successfully │
│ │
│ Reference: ghcr.io/myorg/webapp:v2.1.0 │
│ Blobs: 3 │
│ Size: 62.9 MB │
│ Location: ./oras-backup │
│ Format: OCI Layout │
│ │
╰───────────────────────────────────────────────────────────────╯
Restore Artifact
Push artifacts from a local backup to a registry.
Restore Workflow:
Enter path to backup (directory or .tar.gz):
./oras-backup
After entering the path:
Enter destination reference:
ghcr.io/myorg/webapp-restored:v2.1.0
During restore:
Restoring ./oras-backup → ghcr.io/myorg/webapp-restored:v2.1.0
✔ sha256:a3ed95 config.json ━━━━━━━━━━━━━━━━━━━━ 100% 1.5 KB --
✔ sha256:e1b2f3 app-binary.tar.gz ━━━━━━━━━━━━━━━━━━━━ 100% 45.6 MB --
✔ sha256:c4d5e6 static-assets.tar.gz ━━━━━━━━━━━━━━━━━━━━ 100% 15.8 MB --
Restoring ━━━━━━━━━━━━━━━━━━━━ 100% 3/3 blobs
✔ Restored to ghcr.io/myorg/webapp-restored:v2.1.0
Digest: sha256:7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b
How to launch:
# From the TUI dashboard
oras
# → Select "Copy Artifact", "Backup Artifact", or "Restore Artifact"
# Or use CLI commands directly
oras copy ghcr.io/source/artifact:v1 ghcr.io/dest/artifact:v1
oras backup ghcr.io/myorg/artifact:v1.0 --output ./backup
oras restore ./backup ghcr.io/myorg/artifact-restored:v1.0
Real-time per-layer progress bars with transfer speed, percentage, and ETA. Uses a custom TransferSpeedColumn for human-readable bandwidth display.
Pushing
Pushing to ghcr.io/myorg/webapp:v2.1.0 (3 layers)
✓ sha256:a3ed95 config.json ━━━━━━━━━━━━━━━━━━━━ 100% 1.5 KB --
✓ sha256:e1b2f3 app-binary.tar.gz ━━━━━━━━━━━━━━━━━━━━ 100% 45.6 MB --
sha256:c4d5e6 static-assets.tar.gz ━━━━━━━━━━━━━━━━░░░░ 78% 12.3 MB 24.5 MB/s 0:03
Pushing ━━━━━━━━━━━━━━━░░░░░ 66% 2/3 layers
Pulling
Pulling from ghcr.io/myorg/webapp:v2.1.0 (3 layers)
✓ sha256:a3ed95 config.json ━━━━━━━━━━━━━━━━━━━━ 100% 1.5 KB --
✓ sha256:e1b2f3 app-binary.tar.gz ━━━━━━━━━━━━━━━━━━━━ 100% 45.6 MB --
✓ sha256:c4d5e6 static-assets.tar.gz ━━━━━━━━━━━━━━━━━━━━ 100% 15.8 MB --
Pulling ━━━━━━━━━━━━━━━━━━━━ 100% 3/3 layers
Pulled ghcr.io/myorg/webapp:v2.1.0
Digest: sha256:7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b
Non-TTY fallback (piped / CI)
Pulling (3 layers)
[1/3] sha256:a3ed95 config.json (1.5 KB)
✓ sha256:a3ed95 config.json (1.5 KB)
[2/3] sha256:e1b2f3 app-binary.tar.gz (45.6 MB)
✓ sha256:e1b2f3 app-binary.tar.gz (45.6 MB)
[3/3] sha256:c4d5e6 static-assets.tar.gz (15.8 MB)
✓ sha256:c4d5e6 static-assets.tar.gz (15.8 MB)
Pulled ghcr.io/myorg/webapp:v2.1.0
How to launch:
# Push with live progress
oras push ghcr.io/myorg/webapp:v2.1.0 ./app-binary.tar.gz ./static-assets.tar.gz
# Pull with live progress
oras pull ghcr.io/myorg/webapp:v2.1.0
# Pipe-safe — auto-detects non-TTY and uses plain text
oras pull ghcr.io/myorg/webapp:v2.1.0 | tee pull.log
Manifest Inspector
Drill into any manifest with a menu-driven inspector. View the raw JSON, a structural layer tree, config blob contents, or trigger actions like pull/copy/delete.
Inspector Menu
── Manifest Inspector: ghcr.io/myorg/webapp:v2.1.0 ─────────────────
Select an option:
❯ View Manifest JSON
View Layer Tree
View Config Blob
Actions (Pull/Copy/Delete)
Back to tag list
Manifest JSON
╭─ Manifest JSON ────────────────────────────────────────────────────╮
│ { │
│ "schemaVersion": 2, │
│ "mediaType": "application/vnd.oci.image.manifest.v1+json", │
│ "config": { │
│ "mediaType": "application/vnd.oci.image.config.v1+json", │
│ "digest": "sha256:a3ed95caeb02...", │
│ "size": 1536 │
│ }, │
│ "layers": [ │
│ { │
│ "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", │
│ "digest": "sha256:e1b2f3c4d5e6...", │
│ "size": 47839885 │
│ }, │
│ { │
│ "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", │
│ "digest": "sha256:c4d5e6f7a8b9...", │
│ "size": 16567910 │
│ } │
│ ] │
│ } │
╰────────────────────────────────────────────────────────────────────╯
Layer Tree
╭─ Layer Tree ───────────────────────────────────────────────────────╮
│ │
│ Manifest (application/vnd.oci.image.manifest.v1+json) │
│ ├── config (application/vnd.oci.image.config.v1+json) │
│ │ └── sha256:a3ed95caeb02... (1.5 KB) │
│ ├── layers (2 total) │
│ │ ├── [0] application/vnd.oci.image.layer.v1.tar+gzip │
│ │ │ └── sha256:e1b2f3c4d5e6... (45.6 MB) │
│ │ └── [1] application/vnd.oci.image.layer.v1.tar+gzip │
│ │ └── sha256:c4d5e6f7a8b9... (15.8 MB) │
│ └── referrers (1 total) │
│ └── application/vnd.example.sbom.v1 │
│ └── sha256:sbom123abc... (4 KB) │
│ │
╰────────────────────────────────────────────────────────────────────╯
How to launch:
# From the TUI browser — select a tag to open the inspector
oras --registry ghcr.io --repository myorg/webapp
# Or inspect a manifest directly from CLI
oras manifest fetch ghcr.io/myorg/webapp:v2.1.0
Tag Management
View tags in a styled table with digests, compressed sizes, and timestamps. Add or remove tags through the TUI or CLI.
Tag Table (--format text)
╭──────────────────┬──────────────────────┬──────────┬─────────────────────╮
│ Tag │ Digest │ Size │ Created │
├──────────────────┼──────────────────────┼──────────┼─────────────────────┤
│ latest │ sha256:7a8b9c0d1e2f │ 62.9 MB │ 2026-03-06 14:22 │
│ v2.1.0 │ sha256:7a8b9c0d1e2f │ 62.9 MB │ 2026-03-06 14:22 │
│ v2.0.0 │ sha256:d4e5f6a7b8c9 │ 61.2 MB │ 2026-02-28 09:15 │
│ v1.5.3 │ sha256:1a2b3c4d5e6f │ 58.7 MB │ 2026-02-14 11:03 │
│ v1.5.2 │ sha256:f0e1d2c3b4a5 │ 58.5 MB │ 2026-02-01 16:47 │
│ v1.0.0 │ sha256:9f8e7d6c5b4a │ 52.1 MB │ 2026-01-10 08:30 │
│ sha-a1b2c3d │ sha256:7a8b9c0d1e2f │ 62.9 MB │ 2026-03-06 14:22 │
│ nightly-20260305 │ sha256:b2c3d4e5f6a7 │ 63.4 MB │ 2026-03-05 02:00 │
╰──────────────────┴──────────────────────┴──────────┴─────────────────────╯
Tag Table (--format json)
[
{"tag":"latest","digest":"sha256:7a8b9c0d1e2f...","size":65958707,"created":"2026-03-06T14:22:00Z"},
{"tag":"v2.1.0","digest":"sha256:7a8b9c0d1e2f...","size":65958707,"created":"2026-03-06T14:22:00Z"}
]
Adding Tags
ℹ Enter tags separated by spaces (e.g., v1.0 latest stable):
Tags: stable production
ℹ Tag command: oras tag ghcr.io/myorg/webapp:v2.1.0 stable production
✔ Tagged ghcr.io/myorg/webapp:v2.1.0
How to launch:
# List tags from CLI
oras repo tags ghcr.io/myorg/webapp
# Tag an artifact
oras tag ghcr.io/myorg/webapp:v2.1.0 stable production
# Or manage tags interactively from the TUI inspector
oras --registry ghcr.io --repository myorg/webapp
Interactive Selection
Multi-select prompts powered by MultiSelectionPrompt for batch operations — select multiple repositories, tags, or artifacts in one go.
Multi-Select Tags for Batch Delete
Select tags to delete:
(Press <space> to select, <enter> to accept)
[×] nightly-20260305
[×] sha-a1b2c3d
[ ] latest
[ ] v2.1.0
[ ] v2.0.0
[ ] v1.5.3
[ ] v1.5.2
[ ] v1.0.0
Confirmation for Destructive Actions
⚠ You are about to delete: ghcr.io/myorg/webapp:nightly-20260305
⚠ Digest: sha256:b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3
⚠ Size: 63.4 MB
Are you sure you want to delete this manifest? [y/N] y
✔ Deleted ghcr.io/myorg/webapp:nightly-20260305
Multi-Select Repositories for Batch Pull
Select repositories to pull:
(Press <space> to select, <enter> to accept)
[×] myorg/webapp:latest
[×] myorg/api-service:v3.0.0
[ ] myorg/ml-model:v1.2
[×] team/frontend:stable
[ ] team/backend:latest
[ ] demo/hello-oras:latest
How to launch:
# Multi-select is available throughout the TUI
oras
# Batch operations from the CLI
oras tag ghcr.io/myorg/webapp:v2.1.0 stable production release-candidate
Color Reference
The TUI uses a deliberate color palette via Spectre.Console styles:
| Element | Symbol | Usage |
|---|---|---|
| Success | ✔ (green) | Completed operations, authenticated status |
| Info | ℹ (cyan) | Informational messages, tips |
| Warning | ⚠ (yellow) | Cautions, destructive-action prompts |
| Error | ✗ (red) | Error messages, failed operations |
Symbols are Unicode for rich terminal rendering.
Requirements
The interactive TUI requires a terminal that supports:
- ANSI escape codes — virtually all modern terminals (Windows Terminal, iTerm2, GNOME Terminal, etc.)
- Unicode — for box-drawing characters and status icons
- Interactive stdin — TUI auto-disables when output is piped or redirected
When the environment is non-interactive (CI pipelines, redirected output), all commands gracefully fall back to plain text with no escape codes.
# Force non-interactive mode
oras pull ghcr.io/myorg/webapp:v2.1.0 --no-tty
Ready to try it? Install the CLI and run oras to explore.