Quick Start
This walkthrough takes you from a fresh ferrule install to a real database in under five minutes. SQLite for the warm-up, then a disposable Postgres in Docker for everything else.
Step 1 — your first query
SQLite needs no setup. Run:
ferrule query "sqlite::memory:" "SELECT 1 + 1 AS answer;" --format table
Output:
┌────────┐
│ answer │
├────────┤
│ 2 │
└────────┘
Drop the --format table flag and you’ll get JSON instead — that’s
the default. Either form is fine for now.
ferrule query "sqlite::memory:" "SELECT 1 + 1 AS answer;"
# [
# {
# "answer": 2
# }
# ]
Step 2 — a real database
Spin up a throwaway Postgres in Docker. This mirrors the test setup
in CLAUDE.md; copy and paste:
docker run -d --name ferrule-quickstart \
-e POSTGRES_PASSWORD=ferrule \
-e POSTGRES_USER=ferrule \
-e POSTGRES_DB=ferrule \
-p 127.0.0.1:15432:5432 \
postgres:17-alpine
# Wait for it to come up (~3 seconds)
until docker exec ferrule-quickstart pg_isready -U ferrule >/dev/null 2>&1; do
sleep 1
done
# Seed a tiny schema
PGPASSWORD=ferrule psql -h 127.0.0.1 -p 15432 -U ferrule -d ferrule -c "
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
name TEXT,
signed_up TIMESTAMPTZ DEFAULT now()
);
INSERT INTO customers (name) VALUES ('Alice'), ('Bob'), ('Carol');
"
Now query it directly:
ferrule query "postgres://ferrule:ferrule@127.0.0.1:15432/ferrule?sslmode=disable" \
"SELECT * FROM customers;" --format table
Output something like:
┌────┬───────┬───────────────────────────────┐
│ id │ name │ signed_up │
├────┼───────┼───────────────────────────────┤
│ 1 │ Alice │ 2026-04-26 18:01:23.456+00:00 │
│ 2 │ Bob │ 2026-04-26 18:01:23.456+00:00 │
│ 3 │ Carol │ 2026-04-26 18:01:23.456+00:00 │
└────┴───────┴───────────────────────────────┘
When you’re done with the container:
docker stop ferrule-quickstart && docker rm ferrule-quickstart
Step 3 — save a named connection
Typing the full URL every time gets old. Add it to the registry:
ferrule conn add demo "postgres://ferrule@127.0.0.1:15432/ferrule?sslmode=disable"
ferrule conn set-password demo
# Password: ferrule
Now use the name:
ferrule query demo "SELECT COUNT(*) FROM customers;"
ferrule tables demo
ferrule describe demo customers
ferrule repl demo
The password is stored in your OS keyring under
keyring://ferrule/demo, never on disk in plaintext.
Step 4 — pipe-friendly defaults
The default output format is JSON. That’s chosen so output piped to
jq, awk, or another command “just works”:
ferrule query demo "SELECT * FROM customers" | jq '.[].name'
# "Alice"
# "Bob"
# "Carol"
If you’d rather see tables in your terminal, either pass --format table per command, or set a project default in .ferrule.toml
(see Configuration).
Step 5 — save a bookmark
For queries you run all the time, bookmarks beat shell aliases:
ferrule bookmark add daily-count \
"SELECT COUNT(*) FROM customers WHERE signed_up > now() - interval '1 day';" \
--connection demo
ferrule bookmark run daily-count
Positional parameters work too:
ferrule bookmark add by-name "SELECT * FROM customers WHERE name = ${1};" \
--connection demo
ferrule bookmark run by-name "'Alice'"
How passwords get resolved
Step 3 stored a password in the keyring. The next time you run
ferrule query demo "..." without a password on the URL, ferrule
walks this stack and stops at the first hit:
1. --password CLI flag (you didn't pass one)
2. password_url in profile (no .ferrule.toml profile yet)
3. FERRULE_DEMO_PASSWORD env (unset)
4. keyring://ferrule/demo ← FOUND (set by `conn set-password`)
5. Interactive prompt
6. Fail
This is described in detail in Concepts and Security. For now: storing in the keyring is the right default for a workstation.
Where to next
- Querying Data — output formats, paging, parameterized queries.
- Connections — profiles, environment
interpolation, registry vs
.ferrule.toml. - Interactive REPL — meta-commands, watch mode.
- Concepts — the abstractions everything is built on.