Update documentation for new commands and output formats

- Update README.md with new commands summary and uv development workflow
- Add docs/exploring.md covering databases, tables, schema, rows, get
  commands with filtering, sorting, pagination, and output format examples
- Add docs/writing.md covering create-table, upsert, update, delete, drop
- Update docs/queries.md with output format options (--csv, --tsv, --nl, --table)
- Update docs/inserting.md with cross-references to upsert/update
- Update docs/index.md toctree to include new pages
- Regenerate all cog --help blocks with current command signatures

https://claude.ai/code/session_01DoiJf9Gbvbw2asN9yvP6dx
This commit is contained in:
Claude 2026-02-12 01:28:35 +00:00
commit 02dd3ae9ca
No known key found for this signature in database
7 changed files with 709 additions and 25 deletions

View file

@ -11,10 +11,15 @@ Much of the functionality requires Datasette 1.0a2 or higher.
## Things you can do with dclient
- Run SQL queries against Datasette and returning the results as JSON
- **Explore** databases, tables, schemas, and rows without writing SQL
- **Query** with SQL and get results as JSON, CSV, TSV, or formatted tables
- **Insert** data from CSV, TSV, JSON, or newline-delimited JSON files
- **Upsert** data (insert or update based on primary key)
- **Update** individual rows by primary key
- **Delete** rows or **drop** entire tables
- **Create tables** with explicit schemas
- Run queries against authenticated Datasette instances
- Create aliases and store authentication tokens for convenient access to Datasette
- Insert data into Datasette using the [insert API](https://docs.datasette.io/en/latest/json_api.html#the-json-write-api) (Datasette 1.0 alpha or higher)
- Create aliases and store authentication tokens for convenient access
## Installation
@ -26,36 +31,67 @@ If you want to install it in the same virtual environment as Datasette (to use i
```bash
datasette install dclient
```
## Running a query
## Quick start
```bash
# Explore a Datasette instance
dclient databases https://latest.datasette.io
dclient tables https://latest.datasette.io/fixtures
dclient schema https://latest.datasette.io/fixtures
# Browse rows with filtering and sorting
dclient rows https://latest.datasette.io/fixtures/facetable --table
dclient rows https://latest.datasette.io/fixtures/facetable -w state=CA --sort city
# Fetch a single row by primary key
dclient get https://latest.datasette.io/fixtures/facetable 1
# Run a SQL query
dclient query https://latest.datasette.io/fixtures "select * from facetable limit 1"
```
To shorten that, create an alias:
For write operations (requires authentication):
```bash
# Create a table
dclient create-table https://example.com/db mytable \
--column id integer --column name text --pk id
# Insert data from a CSV file
dclient insert https://example.com/db mytable data.csv --create
# Update a row
dclient update https://example.com/db/mytable 42 name=Alice age=30
# Upsert from a JSON file
dclient upsert https://example.com/db mytable data.json --json
# Delete a row
dclient delete https://example.com/db/mytable 42 --yes
# Drop a table
dclient drop https://example.com/db/mytable --yes
```
To shorten URLs, create an alias:
```bash
dclient alias add fixtures https://latest.datasette.io/fixtures
```
Then run it like this instead:
```bash
dclient query fixtures "select * from facetable limit 1"
```
## Documentation
Visit **[dclient.datasette.io](https://dclient.datasette.io)** for full documentation on using this tool.
## Development
To contribute to this tool, first checkout the code. Then create a new virtual environment:
To contribute to this tool, first checkout the code. Then install dependencies and run tests using [uv](https://docs.astral.sh/uv/):
```bash
cd dclient
python -m venv venv
source venv/bin/activate
uv run pytest
```
Now install the dependencies and test dependencies:
To build the package:
```bash
pip install -e '.[test]'
```
To run the tests:
```bash
pytest
uv build
```

View file

@ -161,7 +161,7 @@ cog.out(
)
]]] -->
```
Usage: dclient actor [OPTIONS] URL_OR_ALIAS
Usage: dclient actor [OPTIONS] [URL_OR_ALIAS]
Show the actor represented by an API token

347
docs/exploring.md Normal file
View file

@ -0,0 +1,347 @@
# Exploring data
dclient provides several commands for exploring Datasette instances without writing SQL.
## Listing databases
Use `dclient databases` to list all databases on a Datasette instance:
```bash
dclient databases https://latest.datasette.io
```
Use `--table` for a formatted text table:
```bash
dclient databases https://latest.datasette.io --table
```
Output:
```
name path is_mutable
-------- -------- ----------
fixtures fixtures False
```
## Listing tables
Use `dclient tables` to list tables in a specific database:
```bash
dclient tables https://latest.datasette.io/fixtures
```
Use `--table` for formatted output:
```bash
dclient tables https://latest.datasette.io/fixtures --table
```
Use `--schema` to include the CREATE TABLE SQL for each table:
```bash
dclient tables https://latest.datasette.io/fixtures --schema
```
Use `--views` to include views in the output (hidden by default).
## Viewing schemas
Use `dclient schema` to show the SQL schema for a database or an individual table:
```bash
# Schema for all tables in a database
dclient schema https://latest.datasette.io/fixtures
# Schema for a specific table
dclient schema https://latest.datasette.io/fixtures/facetable
```
## Browsing rows
Use `dclient rows` to browse table data with filtering, sorting, and pagination — no SQL required:
```bash
dclient rows https://latest.datasette.io/fixtures/facetable --table
```
### Filtering
Use `-w` / `--where` to filter rows. Supports [Datasette filter operators](https://docs.datasette.io/en/stable/json_api.html#table-arguments) like `__gt`, `__contains`, `__exact`, etc.:
```bash
# Exact match
dclient rows https://example.com/db/dogs -w breed=Poodle
# Greater than
dclient rows https://example.com/db/dogs -w age__gt=4
# Multiple filters (AND)
dclient rows https://example.com/db/dogs -w age__gte=3 -w breed=Labrador
```
For raw SQL WHERE clauses, use `--where-sql`:
```bash
dclient rows https://example.com/db/dogs --where-sql "age > 3 and breed != 'Poodle'"
```
### Sorting
```bash
# Sort ascending
dclient rows https://example.com/db/dogs --sort name
# Sort descending
dclient rows https://example.com/db/dogs --sort-desc age
```
### Selecting columns
```bash
# Include only specific columns
dclient rows https://example.com/db/dogs --col name --col breed
# Exclude specific columns
dclient rows https://example.com/db/dogs --nocol id
```
### Full-text search
```bash
dclient rows https://example.com/db/articles --search "python tutorial"
```
### Faceting
```bash
dclient rows https://example.com/db/dogs --facet breed
```
Facet results are printed to stderr, with the rows on stdout.
### Pagination
By default, only the first page of results is returned. Use `--all` to fetch every page:
```bash
dclient rows https://example.com/db/dogs --all
```
Control page size with `--size` and limit total rows with `--limit`:
```bash
# 10 rows per page, max 50 rows total
dclient rows https://example.com/db/dogs --size 10 --limit 50
```
## Fetching a single row
Use `dclient get` to fetch a single row by its primary key:
```bash
dclient get https://latest.datasette.io/fixtures/facetable 1
```
Output:
```json
{
"pk": 1,
"created": "2019-01-14 08:00:00",
"planet_int": 1,
"on_earth": 1,
"state": "CA",
...
}
```
For compound primary keys, separate values with a comma:
```bash
dclient get https://example.com/db/compound_pk a,b
```
## Output formats
The `databases`, `tables`, `rows`, and `query` commands all support multiple output formats:
- `--json` — JSON (default)
- `--csv` — CSV
- `--tsv` — TSV
- `--nl` — Newline-delimited JSON
- `--table` — Formatted text table
```bash
dclient rows https://example.com/db/dogs --csv > dogs.csv
dclient rows https://example.com/db/dogs --table
```
## dclient databases --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["databases", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient databases [OPTIONS] [URL_OR_ALIAS]
List databases on a Datasette instance
Example usage:
dclient databases https://latest.datasette.io
Options:
--token TEXT API token
-v, --verbose Verbose output
--csv Output as CSV
--tsv Output as TSV
--json Output as JSON (default)
--nl Output as newline-delimited JSON
--table Output as text table
--help Show this message and exit.
```
<!-- [[[end]]] -->
## dclient tables --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["tables", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient tables [OPTIONS] [URL_OR_ALIAS]
List tables in a Datasette database
Example usage:
dclient tables https://latest.datasette.io/fixtures
Options:
--token TEXT API token
--views Include views
--schema Show CREATE TABLE SQL
-v, --verbose Verbose output
--csv Output as CSV
--tsv Output as TSV
--json Output as JSON (default)
--nl Output as newline-delimited JSON
--table Output as text table
--help Show this message and exit.
```
<!-- [[[end]]] -->
## dclient schema --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["schema", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient schema [OPTIONS] [URL_OR_ALIAS]
Show the SQL schema for a database or table
Example usage:
dclient schema https://latest.datasette.io/fixtures
dclient schema https://latest.datasette.io/fixtures/facetable
Options:
--token TEXT API token
-v, --verbose Verbose output
--help Show this message and exit.
```
<!-- [[[end]]] -->
## dclient rows --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["rows", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient rows [OPTIONS] [URL_OR_ALIAS]
Browse rows in a Datasette table with filtering and sorting
Example usage:
dclient rows https://latest.datasette.io/fixtures/facetable
dclient rows https://latest.datasette.io/fixtures/facetable -w state=CA
dclient rows https://latest.datasette.io/fixtures/facetable --sort city
dclient rows https://latest.datasette.io/fixtures/facetable --search text
Options:
--token TEXT API token
-w, --where TEXT Filter: column__op=value (e.g. age__gt=30)
--where-sql TEXT Raw SQL WHERE clause
--search TEXT Full-text search query
--sort TEXT Sort by column (ascending)
--sort-desc TEXT Sort by column (descending)
--col TEXT Include only these columns
--nocol TEXT Exclude these columns
--facet TEXT Facet by column
--size INTEGER Number of rows per page
--all Fetch all pages
--limit INTEGER Maximum total rows to return
-v, --verbose Verbose output
--csv Output as CSV
--tsv Output as TSV
--json Output as JSON (default)
--nl Output as newline-delimited JSON
--table Output as text table
--help Show this message and exit.
```
<!-- [[[end]]] -->
## dclient get --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["get", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient get [OPTIONS] [URL_OR_ALIAS] PK_VALUES
Fetch a single row by primary key
Example usage:
dclient get https://latest.datasette.io/fixtures/facetable 1
dclient get https://latest.datasette.io/fixtures/compound_pk a,b
Options:
--token TEXT API token
-v, --verbose Verbose output
--help Show this message and exit.
```
<!-- [[[end]]] -->

View file

@ -9,7 +9,7 @@ A client CLI utility for [Datasette](https://datasette.io/) instances
## Installation
Install `dclient` using `pip` (or [pipx](https://pipxproject.github.io/pipx/):
Install `dclient` using `pip` (or [pipx](https://pipxproject.github.io/pipx/)):
```bash
pip install dclient
@ -21,16 +21,11 @@ If you also have Datasette installed in the same environment it will register it
```bash
datasette install dclient
```
This means you can run any of these commands using `datasette dt` instead, like this:
This means you can run any of these commands using `datasette dc` instead, like this:
```bash
datasette dc --help
datasette dc query https://latest.datasette.io/fixtures "select * from facetable limit 1"
```
You can install it into Datasette this way using:
```bash
datasette install dclient
```
## Contents
@ -38,8 +33,10 @@ datasette install dclient
---
maxdepth: 3
---
exploring
queries
inserting
writing
aliases
authentication
inserting
```

View file

@ -4,6 +4,8 @@ The `dclient insert` command can be used to insert data from a local file direct
First you'll need to {ref}`authenticate <authentication>` with the instance.
See also {doc}`writing` for related commands: `upsert`, `update`, `delete`, `drop`, and `create-table`.
To insert data from a `data.csv` file into a table called `my_table`, creating that table if it does not exist:
```bash
@ -138,3 +140,7 @@ Options:
```
<!-- [[[end]]] -->
:::{note}
To update existing rows rather than inserting new ones, see {doc}`writing` for the `upsert` and `update` commands.
:::

View file

@ -24,6 +24,34 @@ Output:
]
```
## Output formats
Query results default to JSON. Use these flags for other formats:
- `--csv` — CSV
- `--tsv` — TSV
- `--nl` — Newline-delimited JSON (one JSON object per line)
- `--table` — Formatted text table
```bash
dclient query https://latest.datasette.io/fixtures \
"select state, count(*) as n from facetable group by state" --table
```
Output:
```
state n
----- --
CA 10
MI 4
MO 1
```
Export as CSV:
```bash
dclient query https://latest.datasette.io/fixtures \
"select * from facetable limit 5" --csv > results.csv
```
## dclient query --help
<!-- [[[cog
import cog
@ -52,6 +80,11 @@ Usage: dclient query [OPTIONS] URL_OR_ALIAS SQL
Options:
--token TEXT API token
-v, --verbose Verbose output: show HTTP request
--csv Output as CSV
--tsv Output as TSV
--json Output as JSON (default)
--nl Output as newline-delimited JSON
--table Output as text table
--help Show this message and exit.
```

265
docs/writing.md Normal file
View file

@ -0,0 +1,265 @@
# Writing data
In addition to `insert` (documented in {doc}`inserting`), dclient provides several commands for modifying data in a Datasette instance via the [Write API](https://docs.datasette.io/en/latest/json_api.html#the-json-write-api).
All write commands require authentication. See {doc}`authentication` for how to set up tokens.
## Creating tables
Use `dclient create-table` to create a new empty table with an explicit schema:
```bash
dclient create-table https://example.com/db mytable \
--column id integer \
--column name text \
--column age integer \
--pk id
```
Output:
```json
{
"ok": true,
"database": "db",
"table": "mytable",
"schema": "CREATE TABLE [mytable] (\n [id] INTEGER PRIMARY KEY,\n [name] TEXT,\n [age] INTEGER\n)"
}
```
Use `--pk` one or more times to set compound primary keys:
```bash
dclient create-table https://example.com/db events \
--column date text --column venue text --column title text \
--pk date --pk venue
```
## Upserting data
Use `dclient upsert` to insert rows or update existing ones based on primary key. This works like `insert` but uses the [upsert API endpoint](https://docs.datasette.io/en/latest/json_api.html#upserting-rows):
```bash
dclient upsert https://example.com/db mytable data.csv
```
The same file format options as `insert` are supported: `--csv`, `--tsv`, `--json`, `--nl`, `--encoding`, `--no-detect-types`.
Upsert from standard input:
```bash
echo '[{"id": 1, "name": "Updated"}]' | \
dclient upsert https://example.com/db mytable - --json
```
Use `--alter` to add any missing columns automatically.
## Updating a single row
Use `dclient update` to update specific columns of a row by its primary key:
```bash
dclient update https://example.com/db/mytable 42 name=Alice age=30
```
Values are automatically parsed — numbers become integers/floats, `true`/`false` become booleans, `null` becomes null. Everything else is treated as a string.
Use `--alter` to allow adding new columns that don't exist yet.
## Deleting a row
Use `dclient delete` to delete a single row by primary key:
```bash
dclient delete https://example.com/db/mytable 42
```
You'll be prompted for confirmation. Use `--yes` to skip the prompt:
```bash
dclient delete https://example.com/db/mytable 42 --yes
```
## Dropping a table
Use `dclient drop` to drop an entire table:
```bash
dclient drop https://example.com/db/mytable
```
Without `--yes`, dclient will first query the table and show you the row count before asking for confirmation:
```
Drop table mytable (150 rows)? [y/N]:
```
Use `--yes` to skip confirmation:
```bash
dclient drop https://example.com/db/mytable --yes
```
## dclient create-table --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["create-table", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient create-table [OPTIONS] URL_OR_ALIAS TABLE_NAME
Create a new empty table with explicit schema
Example usage:
dclient create-table https://example.com/db mytable \
--column id integer --column name text --pk id
Options:
--column TEXT... Column definition: name type (e.g. --column id integer
--column name text)
--pk TEXT Column(s) to use as primary key
--token TEXT API token
-v, --verbose Verbose output
--help Show this message and exit.
```
<!-- [[[end]]] -->
## dclient upsert --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["upsert", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient upsert [OPTIONS] URL_OR_ALIAS TABLE FILEPATH
Upsert data into a remote Datasette table
Rows with matching primary keys will be updated; others will be inserted. Each
row must include the primary key column(s).
Example usage:
dclient upsert \
https://private.datasette.cloud/data \
mytable data.csv
Options:
--csv Input is CSV
--tsv Input is TSV
--json Input is JSON
--nl Input is newline-delimited JSON
--encoding TEXT Character encoding for CSV/TSV
--no-detect-types Don't detect column types for CSV/TSV
--alter Alter table to add any missing columns
--batch-size INTEGER Send rows in batches of this size
--interval FLOAT Send batch at least every X seconds
-t, --token TEXT API token
--silent Don't output progress
-v, --verbose Verbose output: show HTTP request and response
--help Show this message and exit.
```
<!-- [[[end]]] -->
## dclient update --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["update", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient update [OPTIONS] URL_OR_ALIAS PK_VALUES [UPDATES]...
Update a row by primary key
Pass key=value pairs to set column values.
Example usage:
dclient update https://example.com/db/table 42 name=Alice age=30
Options:
--token TEXT API token
--alter Alter table to add any missing columns
-v, --verbose Verbose output
--help Show this message and exit.
```
<!-- [[[end]]] -->
## dclient delete --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["delete", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient delete [OPTIONS] URL_OR_ALIAS PK_VALUES
Delete a row by primary key
Example usage:
dclient delete https://example.com/db/table 42
dclient delete https://example.com/db/table 42 --yes
Options:
--token TEXT API token
--yes Skip confirmation
-v, --verbose Verbose output
--help Show this message and exit.
```
<!-- [[[end]]] -->
## dclient drop --help
<!-- [[[cog
import cog
from dclient import cli
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli.cli, ["drop", "--help"])
help = result.output.replace("Usage: cli", "Usage: dclient")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
Usage: dclient drop [OPTIONS] URL_OR_ALIAS
Drop a table
Example usage:
dclient drop https://example.com/db/table
dclient drop https://example.com/db/table --yes
Options:
--token TEXT API token
--yes Skip confirmation
-v, --verbose Verbose output
--help Show this message and exit.
```
<!-- [[[end]]] -->