CLI for Arc — operator-facing client for Arc time-series databases.
Status: v0.4.0-dev (PR4). Manages connection profiles, runs SQL queries, writes line protocol, administers databases + measurements, and bulk-imports CSV / LP / Parquet / TLE files.
auth/clustersubcommands ship in follow-up PRs.
Today operating Arc means hand-crafting curl calls: copying the bootstrap token from a stderr banner, building JSON query bodies, remembering header names like x-arc-database, and decoding {"columns":[...],"data":[...]} responses by eye. arcctl replaces that with a familiar CLI workflow modeled on influx, kubectl, and clickhouse-client.
Pre-built binaries + Docker images + Homebrew formula land in v1.0.
For now, build from source:
git clone https://github.com/Basekick-Labs/arcctl
cd arcctl
go build -o arcctl ./cmd/arcctl
./arcctl --versionRequires Go 1.25+.
# 1. Create a connection profile from your Arc instance's bootstrap token
arcctl config create \
--name local \
--endpoint http://localhost:8000 \
--token <token-from-arc-stderr-banner>
# 2. Confirm it's active (first connection auto-activates)
arcctl config current
# 3. List all profiles
arcctl config listarcctl stores connection profiles in ~/.arcctl/config.toml (mode 0600). One profile is marked active; commands use it by default.
# Add multiple environments
arcctl config create --name prod --endpoint https://arc.prod.example.com --token PROD-TOK
arcctl config create --name staging --endpoint https://arc.staging.example.com --token STAGING-TOK --default-database metrics
# Switch active
arcctl config set-active staging
# Override per-command (later PRs)
arcctl --connection prod query "SELECT count(*) FROM cpu"
# Or via env vars (CI-friendly)
ARC_CONNECTION=prod arcctl query "..."
ARC_ENDPOINT=https://... ARC_TOKEN=... arcctl query "..."
# Show active (token redacted)
arcctl config current
# Remove
arcctl config delete staging --yes--connection NAMEflag--endpoint URL --token Tflags (full ad-hoc)ARC_CONNECTIONenv varARC_ENDPOINT+ARC_TOKENenv vars (full ad-hoc)- Active connection in
~/.arcctl/config.toml
If none are set, commands fail with a clear "no active connection" error.
Honors ARCCTL_CONFIG env var for test/CI overrides; otherwise ~/.arcctl/config.toml.
# Pretty table (default)
arcctl query "SELECT host, value FROM cpu ORDER BY value LIMIT 10"
# Override the database for one call
arcctl query --database metrics "SELECT count(*) FROM cpu"
# Read SQL from a file
arcctl query -f reports/p99.sql
# Pipe SQL from another command
echo "SELECT 1" | arcctl query
# Machine-parseable output
arcctl query "SELECT * FROM cpu" -o json | jq '.data[0]'
arcctl query "SELECT * FROM cpu" -o csv > out.csv
# Arrow IPC stream — feed it to pyarrow / duckdb / polars
arcctl query "SELECT * FROM cpu" -o arrow | duckdb -c "SELECT * FROM read_arrow('/dev/stdin')"The output formats:
-o table(default) — pretty-printed bordered table; honors--no-headerand--limit N-o json— the raw{"columns":[...],"data":[...]}response, jq-friendly-o csv— RFC 4180 with a header row by default-o arrow— binary Arrow IPC stream on stdout; server-side execution time goes to stderr
# Stdin pipe (most common in CI / log forwarders)
echo "cpu,host=server-1 value=42.5 $(date +%s)000000000" | arcctl write
# From a file
arcctl write -f payload.lp --database metrics --precision ms
# Explicit precision (default is nanoseconds, matching the server)
echo "cpu v=1 1700000000" | arcctl write --precision s--precision accepts ns, us, ms, or s (anything else is rejected client-side before the request goes out). The body is streamed end-to-end — cat huge.lp | arcctl write never buffers the whole payload in memory.
# List every database the active token can see
arcctl db list
# Inspect one database (info + its measurements)
arcctl db show production
# Create an empty database (server validates name: alphanumeric + `_-`,
# max 64 chars, "system" / "internal" / "_internal" are reserved)
arcctl db create metrics
# Drop a database and ALL its files. Prompts for y/N; pass --yes to
# skip in scripts. The server requires delete.enabled=true in arc.toml
# AND an admin token — if either is missing the server's error message
# surfaces verbatim ("Set delete.enabled=true in arc.toml to enable.").
arcctl db drop old_metrics
arcctl db drop --yes ci_scratch # no prompt
# List measurements inside a database (same data shown by `db show`,
# different default view)
arcctl measurement list --database metrics
arcctl measurement list -c prod --database logs -o jsondb list, db show, and measurement list all support -o table|json|csv (no -o arrow — these endpoints return JSON, not Arrow IPC).
arcctl import ships four file-import flows backed by Arc's admin-only /api/v1/import/* endpoints. Upload bodies are streamed via io.Pipe, so even multi-GB files don't buffer in memory.
# CSV — file has no measurement, so --measurement is required
arcctl import csv -f data.csv --database metrics --measurement cpu
arcctl import csv -f data.csv --database metrics --measurement cpu \
--time-column ts --time-format epoch_ms --delimiter ';' --skip-rows 1
# Line protocol — measurement comes from the LP lines themselves;
# --measurement here is an optional filter. Server auto-detects gzip.
arcctl import lp -f telegraf.lp --database metrics
arcctl import lp -f data.lp.gz --database metrics --precision ms
arcctl import lp -f data.lp --database metrics --measurement cpu # filter
# Parquet — preserves types end-to-end (faster + lossless vs CSV)
arcctl import parquet -f data.parquet --database metrics --measurement cpu
# TLE (NORAD two-line element / satellite tracking)
arcctl import tle -f starlink.tle --database satellites
arcctl import tle -f starlink.tle --database satellites --measurement starlinkAll four require an admin token (server-side adminAuth). Each prints either a pretty result block or -o json for scripting; server errors (auth, validation, "file is empty", quota) surface verbatim.
For HTTPS endpoints, certificate verification is on by default. To skip verification (lab / self-signed certs only), use either:
--insecureon a single command, orinsecure_tls = truein the connection profile (set once viaarcctl config create --insecure)
When verification is skipped, a WARNING: line is printed to stderr. The flag is a no-op on http:// endpoints and the warning is suppressed.
This repo is being built in phased PRs:
PR1 — scaffold,✅ shippedconfigsubcommand tree, multi-connection storePR2 —✅ shippedarcctl query,arcctl write, output formats: table/json/csv/arrowPR3 —✅ shippedarcctl db {list,show,create,drop},arcctl measurement listPR4 —✅ shippedarcctl import {csv,lp,parquet,tle}(msgpack write deferred to a follow-up)- PR5 —
arcctl auth {token,whoami} - PR6 —
arcctl cluster {status,nodes},arcctl compaction,arcctl retention - PR7 —
arcctl write --format msgpack(msgpack-write follow-up) - PR8 — release workflow + Homebrew tap + multi-arch Docker, cut v1.0.0
Target: arcctl 1.x speaks to Arc 26.06+.
go test -race ./...
go vet ./...
gofmt -l .CI runs all three on every PR.
Apache-2.0. See LICENSE.