Pam logo Pam's Database Drawer bitmap

image ### *"Pam, the receptionist, has been doing a fantastic job."* > **Michael Scott:** "You know what's amazing? Pam. Pam is amazing. She's got this drawer - not just any drawer - a database drawer. Full of SQL queries. I didn't even know we needed that, but apparently everyone does because they keep asking her for them. 'Pam, I need the users query.' 'Pam, where's that sales report?' And she just opens the drawer and boom. There it is. I think it's the most popular drawer in the entire office. Maybe even in Scranton. Possibly Pennsylvania." --- [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) ![go badge](https://img.shields.io/badge/Go-1.21+-00ADD8?%20logo=go&logoColor=white) **A minimal CLI tool for managing and executing SQL queries across multiple databases. Written in Go, made beautiful with BubbleTea** [Quick Start](#--------quick-start) • [Configuration](#--------configuration) • [Database Support](#--------database-support) • [Dbeesly](#-dbeesly) • [Features](#--------features) • [Commands](#--------all-commands) • [TUI Navigation](#--------tui-table-navigation) • [Roadmap](#--------roadmap) • [Contributing](#contributing) > This project is currently in beta, please report unexpected behavior through the issues tab
---

image Demo

![pam-demo](https://github.com/user-attachments/assets/b62bec1d-2255-4d02-9b7f-1c99afbeb664) ### Highlights - **Query Library** - Save and organize your most-used queries - **Runs in the CLI** - Execute queries with minimal overhead - **Multi-Database** - Works with PostgreSQL, MySQL, SQLite, Oracle, SQL Server, ClickHouse and Firebird - **Table view TUI** - Keyboard focused navigation with vim-style bindings - **In-Place Editing** - Update cells, delete rows and edit your SQL directly from the results table - **Export your data** - Export your data as CSV, JSON, SQL, Markdown or HTML tables ---

image Quick Start

### Installation Go to [the releases page](https://github.com/eduardofuncao/pam/releases) and find the correct version for your system. Download it and make sure the file is executable and moved to a directory in your $PATH.
Go install Use go to install `pam` directly ```bash go install github.com/eduardofuncao/pam/cmd/pam@latest ``` this will put the binary `pam` in your $GOBIN path (usually `~/go/bin`)
Build Manually Follow these instructions to build the project locally ```bash git clone https://github.com/eduardofuncao/pam go build -o pam ./cmd/pam ``` The pam binary will be available in the root project directory
Nix / NixOS (Flake) Pam is available as a Nix flake for easy installation on NixOS and systems with Nix. #### Run directly without installing ```bash nix run github:eduardofuncao/pam ``` #### Install to user profile ```bash nix profile install github:eduardofuncao/pam ``` #### Enter development shell ```bash nix develop github:eduardofuncao/pam ``` #### NixOS System-wide Add to your flake-based configuration.nix or flake.nix: ```nix { description = "My NixOS config"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; pam.url = "github:eduardofuncao/pam"; }; outputs = { self, nixpkgs, pam, ... }: { nixosConfigurations.myHostname = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ { nixpkgs.config.allowUnfree = true; environment.systemPackages = [ pam.packages.x86_64-linux.default ]; } ]; }; }; } ``` Then rebuild: sudo nixos-rebuild switch #### Home Manager Add to your home.nix or flake config: ```nix { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nix-unstable"; pam.url = "github:eduardofuncao/pam"; }; outputs = { self, nixpkgs, pam, ... }: { homeConfigurations."username" = { pkgs = nixpkgs.legacyPackages.x86_64-linux; modules = [ { nixpkgs.config.allowUnfree = true; home.packages = [ pam.packages.x86_64-linux.default ]; } ]; }; }; } ``` Then apply: home-manager switch Note: Oracle support requires `allowUnfree = true` in your Nix configuration.
### Basic Usage ```bash # Create your first connection (PostgreSQL example) pam init mydb postgres "postgresql://user:pass@localhost:5432/mydb" # Add a saved query pam add list_users "SELECT * FROM users" # List your saved queries pam list queries # Run it, this opens the interactive table viewer pam run list_users # Or run inline SQL pam run "SELECT * FROM products WHERE price > 100" ``` ### Navigating the Table Once your query results appear, you can navigate and interact with the data: ```bash # Use vim-style navigation or arrow-keys j/k # Move down/up h/l # Move left/right g/G # Jump to first/last row # Copy data y # Yank (copy) current cell v # Enter visual mode to select multiple cells and copy with y x # Export selected data as csv, tsv, json, sql, markdown or html # Edit data directly u # Update current cell (opens your $EDITOR) D # Delete current row # Modify and re-run e # Edit the query and re-run it # Exit q # Quit back to terminal ``` ---

image Configuration

Pam stores its configuration at `~/.config/pam/config.yaml`. ### Row Limit `default_row_limit: 1000` All queries are automatically limited to prevent fetching massive result sets. Configure via `default_row_limit` in config or use explicit `LIMIT` in your SQL queries. ### Column Width `default_column_width: 15` The width for all columns in the table TUI is fixed to a constant size, which can be configured through `default_column_width` in the config file. There are plans to make the column widths flexible in version v0.2.0. ### Color Schemes `color_scheme: "default"` Customize the terminal UI colors with built-in schemes: **Available schemes:** `default`, `dracula`, `gruvbox`, `solarized`, `nord`, `monokai` `black-metal`, `black-metal-gorgoroth`, `vesper`, `catppuccin-mocha`, `tokyo-night`, `rose-pine`, `terracotta` Each scheme uses a 7-color palette: Primary (titles, headers), Success (success messages), Error (errors), Normal (table data), Muted (borders, help text), Highlight (selected backgrounds), Accent (keywords, strings). ---

image Database Support

Examples of init/create commands to start working with different database types ### PostgreSQL ```bash pam init pg-prod postgres postgres://myuser:mypassword@localhost:5432/mydb?sslmode=disable # or connect to a specific schema: pam init pg-prod postgres postgres://myuser:mypassword@localhost:5432/mydb?sslmode=disable schema-name ``` ### MySQL / MariaDB ```bash pam init mysql-dev mysql 'myuser:mypassword@tcp(127.0.0.1:3306)/mydb' pam init mariadb-docker mariadb "root:MyStrongPass123@tcp(localhost:3306)/dundermifflin" ``` ### SQL Server ```bash pam init sqlserver-docker sqlserver "sqlserver://sa:MyStrongPass123@localhost:1433/master" ``` ### SQLite ```bash pam init sqlite-local sqlite file:///home/eduardo/dbeesly/sqlite/mydb.sqlite ``` ### Oracle ```bash pam init oracle-stg oracle myuser/mypassword@localhost:1521/XEPDB1 # or connect to a specific schema: pam init oracle-stg oracle myuser/mypassword@localhost:1521/XEPDB1 schema-name ``` > Make sure you have the [Oracle Instant Client](https://www.oracle.com/database/technologies/instant-client/downloads.html) or equivalent installed in your system ### ClickHouse ```bash pam init clickhouse-docker clickhouse "clickhouse://myuser:mypassword@localhost:9000/dundermifflin" ``` ### FireBird ```bash pam init firebird-docker firebird user:masterkey@localhost:3050//var/lib/firebird/data/the_office ``` --- ## 🐝 Dbeesly To run containerized test database servers for all supported databases, use the sister project [dbeesly](https://github.com/eduardofuncao/dbeesly) image ---

image Features

### Query Management Save, organize, and execute your SQL queries with ease. ```bash # Add queries with auto-incrementing IDs pam add daily_report "SELECT * FROM sales WHERE date = CURRENT_DATE" pam add user_count "SELECT COUNT(*) FROM users" pam add employees "SELECT TOP 10 * FROM employees ORDER BY last_name" # Add parameterized queries with :param|default syntax pam add emp_by_salary "SELECT * FROM employees WHERE salary > :min_sal|30000" pam add search_users "SELECT * FROM users WHERE name LIKE :name|P% AND status = :status|active" # When creating queries with params and not default, pam will prompt you for the param value every time you run the query pam add search_by_name "SELECT * FROM employees where first_name = :name" # Run parameterized queries with named parameters (order doesn't matter!) pam run emp_by_salary --min_sal 50000 pam run search_users --name Michael --status active # Or use positional args (must match SQL order) pam run search_users Michael active # List all saved queries pam list queries # Search for specific queries pam list queries emp # Finds queries with 'emp' in name or SQL pam list queries employees --oneline # displays each query in one line # Run by name or ID pam run daily_report pam run 2 # Edit query before running (great for testing parameter values) pam run emp_by_salary --edit ``` image ### TUI Table Viewer Navigate query results with Vim-style keybindings, update cells in-place, delete rows and copy data image **Key Features:** - Syntax-highlighted SQL display - Column type indicators - Primary key markers - Live cell editing - Visual selection mode ### Connection Switching Manage multiple database connections and switch between them instantly. ```bash # List all connections pam list connections pam switch production ``` Display current connection and check if it is reachable ``` pam status ```
image
### Database Exploration Explore your database schema and visualize relationships between tables. ```bash # List all tables and views in multi-column format pam explore # Query a table directly pam explore employees --limit 100 # Visualize foreign key relationships pam explain employees pam explain employees --depth 2 # Show relationships 2 levels deep ``` image **Note:** The `pam explain` command is currently a work in progress and may change in future versions. --- ### Editor Integration Pam uses your `$EDITOR` environment variable for editing queries and UPDATE/DELETE statements.
image
```bash # Set your preferred editor export EDITOR=vim export EDITOR=nano export EDITOR=code ``` You can also use the editor to edit queries before running them ```bash # Edit existing query before running pam run daily_report --edit # Create and run a new query on the fly pam run # Re-run the last executed query pam run --last # Edit all queries at once pam edit queries ``` ---

image All Commands

### Connection Management | Command | Description | Example | |---------|-------------|---------| | `create [schema]` | Create new database connection | `pam create mydb postgres "postgresql://..."` | | `switch ` | Switch to a different connection | `pam switch production` | | `status` | Show current active connection | `pam status` | | `list connections` | List all configured connections | `pam list connections` | ### Query Operations | Command | Description | Example | |---------|-------------|---------| | `add [sql]` | Add a new saved query | `pam add users "SELECT * FROM users"` | | `remove ` | Remove a saved query | `pam remove users` or `pam remove 3` | | `list queries` | List all saved queries | `pam list queries` | | `list queries --oneline` | lists each query in one line | `pam list -o` | | `list queries ` | lists queries containing search term | `pam list employees` | | `run ` | Execute a query | `pam run users` or `pam run 2` | | `run` | Create and run a new query | `pam run` | | `run --edit` | Edit query before running | `pam run users --edit` | | `run --last`, `-l` | Re-run last executed query | `pam run --last` | | `run --param` | run with named params | `pam run --name Pam` | ### Database Exploration | Command | Description | Example | |---------|-------------|---------| | `explore` | List all tables and views in multi-column format | `pam explore` | | `explore [-l N]` | Query a table with optional row limit | `pam explore employees --limit 100` | | `explain
[-d N] [-c]` | Visualize foreign key relationships | `pam explain employees --depth 2` | ### Info | Command | Description | Example | |---------|-------------|---------| | `info tables` | List all tables from current schema | `pam info tables` | | `info views` | List all views from current schema | `pam info views` | ### Configuration | Command | Description | Example | |---------|-------------|---------| | `edit config` | Edit main configuration file | `pam edit config` | | `edit queries` | Edit all queries for current connection | `pam edit queries` | | `help [command]` | Show help information | `pam help run` | ---

image TUI Table Navigation

When viewing query results in the TUI, you have full Vim-style navigation and editing capabilities. ### Basic Navigation | Key | Action | |-----|--------| | `h`, `←` | Move left | | `j`, `↓` | Move down | | `k`, `↑` | Move up | | `l`, `→` | Move right | | `g` | Jump to first row | | `G` | Jump to last row | | `0`, `_`, `Home` | Jump to first column | | `$`, `End` | Jump to last column | | `Ctrl+u`, `PgUp` | Page up | | `Ctrl+d`, `PgDown` | Page down | ### Data Operations | Key | Action | |-----|--------| | `v` | Enter visual selection mode | | `y` | Copy selected cell(s) to clipboard | | `Enter` | Show cell value in detail view (with JSON formatting) | | `u` | Update current cell (opens editor) | | `D` | Delete current row (requires WHERE clause) | | `e` | Edit and re-run query | | `s` | Save current query | | `q`, `Ctrl+c`, `Esc` | Quit table view | ### Detail View Mode Press `Enter` on any cell to open a detailed view that shows the full cell content. If the content is valid JSON, it will be automatically formatted with proper indentation. **In Detail View:** | Key | Action | |-----|--------| | `↑`, `↓`, `j`, `k` | Scroll through content | | `e` | Edit cell content (opens editor with formatted JSON) | | `q`, `Esc`, `Enter` | Close detail view | When you press `e` in detail view: - The editor opens with the full content (JSON will be formatted) - Edit the content as needed - Save and close to update the database - JSON validation is performed automatically - The table view updates with the new value ### Visual Mode Press `v` to enter visual mode, then navigate to select a range of cells. Press `y` to copy the selection as plain text, or `x` to export the selected data as csv, tsv, json, sql insert statement, markdown or html > The copied or exported data will be available in your clipboard ---

image Roadmap

> This project is currently in beta, please report unexpected behavior through the issues tab ### v0.1.0 Ryan 📎 - [x] Multi-database support (PostgreSQL, MySQL, SQLite, Oracle, SQL Server, ClickHouse) - [x] Query library with save/edit/remove functionality - [x] Interactive TUI with Vim navigation - [x] In-place cell updates and row deletion - [x] Visual selection and copy (single and multi cell) - [x] Syntax highlighting - [x] Query editing in external editor - [x] Primary key detection - [x] Column type indicators - [x] Row limit configuration option - [x] Info command, list all tables/views in current connection ### v0.2.0 - Kelly 👗 - [x] Program colors configuration option - [x] Query parameter with prompt and defaults (e.g., `WHERE first_name = :name|Pam`) - [x] CSV/JSON export for multiple cells - [x] Display column types correctly for join queries - [x] `pam explore` and `pam explain` ### v0.3.0 - Jim 👔 - [ ] Shell autocomplete (bash, fish, zsh) - [ ] Encryption on connection username/password in config file - [ ] Dynamic column width --- ## Contributing We welcome contributions! Get started with detailed instructions from [CONTRIBUTING.md](CONTRIBUTING.md) Thanks a lot to all the contributors: ## Acknowledgments Pam wouldn't exist without the inspiration and groundwork laid by these fantastic projects: - **[naggie/dstask](https://github.com/naggie/dstask)** - For the elegant CLI design patterns and file-based data storage approach - **[DeprecatedLuar/better-curl-saul](https://github.com/DeprecatedLuar/better-curl-saul)** - For demonstrating a simple and genius approach to making a CLI tool - **[dbeaver](https://github.com/dbeaver/dbeaver)** - The OG database management tool Built with: - [Bubble Tea](https://github.com/charmbracelet/bubbletea) - The TUI framework - Go standard library and various database drivers --- ## License MIT License - see [LICENSE](LICENSE) file for details ---
**Made with 👚 by [@eduardofuncao](https://github.com/eduardofuncao)** > *"I don't think it would be the worst thing if it didn't work out... Wait, can I say that?"* - Pam Beesly (definitely NOT about Pam's Database Drawer) Pam mascot