plot-cli is a simple command-line plotting tool for terminal-based data visualization.
It uses DuckDB for data loading/transformation and tplot for rendering. Supports CSV, JSON,
NDJSON, and Parquet input with SQL-style filtering and time-series bucketing.
This project uses uv for all Python tooling. Do not use pip, poetry, or conda.
- Install dependencies:
uv sync - Run the CLI:
uv run plotoruv run plot-cli - Run tests:
uv run pytest - Run a specific test marker:
uv run pytest -m unitoruv run pytest -m integration - Add a dependency:
uv add <package> - Add a dev dependency:
uv add --group dev <package> - Build:
uv build
The lockfile is uv.lock. Always commit it alongside pyproject.toml changes.
pyproject.toml # PEP 621 metadata, dependencies, pytest config (hatchling backend)
uv.lock # Locked dependency versions
src/plot_cli/ # Package source (src-layout)
__init__.py # Entry-point, PlotApp (CmdKit Application), CLI interface
config.py # Configuration via CmdKit (TOML), logging, error handling
query.py # QueryBuilder — DuckDB queries, format detection, filtering, bucketing
plot.py # Figure/TimeSeriesFigure wrappers around tplot, tick generation
tests/
test_app.py # Unit tests — version output
test_query.py # Unit tests — QueryBuilder, format detection, filtering, aggregation
test_cli.py # Integration tests — CLI output modes, filtering, aggregation options
- CmdKit pattern: The CLI follows the CmdKit
Applicationpattern.PlotAppin__init__.pydefines the full CLI interface viaInterfacewith argument groups. See cmdkit docs. - Data pipeline:
PlotApp.run()→_load_data()(QueryBuilder) → output or render. - QueryBuilder (
query.py): Builds and executes DuckDB SQL queries. Handles format detection, column selection, WHERE/datetime filtering, time bucketing, PIVOT for--by, and datetime scale conversion. - Figure (
plot.py): Thin wrapper overtplot.Figure.TimeSeriesFigureextends it with smart datetime axis tick generation via_CustomTplotFigure.
- License headers: Every
.pyfile starts with SPDX copyright/license comments. - Type annotations: Use
from __future__ import annotations. PreferOptional,List,Tuplefromtyping(existing convention in this codebase). - Imports: Group as: type annotations, standard libs, external libs, internal libs.
Include a
# Public interfacesection with__all__. - Logging: Use
cmdkit.logging.Loggerin application code,logging.getLogger(__name__)in library modules. - Self annotations: Methods use explicit
self: ClassNametype annotations.
- Framework: pytest with custom markers defined in
pyproject.toml. - Markers:
@mark.unitfor fast interface tests,@mark.integrationfor CLI/system tests. - Run all tests:
uv run pytest - Run by marker:
uv run pytest -m unit - Test data: Use
tmp_pathfixture for temporary files; create CSV/JSON/Parquet inline. - CLI tests: Invoke via
PlotApp.main([...])and capture output withcapsys.
- Work on the
wipbranch withWIP:prefixed commit messages. - Push to
wipfreely; collapse into logical commits before PR againstmain. - Include
Co-Authored-By: Oz <oz-agent@warp.dev>on AI-assisted commits.
cmdkit[toml]— CLI framework (Application, Interface, Configuration, Logger)duckdb— In-process SQL for data loading and transformationpandas— DataFrame interchange between DuckDB and plottingtplot— Terminal-based plotting (line, scatter, bar, histogram)pyarrow— Parquet read/write support