dnscale-cli

module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2026 License: MIT

README

DNScale CLI

Manage DNS zones and records, inspect DNSSEC, and read usage from scripts or a terminal. The standalone Go module uses the public DNScale Go SDK.

Current release: 1.0.0. Start with read-only commands and offline validation, then test record changes in a disposable zone before using them in production.

Install

Homebrew (macOS and Linux)
brew install dnscaleou/tap/dnscale
dnscale --version

The official tap selects your platform's release archive, verifies its checksum, and installs Bash, Zsh, and Fish completions. Upgrade with brew upgrade dnscale, or uninstall with brew uninstall dnscale.

Binary downloads

Download your platform's archive and checksums.txt from the 1.0.0 release. Prebuilt binaries do not require Go.

Platform Archive
macOS Apple Silicon dnscale_1.0.0_darwin_arm64.tar.gz
macOS Intel dnscale_1.0.0_darwin_amd64.tar.gz
Linux ARM64 dnscale_1.0.0_linux_arm64.tar.gz
Linux AMD64 dnscale_1.0.0_linux_amd64.tar.gz
Windows AMD64 dnscale_1.0.0_windows_amd64.zip

On macOS or Linux, compare the SHA-256 hash with the matching line in checksums.txt before extracting. For example, on Apple Silicon:

shasum -a 256 dnscale_1.0.0_darwin_arm64.tar.gz
tar -xzf dnscale_1.0.0_darwin_arm64.tar.gz
mkdir -p "$HOME/.local/bin"
install -m 755 dnscale "$HOME/.local/bin/dnscale"
export PATH="$HOME/.local/bin:$PATH"
dnscale --version

Use the archive name for your platform. Linux also provides sha256sum for verification. Add the PATH setting to your shell startup file to keep it across sessions. Archives include the quickstart and example record files.

On Windows, compare the hash with checksums.txt, then extract the archive and add the destination directory to your user PATH:

Get-FileHash .\dnscale_1.0.0_windows_amd64.zip -Algorithm SHA256
Expand-Archive .\dnscale_1.0.0_windows_amd64.zip -DestinationPath "$env:LOCALAPPDATA\DNScale\bin" -Force
& "$env:LOCALAPPDATA\DNScale\bin\dnscale.exe" --version
Install with Go

With Go 1.25 or newer:

go install github.com/dnscaleou/dnscale-cli/cmd/dnscale@v1.0.0

Add GOBIN, or the bin directory under go env GOPATH when GOBIN is unset, to your PATH.

Build from source
git clone --branch v1.0.0 https://github.com/dnscaleou/dnscale-cli.git
cd dnscale-cli
make build
bin/dnscale --version
bin/dnscale --help

Build/check/release targets pin Go 1.25.14 using .go-version and Go's toolchain selection. On Windows, use go build -o bin/dnscale.exe ./cmd/dnscale.

Upgrade, remove, and complete commands

For manual installs, download and verify the new archive, then replace the binary. Go users can install the desired version tag or use @latest. Remove the installed binary and completion files to uninstall. Run dnscale auth logout --profile NAME for each saved profile first if you also want to remove its keychain credential; revoke API keys separately in the dashboard.

Generate completion with dnscale completion bash, zsh, fish, or powershell; its help describes installation for each shell. Homebrew installs Bash, Zsh, and Fish completions automatically.

Authentication

Create a scoped API key in the DNScale dashboard. Set DNSCALE_API_KEY from your secret manager or CI secret. The CLI never reads .env files and never accepts a key as a command-line flag.

dnscale auth status
dnscale auth login --profile work       # stores DNSCALE_API_KEY in OS keychain
dnscale auth status --profile work
dnscale auth profiles
dnscale auth use work
dnscale auth logout --profile work     # local removal; does not revoke the key

auth login --key-stdin reads a token from stdin instead of the environment. It never prompts. Keychain failure returns an error; there is no plaintext fallback. Environment authentication works in CI without a keychain.

Credentials are bound to the endpoint saved with a profile. For a provisioned sandbox, save a separate profile with its actual /v1 URL:

dnscale auth login --profile sandbox --base-url https://YOUR_SANDBOX_HOST/v1

The endpoint defaults to https://api.dnscale.eu/v1. A profile named sandbox does not simulate DNS writes. auth status reports local configuration only; it does not validate a key or infer account identity.

Selection order:

  1. --profile, then DNSCALE_PROFILE: use only that stored profile and ignore ambient DNSCALE_API_KEY and DNSCALE_BASE_URL.
  2. Otherwise, DNSCALE_API_KEY uses --base-url, then DNSCALE_BASE_URL, then the default endpoint.
  3. Otherwise, use the default saved profile. An incompatible --base-url is rejected for stored credentials.

Metadata lives in <os.UserConfigDir()>/dnscale/config.json, or $DNSCALE_CONFIG_DIR/config.json, with atomic file replacement and restrictive permissions. Keys live in OS keychain service eu.dnscale.cli under IDs derived from the profile and endpoint. Profiles contain no tokens.

Commands

