Lightweight CSV dashboard. Python stdlib only — no npm, no build, no dependencies.
chmod +x csnap.py
ln -sf "$PWD/csnap.py" ~/.local/bin/csnap # any dir on your PATHcsnap . # serve CSVs in the current directory
csnap dir/dir/dir # or any other directory
csnap data --port 8080Prints the URL; open it. Default host is 127.0.0.1, default port 8000.
Tables — lists every *.csv in the directory as a card (name, column count, file size).
The search box filters by table name or column name; when a column matches, the card says which.
Click a card to load it. Rows are fetched 100 at a time from the server, so the list view never
reads row data.
Relations — draws each table as a box and connects columns using relation.json.
Drag a table header to move it. Relations pointing at an unknown table or column are skipped
and reported at the top.
Lives next to the CSVs. Table name = filename without .csv, column names come from the header row.
{
"relations": [
{ "from": "orders.customer_id", "to": "customers.id", "type": "many-to-one" }
]
}type is a free-text label drawn on the edge; omit it if you don't want one.
| Endpoint | Returns |
|---|---|
GET /api/tables |
[{name, bytes, columns}] — header row only |
GET /api/table?name=X&offset=0&limit=100 |
{columns, rows, total} |
GET /api/relations |
contents of relation.json |
python3 test_csnap.py- Binds to
127.0.0.1by default.--host 0.0.0.0exposes the served directory to your network. - Table names are resolved inside the served directory only;
../is rejected. - Row counts require a full file scan. Fine up to ~100 MB; add an index if you go bigger.
data/holds sample CSVs —csnap datato see it working.