DNS operations CLI for ClouDNS accounts reached through an IP-whitelisted VPS. It can run either from an operator machine through SSH, or directly on the whitelisted VPS itself. Target audience is agents managing DNS for their site-owners.
npm install
npm install -g . # makes `cloudns` available system-wideCreate .env in the project root:
cp .env.example .envFill in:
CLOUDNS_TRANSPORT=ssh|direct
CLOUDNS_AUTH_ID=
CLOUDNS_AUTH_PASSWORD=
For CLOUDNS_TRANSPORT=ssh, also set:
VPS_HOST=
VPS_USER=
VPS_SSH_KEY=
Transport selection can also be passed on the command line with --transport or -t.
ssh: run API calls as remotecurlcommands over SSH on the whitelisted VPSdirect: run localcurlon the current machine, intended for agents already running on the whitelisted VPS
If both env and CLI transport selectors are present, they must match. If neither is set:
- interactive TTY runs prompt for transport selection once
- non-interactive runs fail fast with exit code
2
On first interactive run, if .env is missing, the CLI creates it from .env.example, writes the selected CLOUDNS_TRANSPORT value back into .env, and then prompts for any remaining missing required fields. Secret fields such as CLOUDNS_AUTH_PASSWORD are captured without echoing the value back into terminal output.
In SSH mode, credentials are sent in POST data over SSH stdin and are not placed in the local SSH command line.
$ cloudns auth check -t direct
✓ CloudNS auth check ok
$ cloudns auth check
✗ CloudNS auth check failed: transport must be set via --transport or CLOUDNS_TRANSPORT in non-interactive mode
$ cloudns capabilities -f json
{"ok":true,"command":"capabilities","status":"ok","exitCode":0,"data":{"name":"cloudns-tools",...
$ cloudns doctor -f json
{"ok":true,"command":"doctor","status":"ok","exitCode":0,"transport":{"mode":"direct","selectedBy":"env"},...
capabilities does not require .env; it reports the installed command contract for agents. doctor is non-mutating and checks local config plus a read-only CloudNS API probe when configuration is complete.
$ cloudns zone list
✓ zone list · 2 zones · ok
- fieldnotes.net
- fieldnotes.ru
$ cloudns zone list -f json
{"action":"zone list","status":"ok","recordsAffected":2,"data":[{"name":"fieldnotes.net"},{"name":"fieldnotes.ru"}]}
$ cloudns record list fieldnotes.net
✓ record list · 5 records · ok
- A · @ · 203.0.113.42 · ttl 3600
- A · www · 203.0.113.42 · ttl 3600
- MX · @ · in1-smtp.messagingengine.com · ttl 3600
- TXT · @ · v=spf1 include:spf.messagingengine.com ?all · ttl 3600
- CNAME · blog · ext.blogging.example · ttl 3600
Adding a record that already exists is a no-op and exits 0:
$ cloudns record add fieldnotes.net -T A -N dev -V 203.0.113.55
✓ record add · 1 records affected · ok
$ cloudns record add fieldnotes.net -T A -N dev -V 203.0.113.55
skipped record add · 0 records affected · already exists
$ cloudns preset diff fieldnotes.net fastmail
✓ preset diff · 3 changes · ok
additions:
- MX · @ · in1-smtp.messagingengine.com
- MX · @ · in2-smtp.messagingengine.com
- TXT · @ · v=spf1 include:spf.messagingengine.com ?all
$ cloudns backup create fieldnotes.net
✓ backup create · 5 records affected · ok
wrote backups/fieldnotes.net-20260425T093000.json
Agents can call the CLI with JSON instead of shell-style arguments:
cloudns api --input request.json
cloudns api --input - < request.jsonExample request:
{
"schemaVersion": 1,
"operation": "record.add",
"options": { "transport": "direct", "dryRun": true },
"target": { "zone": "fieldnotes.net" },
"record": {
"type": "A",
"name": "dev",
"value": "203.0.113.55",
"ttl": 3600
}
}0: success1: API, SSH, or runtime failure2: config, auth, or usage failure3: dry-run prevented a write
See docs/guide.md for the full command reference.
Runtime-safe presets live in templates/.
The richer provider reference catalog lives in docs/examples/.
Created with Claude Code, Codex, Perplexity, Superpowers by Jesse Vincent and Get Shit Done by TÂCHES, in cross-review and careful testing.