Getting started

AT-1 compresses your data losslessly and lets you query it while compressed. Here's the five-minute tour.

Install

npm i -g @tinyfiles/cli              # the full CLI as a self-contained binary — no Python required (pnpm/yarn/bun too)
npm install @tinyfiles/decoder            # WASM decoder for the browser/Node (decode-only)

Connect your account

AT-1 is metered against the account you create on the dashboard, so the first step after installing is to connect this machine. Create an API key in the dashboard under API Keys, then:

at1 login --key <API_KEY>     # key from the dashboard -> API Keys
at1 whoami                    # show the connected account
at1 logout                    # disconnect this machine

# CI / headless: set the key via the environment instead of logging in
export AT1_LICENSE_KEY=<API_KEY>
export AT1_METER_URL=https://tinyfiles.io/api   # default; override for self-host

at1 login stores your key in ~/.at1/config.json (mode 0600). Environment variables AT1_LICENSE_KEY / AT1_METER_URL take precedence when set, which is the way to wire CI or a container. On the desktop app, use the Connect account panel and paste the same API key. For SDK / native usage the host process sets the key (env or config) and every operation is metered against that account.

Compress (losslessly) & decompress

at1 compress qcolumnar trades.csv trades.at1     # ~5% of original, verified lossless
at1 decompress trades.at1 trades.out             # byte-for-byte identical to trades.csv

The encoder auto-selects a codec by data type, or pass it explicitly (qcolumnar for CSV/tables, qjson for NDJSON, log/osm/vcf…). Every output is byte-compared to the original before it ships.

To get a queryable archive, use a queryable codec. Only qcolumnar (tables/CSV) and qjson (NDJSON) produce files you canat1 query/at1 sql in place. The generic codecs compress to roughly the same size as xz but are not queryable — if at1 query reports “not queryable,” re-compress with qcolumnar or qjson. For purely numeric columns, see adaptive compression. qcolumnar columns are positional with names taken from the CSV header row; keep your header and filter on integer/timestamp keys (decimal-range predicate pushdown is being refined).

Query while compressed

at1 query trades.at1 --where price:42000:43000 --select aggId,price,ts
at1 sql   trades.at1 "SELECT aggId, price WHERE ts BETWEEN 1704067200000 AND 1704067210000"
# reads only the touched blocks — under 1% of the file for a selective query

As a storage tier

python at1_adapter.py tier  ./logs ./logs_at1     # compress a tree
mongoexport --db app --collection trades | python connectors/at1_ingest.py trades.at1

Decode in your app

# Python
from at1decode import decode
original = decode(open("trades.at1","rb").read())

# JavaScript (browser / Node)
import { decode } from "@tinyfiles/decoder";
const original = await decode(at1Bytes);

Free tier & limits

The free tier is metered, not unlimited. Usage is tracked against your connected account, and you may hit one of these:

  • Free credit, then metered. The free tier covers a one-time 100 GB-compressedtrial (free account, no card) as a credit, not a hard cap. Once it's used: add a card and usage continues at the metered TB-under-management rate; with no card, encoding is blocked (card_required) until you add one. Decoding an existing file is never blocked. See pricing.
  • Payment required. An unpaid or past-due paid account is blocked (payment_required) until the balance is settled.
  • Update required. A client that is too far out of date may be asked to update (npm i -g @tinyfiles/cli@latest) before it can keep metering.

Offline / self-hosted builds with no key configured run unmetered; metering is cooperative, and decoding an .at1 file is always free and open.

Next: the Query guide, the SDK, or the CLI reference.