A terminal UI for managing Laravel applications running inside Docker containers — locally or on remote servers over SSH.
- Multi-server support — connect to any number of SSH servers or use your local Docker socket
- Container browser — lists all running Docker containers with favorites, custom display names, and filtering
- Artisan commands — full autocomplete list of all
php artisancommands with descriptions - Composer commands — browse and run composer scripts; auto-downloads
composer.pharif not installed - npm scripts — browse and run scripts from
package.json - Custom commands — define reusable command groups per container or globally in config
- Interactive shell — run any command with live stdin/stdout streaming
- Log viewer — tail Laravel logs, Docker stdout/stderr, and host service logs (nginx, php-fpm, supervisor, etc.) with lazy chunk loading and line-wrap toggle
- Docker commands — inspect, restart, stats, top, diff, network info, and more
- PostgreSQL management — connect to any PostgreSQL container, browse databases, run SQL queries, explore schema, maintenance queries, and download compressed dumps
- SQL query history — per-database persistent history with
↑↓navigation (stored in~/.config/laradok/sql_history.json)
brew install alexbabintsev/tap/laradokUpgrade later with brew upgrade laradok.
git clone https://github.com/alexbabintsev/laradok
cd laradok
go build -o laradok .
mv laradok /usr/local/bin/- Docker installed and accessible on target hosts
- SSH key-based auth for remote servers (or
ssh-agent) - Go 1.22+ (only for building from source)
Default config path: ~/.config/laradok/config.yaml
Override with:
laradok /path/to/config.yaml
# or
LARADOK_CONFIG=/path/to/config.yaml laradok# No config needed — laradok auto-adds a local server if none are defined.commands:
- name: "Cache"
commands:
- label: "cache:clear"
cmd: "php artisan cache:clear"
desc: "Flush the application cache"
- name: "Database"
commands:
- label: "migrate"
cmd: "php artisan migrate --force"
desc: "Run database migrations"
- label: "migrate:rollback"
cmd: "php artisan migrate:rollback"
desc: "Rollback the last migration"
servers:
- name: "Production"
host: "your-server.com"
port: 22
user: "root"
key: "~/.ssh/id_ed25519"
type: ssh
containers:
- name: "myapp-*" # glob pattern supported
display_name: "My App"
favorite: true
root_path: "/var/www/html" # default, can be omitted
custom_logs:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
commands:
- name: "Horizon"
commands:
- label: "horizon:status"
cmd: "php artisan horizon:status"
desc: "Get the current status of Horizon"
- name: "Local Dev"
type: local| Field | Type | Description |
|---|---|---|
name |
string | Docker container name or glob pattern (e.g. app-*) |
display_name |
string | Custom label shown in the container list |
favorite |
bool | Pin to top of list with a star indicator |
hidden |
bool | Hide from container list entirely |
root_path |
string | Path to Laravel root inside container (default: /var/www/html) |
custom_logs |
[]string | Extra log file paths shown in Server Logs |
commands |
[]CommandGroup | Per-container command groups (appear before global commands) |
laradok tries auth methods in this order:
- Explicit
key:path from config (with optionalpassphrase:) ssh-agent(viaSSH_AUTH_SOCK)- Standard key files:
~/.ssh/id_ed25519,~/.ssh/id_rsa,~/.ssh/id_ecdsa, etc.
laradok # use default config
laradok ~/.config/laradok/config.yaml| Key | Action |
|---|---|
↑ / ↓ / j / k |
Navigate list |
Enter |
Select / run |
Esc |
Go back |
PgUp / PgDn |
Scroll by page |
F2 |
Toggle line wrapping (output screens) |
Ctrl+C |
Quit |
After selecting a container, the main menu offers:
| Option | Description | Shown when |
|---|---|---|
| Commands | Browse configured command groups | container has custom commands in config |
| Artisan Commands | Full php artisan list with autocomplete |
artisan file found |
| Composer Commands | Browse and run composer scripts | composer or php found |
| Npm Commands | Browse and run npm scripts | npm found |
| Docker Commands | Container management (inspect, restart, stats…) | always |
| Custom Command | Interactive shell with live stdin | always |
| Laravel Logs | Browse and tail storage/logs/*.log files |
artisan file found |
| Docker Logs | Stream container stdout/stderr | always |
| Server Logs | Tail nginx, php-fpm, supervisor logs | always |
| Database | PostgreSQL management (see below) | psql found |
| Download Storage | Archive and download storage/ to ~/Downloads/ |
artisan file found |
| File Browser | Walk the container filesystem, view sizes, download any file or folder as .tar.gz |
always |
Menu items are detected automatically with a single docker exec probe when the container is opened. A spinner is shown during detection.
Select a PostgreSQL container from the container list, then choose Database from the main menu.
laradok auto-detects credentials from the container's environment variables (POSTGRES_USER, POSTGRES_PASSWORD). If POSTGRES_USER is not set, it falls back to postgres.
- DB size — total size on disk
- DB version / uptime — PostgreSQL version and start time
- Table sizes (top 20) — largest tables by total size including indexes
- Table row counts — estimated rows per table from
pg_stat_user_tables - Cache hit ratio — buffer cache hit percentage (healthy: >99%)
- Active connections — current sessions with duration and query preview
- Long running queries — queries active for more than 5 seconds
- List tables — all user tables with schema
- List schemas — non-system schemas with owner
- List views — all user-defined views
- List sequences — all sequences with last value
- List functions — user-defined functions with argument signatures
- Unused indexes — indexes with zero scans (candidates for removal)
- Duplicate indexes — indexes covering identical column sets
- Index usage — scan counts and tuple stats per index
- Table bloat — dead tuple counts, live/dead ratio, last autovacuum time
- Active locks — current lock activity with query preview
- Replication status — streaming replication lag per replica
- VACUUM ANALYZE — run full vacuum analyze on all tables
- Run SQL query — open SQL input with persistent per-database history
- Download SQL dump —
pg_dump --no-owner --no-acl | gzip, saves to~/Downloads/<db>_<timestamp>.sql.gz - Download SQL dump (inserts) — same but with
--inserts --column-inserts(slower, more portable INSERT-based dump) - Download custom dump —
pg_dump --no-owner --no-acl -Fc, saves to~/Downloads/<db>_<timestamp>.dump(binary format, use withpg_restorefor selective table restore)
- Stored per-database in
~/.config/laradok/sql_history.json - Key format:
serverName/containerName/dbName - Up to 200 queries per database
↑/↓to navigate history in the SQL input screen- Duplicate queries are deduplicated (most recent position kept)
laradok/
├── main.go
├── internal/
│ ├── config/ # YAML config loading, SSH key expansion, SQL history persistence
│ ├── connection/ # SSHClient and LocalClient implementing the Runner interface
│ ├── docker/ # Docker/psql command builders, log tailing, DB introspection
│ ├── msgs/ # Bubble Tea message types for screen navigation and streaming
│ ├── tui/
│ │ ├── model.go # Root App model — screen stack, async orchestration
│ │ ├── keys.go # Key bindings
│ │ └── screens/ # Individual TUI screens
│ └── dbg/ # Debug logging (conditional)
The Runner interface (RunCommand, StreamCommand, InteractiveCommand, TailFile) is implemented by both SSHClient and LocalClient, making all features work identically on local and remote Docker hosts.
Available from the main menu on any Laravel container. Shows the size of storage/ before transferring, then:
- Runs
tar -czf - storage/ | base64 -w 76inside the container (no temp files on server) - Streams base64 lines to the local machine
- Decodes and writes to
~/Downloads/<container>_storage_<timestamp>.tar.gz
Progress is shown line-by-line in the output screen.
Available from the main menu on any container, rooted at the filesystem root /.
- Lists directories first, then files, each with its size — directories sized recursively with
du -sb(falls back todu -skon BusyBox). ↑↓to move,enter/→to open a directory or view a file in the log viewer (scroll, tail, lazy-load earlier lines),←/backspaceto go up,escto leave the browser at the root.- Press
don any file or directory to archive and download it the same way as Download Storage:tar -czf - | base64streamed to~/Downloads/<container>_<name>_<timestamp>.tar.gz. No temp files are created on the server, so nothing is left behind after the transfer.
- No telemetry or network calls except to your configured servers
- SSH credentials stay local; only Docker and psql commands are executed on remote hosts
- SQL history is stored unencrypted at
~/.config/laradok/sql_history.json - Dump files are written to
~/Downloads/and never transmitted elsewhere