arcli: The Command Line for Arc

#Arc#arcli#CLI#time-series#database#developer tools#Basekick Labs
Cover image for arcli: The Command Line for Arc

Arc has had a web console for a while. Launchpad covers the browser: SQL, logs, tokens, retention, alerts. What it did not have was a good answer for the terminal.

That answer is arcli, and it is available now. brew install basekick-labs/tap/arcli, or deb, rpm, Arch, Docker, or a plain binary. The documentation is at docs.basekick.net/arcli.

What it replaces

Operating Arc from a shell meant writing curl by hand. Copy the bootstrap token out of a stderr banner, build the JSON query body, set Authorization: Bearer, remember that the database goes in the x-arc-database header, then read back {"columns":[...],"data":[...]} and decode it by eye. Every environment meant swapping shell variables, and every admin task meant looking up an endpoint.

arcli is that workflow as a CLI, modelled on tools people already know: influx, kubectl, clickhouse-client. Named connections, one active at a time, overridable per command.

# save a connection; the first one becomes active
arcli config create --name local --endpoint http://localhost:8000 --token YOUR-TOKEN
 
# health and token check in one call
arcli ping
 
# query
arcli query "SELECT host, avg(usage) AS usage FROM cpu GROUP BY 1 ORDER BY 2 DESC"

That last command prints a table. Add -o json and pipe it to jq, -o csv and redirect it to a file, or -o arrow and stream Arrow IPC straight into pandas, polars or DuckDB without a file in between.

Getting started

Install it, point it at a server, and write a row:

brew install basekick-labs/tap/arcli
 
arcli config create --name local --endpoint http://localhost:8000 --token YOUR-TOKEN
arcli db create metrics
echo "cpu,host=web-1 usage=0.63 $(date +%s)000000000" | arcli write --database metrics
arcli query --database metrics "SELECT * FROM cpu"

For more than one server, add profiles and switch between them:

pass show arc/prod | arcli config create --name prod --endpoint https://arc.example.net --token-stdin
arcli query -c prod "SELECT count(*) FROM cpu"   # one command against prod
arcli config set-active prod                      # or change the default

--token-stdin reads the token from a pipe, which keeps it out of shell history and out of ps. In CI, ARC_ENDPOINT and ARC_TOKEN work with no config file at all. If your Arc runs with auth.enabled = false, the token is optional and arcli sends no Authorization header.

Real data in one command

A single point proves the write path works. It does not show you what Arc is for. So arcli sample loads a real public dataset into a database you own:

arcli sample load citibike

That is a month of New York City Citi Bike trips: 1,003,770 rows across 31 daily Parquet files, about 39 MiB. arcli creates the database, downloads the files four at a time, checks each one against a published SHA-256, imports them, and prints two queries to run against what landed.

Verified 31 files against the published checksums.
Imported 31 files, 1003770 rows into nyc.citibike_trips

The first printed query returns the busiest stations, W 21 St & 6 Ave at the top with 4,070 trips, then W 31 St & 7 Ave. Midtown and the Flatiron, which is what anyone who knows the city would guess. The second is a window function over a million rows, hourly departures with a moving average, and it shows the commute curve: quiet at 02:00, climbing through the morning, peaking at 17:00.

Interrupted downloads resume, since a file already present with a matching checksum is not fetched again. If the target measurement already holds rows, arcli says so and asks before adding more, so a second run cannot silently double the numbers. arcli sample show citibike -o json prints every file URL and checksum if you would rather fetch them yourself and use arcli import parquet.

The admin surface

Queries and writes are the obvious part. The rest of arcli is the work that used to be curl and a wiki page:

  • Tokens: create, rotate, revoke and delete API tokens, set permissions and expiry, see which token was last used when
  • Data lifecycle: retention policies and continuous queries, each with a dry run before anything is deleted or written, and an execution history afterwards
  • Deletes: remove rows by SQL predicate, with the row and file count shown before you confirm
  • Backups: create, inspect, restore and delete server-side backups
  • Operations: cluster and compaction status, a manual compaction trigger, the scheduler state, and the server's recent log entries filtered by level and time window
  • Bulk import: CSV, line protocol, Parquet and TLE files, parsed server side

Every one of those is a subcommand with its own flags, prompts and output formats. arcli logs --level error --since 6h is a lot shorter than the curl equivalent.

Built for scripts

Anything that runs in a terminal ends up in a pipeline eventually, so the details that matter to scripts are fixed:

Results go to stdout. Warnings, progress, prompts and errors go to stderr. Exit code 0 means the command did what it said, 1 means anything else, and an interrupted command exits 130 with a line telling you the server may still be working. Destructive commands prompt [y/N], default no, and refuse to run unattended unless you pass --yes.

Tokens are redacted everywhere arcli prints them. The two commands whose job is to hand you a new secret, auth token create and auth token rotate, print that secret alone on stdout so TOKEN=$(arcli auth token create --name ci --permission write) captures it cleanly and nothing else.

Shell completion ships for bash, zsh, fish and PowerShell, and it knows your setup: -c <TAB> completes the connection names from your config file, and enum flags complete to their valid values. Completion never contacts a server. Man pages are installed by the packages and the Homebrew formula.

Privacy

With one exception, every request goes to the Arc server you configured, and the only thing arcli writes is ~/.arcli/config.toml. The exception is arcli sample, which downloads datasets from samples.basekick.net. Those requests carry the same headers as any other arcli request and never your token, your Arc endpoint or anything about your data, but fetching a file from a server does reveal your IP address and the file you asked for, the same as any website.

There is one identifier. The first time arcli writes that file it generates a random installation id and sends it to your own Arc servers in a header. Arc's own telemetry, which is opt-out and off if you turned it off, can then report how many CLI installations talk to how many instances. Because the id is the same for every server you use, it links the servers one installation talks to. DO_NOT_TRACK=1 or send_installation_id = false stops it, and arcli config current shows the id and whether it is being sent. The full statement is on the privacy page.

Versions and compatibility

arcli follows Arc's calendar versioning and talks to Arc 26.06 or newer, 26.09.4 at the time of writing. Every release ships archives for Linux, macOS and Windows on amd64 and arm64, deb, rpm and Arch packages, a multi-arch image on GHCR, a checksums.txt signed with cosign, and an SBOM per archive.

Because Go only accepts v0 and v1 tags for a module path without a version suffix, go install ...@latest builds the current main rather than a tagged release. The packages and Homebrew are the supported channels.

What is next

The Enterprise surface is the gap: query governance, RBAC, audit, tiering, spoke and MQTT all have endpoints that arcli does not wrap yet. An interactive shell and debug subcommands are on the list after that.

If a command is missing, awkward, or wrong, open an issue or say something in Discord.


Arc is an open source, SQL-native time-series database. Single Go binary, Parquet storage on infrastructure you own. Get started.

Ready to handle billion-record workloads?

Deploy Arc in minutes. Own your data in open files on your storage. Use for analytics, observability, AI, IoT, or data warehousing.

Get Started ->