Command Purpose
zones list [--offset N --limit N --all] Accessible zones; limit 1–100
zones get ZONE Zone details
zones create DOMAIN [--region EU|GLOBAL|EU_GLOBAL] Active master zone; region defaults to EU_GLOBAL
records list ZONE [--offset N --limit N --all] Records; limit 1–1000
records get ZONE RECORD_ID One record value
records create ZONE Create a value using record flags or a file
records update ZONE RECORD_ID Replace the selected value using a complete body
records delete ZONE RECORD_ID --yes Delete the selected value
dnssec status ZONE Signing status; disabled is a successful result
dnssec ds ZONE Public DS records; an empty result is []
usage current Current billing-month usage
usage summary [--month YYYY-MM] Selected month; defaults to current
usage zone ZONE [--start-date DATE --end-date DATE] Daily zone usage; supply both dates or neither
completion bash|zsh|fish|powershell Generate shell completion

ZONE accepts a UUID or an exact domain name, ignoring case and a terminal dot. Name resolution scans accessible zones with pagination and rejects ambiguity. IDs go directly to the endpoint. Record IDs remain opaque: retain the ID returned after an update. Zone deletion, imports, whole-RRset deletion, and DNSSEC mutations are intentionally outside this command set.

Record input and DNS semantics

dnscale records create example.com --file examples/record.json --dry-run
dnscale records create example.com --name www --type A --content 192.0.2.10 --ttl 300
dnscale records update example.com RECORD_ID --file replacement.json
dnscale records delete example.com REPLACEMENT_RECORD_ID --yes

Files contain one UTF-8 JSON object, up to 1 MiB. --file - reads stdin. File input cannot be mixed with record field flags. Unknown fields, trailing JSON documents, and missing name/type/content fail before authentication or network access. Optional flags are --ttl, --priority, --disabled, and --comment; --disabled=false, --priority 0, and --comment '' are explicit. JSON preserves null for nullable comment and priority fields.

Updates use the API's PUT semantics. Name, type, and content are required; name/type must match the selected record. The CLI does not fetch and merge old fields. Omitted TTL or 0 means the server default of 3600; omitted disabled means false. Omitted/null comment preserves it, while an empty string clears the DNScale-owned comment. TTL and comments apply to the complete RRset. Each sibling retains its own content and disabled state.

Use the documented TTL range 300–86400 seconds. The client also accepts existing API compatibility TTLs below 300 and the zero/default form. MX content is the target name with priority supplied separately. SRV accepts the full priority weight port target content; the API also supplies defaults for a target-only value. SOA and platform NS protections are enforced by the server.

--dry-run on create/update is entirely offline: no credentials, resolution, or HTTP requests. It returns the validated request with submitted: false and validation: "local_only". It does not prove DNS validity, ownership, quota, permissions, or server acceptance. Deletion always requires --yes and never prompts.

JSON, pagination, and errors

Results use indented JSON; --json emits compact JSON. Successful output goes to stdout and errors to stderr. Help, version, and completion are text.

{
  "data": [],
  "context": {
    "profile": "environment",
    "base_url": "https://api.dnscale.eu/v1",
    "credential_source": "environment"
  },
  "pagination": {
    "offset": 0, "limit": 50, "returned": 0, "total": 0, "has_more": false
  },
  "request_id": "server-request-id"
}

context is omitted on offline operations. Pagination appears on lists and includes next_offset when more results remain. --all prints only after all pages succeed and rejects inconsistent pagination or repeated IDs. It is not an atomic snapshot. request_id, when supplied by the server, is from the final request, including when a command resolves a zone name first.

Errors contain error.code, error.message, and, when available, http_status, request_id, and retry_after_seconds. Malformed/plain-string middleware errors retain HTTP metadata and use the SDK's HTTP_ERROR fallback. Credentials are redacted even if an upstream response echoes them.

Exit Meaning
0 Success or successful local validation
1 API, protocol, pagination, or output failure
2 Invalid arguments, input, or local configuration
3 Authentication or permission failure (401/403)
4 Rate limit after eligible read retries
5 Network failure or timeout
130 Interrupted

--timeout defaults to 30 seconds for the entire API command, including zone resolution, pages, and retry waits. --retries defaults to 2 and applies only to safe reads. Mutations are never automatically retried. A failed or timed-out mutation may have completed: inspect state before resubmitting. Regional updates are separate transactions; PARTIAL_RECORD_UPDATE requires checking every affected region. HTTP redirects are rejected. HTTPS is required except for loopback development URLs.

API scopes

Operations Required scopes/access
Zone reads zones:read
Zone creation zones:read, zones:write; customer-wide key
Record reads zones:read, records:read
Record writes Above, plus records:write
DNSSEC inspection zones:read, dnssec:read; full-zone access
Account usage usage:read; customer-wide key
Zone usage zones:read, usage:read; full-zone access

The server enforces zone/name restrictions. The CLI never switches credentials or broadens scope after a denial. DNSSEC inspection does not certify registrar DS configuration or public propagation and never retrieves private keys.

Development

make check           # formatting, race tests, compiled-binary fixtures, vet, modules
make cross-check     # Linux/macOS amd64+arm64, Windows amd64
make build

Tests use local fixtures and need no database, real keychain, or live account.

See the DNS quickstart, license, and dependency notices.

Report issues in dnscaleou/dnscale-cli.

Directories

Path Synopsis
cmd
dnscale command
internal
cli

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL