Shoveler: A desktop SQL workbench for DuckDB
Project description
Shoveler - A DuckDB Workbench
A minimal desktop SQL workbench for DuckDB, built with Python and PySide6.
Named after the Australasian shoveler - a species of "dabbling duck" - in honor of both the database's name and the app's purpose.
Setup (uv)
git clone https://github.com/mrmatho/shoveler
cd shoveler
uv sync
uv sync creates a .venv, installs all dependencies including the dev group,
and respects uv.lock if it exists. Run it again after pulling changes.
Running
uv run python -m shoveler
Testing
uv run pytest
Configuration layout
Shoveler now keeps most theme and UI configuration out of the widget classes.
- Theme stylesheets live in
src/shoveler/assets/themes/as.qssfiles. - Structured configuration lives in
src/shoveler/config/. theme.pyloads and normalizes app themes.syntax.pycontains SQL highlighting keywords and per-theme editor colors.ui.pycontains shared UI constants such as status colors and path thresholds.text.pycontains user-facing labels, tooltips, dialog text, and status message helpers.
When adding a new theme, update both the .qss assets and the relevant per-theme values in src/shoveler/config/ so editor syntax, status colors, and other theme-aware UI elements stay in sync.
Usage
- Open File — connect to an existing
.duckdbor.dbfile (green indicator) - New In-Memory — scratch database; data is lost when closed (amber indicator)
- File > Save Database As... — save current database state to a
.duckdbfile - Checkpoint — flush the write-ahead log to disk (file databases only)
- F5 or Ctrl+Enter — run query
- Select part of your SQL to run only that selection
- Double-click a table name in the schema panel to insert it into the editor
- View > Syntax highlighting — toggle SQL highlighting on or off; enabled by default and remembered between launches
Documentation (Phase 1)
Basic user docs are available in the docs/ folder:
Publish with GitHub Pages
For a simple setup:
- Go to repository Settings > Pages.
- Under Build and deployment, set Source to Deploy from a branch.
- Choose branch
mainand folder/docs. - Save.
GitHub Pages will publish the docs automatically from the docs/ directory.
Building a standalone Windows executable
The project includes shoveler.spec with the correct PyInstaller
configuration. Use this rather than running pyinstaller with flags directly —
the spec handles a non-obvious issue with DuckDB's compiled extension.
uv run pyinstaller shoveler.spec
Output is in dist/Shoveler/. Distribute that folder as a zip.
Building and publishing desktop binaries with GitHub Actions
This repo includes a release workflow at .github/workflows/desktop-release.yml.
- Trigger: push a tag like
v1.2.0(or run manually with workflow_dispatch). - Build matrix: Windows, macOS, Linux.
- Output artifacts:
Shoveler-windows-x64.zipShoveler-macos-universal.zipShoveler-linux-x64.tar.gz
- Release publish: on tag pushes, artifacts are attached automatically to the GitHub Release.
Release steps
- Update version/changelog as needed.
- Create and push a version tag:
git tag v1.2.0
git push origin v1.2.0
- Wait for the
Desktop Releaseworkflow to finish. - Open the matching GitHub Release and verify all three artifacts are attached.
Why --onedir and not --onefile?
--onefile extracts everything to a temp directory on every launch, which makes
startup noticeably slow for a PySide6 app. --onedir is faster and easier to
debug if something goes wrong.
Known PyInstaller issue with DuckDB:
DuckDB's compiled core (_duckdb.pyd on Windows) lives outside the duckdb/
package directory. PyInstaller does not find it automatically. The spec file
uses collect_all('duckdb') which handles this correctly. If you ever regenerate
the spec from scratch, make sure this is included or the packaged app will fail
to start.
Extending
| Feature | Where to add it |
|---|---|
| More export formats | Add menu items in ResultsPanel._show_export_menu() — raw data is in _last_rows / _last_columns |
| Results table badges | Update ResultsPanel._populate_table() and keep export using _last_rows / _last_columns only; badge text comes from QueryResult.column_types |
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shoveler-0.1.3.tar.gz.
File metadata
- Download URL: shoveler-0.1.3.tar.gz
- Upload date:
- Size: 104.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b885877d0e1805f5ef681fd23142a2ec8f96cf721d0b2f5a5d0dd6329299f0a3
|
|
| MD5 |
d1ba1548c69dcff35cfc9a3e9c4f71d7
|
|
| BLAKE2b-256 |
a13a6b30f6d642f145916dc2388b78c99460bd6fd9e3e4bebc98453753056e4f
|
Provenance
The following attestation bundles were made for shoveler-0.1.3.tar.gz:
Publisher:
python-publish.yml on mrmatho/shoveler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shoveler-0.1.3.tar.gz -
Subject digest:
b885877d0e1805f5ef681fd23142a2ec8f96cf721d0b2f5a5d0dd6329299f0a3 - Sigstore transparency entry: 1640130733
- Sigstore integration time:
-
Permalink:
mrmatho/shoveler@4aac99699907965b23ce9523934f97aa3e25fe2a -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/mrmatho
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@4aac99699907965b23ce9523934f97aa3e25fe2a -
Trigger Event:
release
-
Statement type:
File details
Details for the file shoveler-0.1.3-py3-none-any.whl.
File metadata
- Download URL: shoveler-0.1.3-py3-none-any.whl
- Upload date:
- Size: 87.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5711d49784f09681199a6bd84d3922bcd594dd9865e379147f1d10411a68b251
|
|
| MD5 |
03a183d858d0ebf134998f79c9e5bc56
|
|
| BLAKE2b-256 |
0a8a9c149e9c24fa9c380b7271fccf756f11422455f6749e64fc63fce947e3cf
|
Provenance
The following attestation bundles were made for shoveler-0.1.3-py3-none-any.whl:
Publisher:
python-publish.yml on mrmatho/shoveler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shoveler-0.1.3-py3-none-any.whl -
Subject digest:
5711d49784f09681199a6bd84d3922bcd594dd9865e379147f1d10411a68b251 - Sigstore transparency entry: 1640130808
- Sigstore integration time:
-
Permalink:
mrmatho/shoveler@4aac99699907965b23ce9523934f97aa3e25fe2a -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/mrmatho
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@4aac99699907965b23ce9523934f97aa3e25fe2a -
Trigger Event:
release
-
Statement type: