Configure sources and credentials
Every source is part of the reviewed repository contract. The manifest stores connection metadata and the name of a password variable, but never the password itself.
Declare a source
[[sources]]
name = "reporting"
host = "sql.example.com"
port = 1433
database = "Reporting"
user = "skiff_reader"
password_env = "REPORTING_DB_PASS"
trust_cert = false
snapshot = false
| Field | Requirement |
|---|---|
name |
Unique, nonempty source name used by [[queries]] |
host |
SQL Server hostname or address |
port |
Optional; defaults to 1433 |
database |
Database selected when the connection opens |
user |
SQL Server login name |
password_env |
Name of the process environment variable holding the password |
trust_cert |
Optional; defaults to false |
snapshot |
Optional; defaults to false |
Source names are matched case-insensitively. Skiff rejects empty or duplicate names, invalid ports, and password-variable names containing =.
Use least-privilege logins
SQL Server permissions are the authorization boundary. Give each source login SELECT access to only the intended tables or views. Skiff checks query shape, but it does not reproduce database grants with an application allowlist.
Do not set trust_cert = true for a production server. That option disables certificate verification and exists for deliberately untrusted development certificates.
Supply passwords through the process
export REPORTING_DB_PASS='...'
skiff check
You may load a gitignored .env with your shell or direnv; Skiff itself reads only the process environment. This keeps values out of skiff.toml but does not make the environment a secrets manager.
Choose source consistency
By default, a source runs without a transaction. Schedule refreshes outside the source's load window and use checks to catch tables that disagree.
Set snapshot = true when all queries for one source must observe the same database state:
[[sources]]
name = "reporting"
host = "sql.example.com"
database = "Reporting"
user = "skiff_reader"
password_env = "REPORTING_DB_PASS"
snapshot = true
This requires ALLOW_SNAPSHOT_ISOLATION on that database and adds row-versioning cost to writes. Have the database owner make that decision; do not substitute NOLOCK.
Different sources load in parallel. Snapshot consistency applies within one source, not across independent SQL Server databases.
Set global limits
[limits]
max_rows = 500000
timeout_secs = 60
timeout_secs must be greater than zero. max_rows must be greater than zero or -1; set it to -1 to disable the row limit while keeping the timeout. The defaults are 500,000 rows per query and 60 seconds.
Keep paths inside the repository
The output, query files, and check files must use relative paths that remain inside the repository. Query and check files must end in .sql; the output must end in .duckdb.
Skiff resolves real paths before use and rejects traversal, absolute paths, and symlink escapes. The destination must be a regular, single-link file when it already exists.