Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Comprehensive Gandi domain registrar integration for domain and DNS management. Register and manage domains, create/update/delete DNS records (A, AAAA, CNAME, MX, TXT, SRV, and more), configure email forwarding and aliases, check SSL certificate status, create DNS snapshots for safe rollback, bulk update zone files, and monitor domain expiration. Supports multi-domain management, zone file import/export, and automated DNS backups. Includes both read-only and destructive operations with safety co
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-24 | ✗→✓ | ▲ Improved | — | — |
| case-10 | ✗→✓ | ▲ Improved | — | — |
| case-18 | ✗→✓ | ▲ Improved | — | — |
| case-25 | ✗→✓ | ▲ Improved | — | — |
| case-07 | ✗→✓ | ▲ Improved | — | — |
Comprehensive Gandi domain registrar integration for Moltbot.
Status: ✅ Phase 2 Complete - DNS modification & snapshots functional
This skill can perform DESTRUCTIVE operations on your Gandi account:
Before running ANY script:
create-snapshot.js)Destructive scripts (⚠️ modify or delete data):
add-dns-record.js, delete-dns-record.js, update-dns-bulk.jsadd-email-forward.js, update-email-forward.js, delete-email-forward.jsrestore-snapshot.js (replaces current DNS)Read-only scripts (✅ safe, no modifications):
list-domains.js, list-dns.js, list-snapshots.jslist-email-forwards.js, check-domain.js, check-ssl.js📖 For complete script documentation: See SCRIPTS.md for detailed information about:
⚠️ Security Recommendation: Use the minimum required scopes for your use case.
Read-Only (Recommended for viewing only):
Write Access (Required for modifications - use with caution):
Security Best Practices:
Scripts check for credentials in priority order:
GANDI_API_TOKEN environment variable (checked first)~/.config/gandi/api_token file (fallback if env var not set)Choose the method that fits your workflow:
bash# Set environment variable (replace YOUR_PAT with actual token) export GANDI_API_TOKEN="YOUR_PERSONAL_ACCESS_TOKEN" # Add to shell profile for persistence (~/.bashrc, ~/.zshrc, etc.) echo 'export GANDI_API_TOKEN="YOUR_PERSONAL_ACCESS_TOKEN"' >> ~/.bashrc
Benefits:
bash# Create config directory mkdir -p ~/.config/gandi # Store your token (replace YOUR_PAT with actual token) echo "YOUR_PERSONAL_ACCESS_TOKEN" > ~/.config/gandi/api_token # Secure the file (owner read-only) chmod 600 ~/.config/gandi/api_token
Benefits:
Required: Node.js >= 18.0.0
bashcd gandi-skill/scripts # Install npm dependencies npm install # Verify installation npm list --depth=0
Expected packages:
Troubleshooting:
node or npm not found: Install Node.js from nodejs.orgsudo - fix npm permissions or use nvmnode_modules/ and package-lock.json, then npm install againbashcd gandi-skill/scripts node test-auth.js
Expected output:
✅ Authentication successful!
Your organizations:
1. Personal Account (uuid-here)
Type: individual
🎉 You're ready to use the Gandi skill!If you plan to register domains, save your contact information once for reuse:
bashcd gandi-skill/scripts node setup-contact.js
The script will prompt for:
Contact information is saved to:
~/.config/gandi/contact.jsonPrivacy Options:
delete-contact.jsManaging saved contact:
bash# View current contact node view-contact.js # Update contact info or privacy preference node setup-contact.js # Delete saved contact manually node delete-contact.js # Delete without confirmation node delete-contact.js --force
One-time purge override:
bash# Register and delete contact (even if preference is "retain") node register-domain.js example.com --purge-contact
bashnode list-domains.js
Output shows:
bashnode list-dns.js example.com
Output shows:
Once configured, you can use natural language:
> "List my Gandi domains"
> "Show DNS records for example.com"
> "When does example.com expire?"
> "Is auto-renewal enabled for example.com?"
Check if a specific domain is available for registration:
bashnode check-domain.js example.com
Features:
Example Output:
🔍 Checking availability for: example.com
Domain: example.com
✅ Status: AVAILABLE
💰 Pricing:
1 year: 12.00 EUR (+ 2.40 tax)
2 years: 24.00 EUR (+ 4.80 tax)
📋 Supported Features:
• create
• dnssec
• livedns
🌐 TLD Information:
Extension: comFind available alternatives with TLD variations and name modifications:
bash# Check all configured TLDs + variations node suggest-domains.js example # Check specific TLDs only node suggest-domains.js example --tlds com,net,io # Skip name variations (only check TLDs) node suggest-domains.js example --no-variations # Output as JSON node suggest-domains.js example --json
Name Variation Patterns:
example → ex-ample)example → exmpl)example → get-example, my-example)example → example-app, example-hub)example → example2, example3)Example Output:
🔍 Checking availability for: example
📊 Checking 13 TLDs and generating variations...
═══════════════════════════════════════════════════════
📋 EXACT MATCHES (Different TLDs)
═══════════════════════════════════════════════════════
✅ Available:
example.net 12.00 EUR
example.io 39.00 EUR
example.dev 15.00 EUR
❌ Unavailable:
example.com (unavailable)
example.org (unavailable)
═══════════════════════════════════════════════════════
🎨 NAME VARIATIONS
═══════════════════════════════════════════════════════
Hyphenated:
✅ ex-ample.com 12.00 EUR
Prefix:
✅ get-example.com 12.00 EUR
✅ my-example.com 12.00 EUR
Suffix:
✅ example-app.com 12.00 EUR
✅ example-io.com 12.00 EUR
═══════════════════════════════════════════════════════
📊 SUMMARY: 8 available domains found
═══════════════════════════════════════════════════════Domain checker configuration is stored in gandi-skill/config/domain-checker-defaults.json.
Structure:
json{ "tlds": { "mode": "extend", "defaults": ["com", "net", "org", "info", "io", "dev", "app", "ai", "tech"], "custom": [] }, "variations": { "enabled": true, "patterns": ["hyphenated", "abbreviated", "prefix", "suffix", "numbers"], "prefixes": ["get", "my", "the", "try"], "suffixes": ["app", "hub", "io", "ly", "ai", "hq"], "maxNumbers": 3 }, "rateLimit": { "maxConcurrent": 3, "delayMs": 200, "maxRequestsPerMinute": 100 }, "limits": { "maxTlds": 5, "maxVariations": 10 } }
Rate Limiting & Limits:
These limits ensure good API citizenship and prevent overwhelming Gandi's API.
TLD Modes:
"extend": Use defaults + custom TLDs (merged list)"replace": Use only custom TLDs (ignore defaults)Gateway Console Integration:
When Gateway Console support is added (#3), configuration will be available at:
yamlskills: entries: gandi: config: domainChecker: tlds: mode: extend defaults: [...] custom: [...] variations: enabled: true patterns: [...]
See docs/gateway-config-design.md for complete configuration architecture.
Create or update individual DNS records:
bash# Add an A record for root domain node add-dns-record.js example.com @ A 192.168.1.1 # Add www subdomain pointing to root node add-dns-record.js example.com www CNAME @ # Add MX record for email node add-dns-record.js example.com @ MX "10 mail.example.com." # Add TXT record for SPF node add-dns-record.js example.com @ TXT "v=spf1 include:_spf.google.com ~all" # Add with custom TTL (5 minutes) node add-dns-record.js example.com api A 192.168.1.10 300
Supported record types: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, PTR
Remove specific DNS records:
bash# Delete old A record node delete-dns-record.js example.com old A # Delete with confirmation prompt node delete-dns-record.js example.com test CNAME # Delete without confirmation node delete-dns-record.js example.com old A --force
Replace all DNS records at once:
bash# From JSON file node update-dns-bulk.js example.com new-records.json # From stdin cat records.json | node update-dns-bulk.js example.com # Skip automatic snapshot node update-dns-bulk.js example.com records.json --no-snapshot # Skip confirmation node update-dns-bulk.js example.com records.json --force
JSON format:
json[ { "rrset_name": "@", "rrset_type": "A", "rrset_ttl": 10800, "rrset_values": ["192.168.1.1"] }, { "rrset_name": "www", "rrset_type": "CNAME", "rrset_ttl": 10800, "rrset_values": ["@"] }, { "rrset_name": "@", "rrset_type": "MX", "rrset_ttl": 10800, "rrset_values": ["10 mail.example.com.", "20 mail2.example.com."] } ]
Create safety backups before making changes:
bash# Create a snapshot node create-snapshot.js example.com "Before migration" # List all snapshots node list-snapshots.js example.com # Restore from a snapshot node restore-snapshot.js example.com abc123-def456-ghi789 # Restore without confirmation node restore-snapshot.js example.com abc123-def456-ghi789 --force
Automatic snapshots:
--no-snapshot)bash# Root domain node add-dns-record.js example.com @ A 192.168.1.1 # WWW subdomain node add-dns-record.js example.com www CNAME @
bash# MX records node add-dns-record.js example.com @ MX "1 ASPMX.L.GOOGLE.COM." node add-dns-record.js example.com @ MX "5 ALT1.ASPMX.L.GOOGLE.COM." node add-dns-record.js example.com @ MX "5 ALT2.ASPMX.L.GOOGLE.COM." # SPF record node add-dns-record.js example.com @ TXT "v=spf1 include:_spf.google.com ~all"
To redirect one domain to another:
bash# Point root domain to same server node add-dns-record.js old-domain.com @ A 192.168.1.1 # Point www to same CNAME node add-dns-record.js old-domain.com www CNAME @
Then configure HTTP 301 redirect at the server level.
bash# API subdomain node add-dns-record.js example.com api A 192.168.1.10 # Staging subdomain node add-dns-record.js example.com staging A 192.168.1.20 # Wildcard subdomain node add-dns-record.js example.com "*" A 192.168.1.100
See all email forwards configured for a domain:
bashnode list-email-forwards.js example.com
Forward emails to one or more destinations:
bash# Simple forward node add-email-forward.js example.com hello you@personal.com # Forward to multiple destinations node add-email-forward.js example.com support team1@example.com team2@example.com # Catch-all forward (forwards all unmatched emails) node add-email-forward.js example.com @ catchall@example.com
Change the destination(s) for an existing forward:
bash# Update single destination node update-email-forward.js example.com hello newemail@personal.com # Update to multiple destinations node update-email-forward.js example.com support new1@example.com new2@example.com
Note: This replaces all existing destinations with the new ones.
Remove email forwards:
bash# Delete with confirmation prompt node delete-email-forward.js example.com old # Delete without confirmation node delete-email-forward.js example.com old --force # Delete catch-all forward node delete-email-forward.js example.com @ --force
bash# Forward contact@ to your personal email node add-email-forward.js example.com contact you@gmail.com # Forward sales@ to team node add-email-forward.js example.com sales team@example.com
bash# Forward all email from old domain to new domain # Preserves the local part (username before @) # First, list existing forwards on old domain node list-email-forwards.js old-domain.com # Then create matching forwards on new domain node add-email-forward.js old-domain.com contact contact@new-domain.com node add-email-forward.js old-domain.com support support@new-domain.com # Or use catch-all to forward everything node add-email-forward.js old-domain.com @ admin@new-domain.com
bash# Forward to entire team node add-email-forward.js example.com team alice@example.com bob@example.com charlie@example.com # Update team members node update-email-forward.js example.com team alice@example.com dave@example.com
bash# Forward all unmatched emails to one address node add-email-forward.js example.com @ catchall@example.com # Forward all unmatched emails to multiple addresses node add-email-forward.js example.com @ admin1@example.com admin2@example.com
Note: Catch-all forwards only apply to email addresses that don't have specific forwards configured.
bash# 1. Set up MX records (if not already done) node add-dns-record.js example.com @ MX "10 spool.mail.gandi.net." node add-dns-record.js example.com @ MX "50 fb.mail.gandi.net." # 2. Create specific forwards node add-email-forward.js example.com hello you@personal.com node add-email-forward.js example.com support team@example.com node add-email-forward.js example.com sales sales-team@example.com # 3. Set up catch-all for everything else node add-email-forward.js example.com @ admin@example.com # 4. List all forwards to verify node list-email-forwards.js example.com
All scripts are in gandi-skill/scripts/:
| Script | Purpose | |--------|---------| | test-auth.js | Verify authentication works | | setup-contact.js | Save contact info for domain registration (run once) | | view-contact.js | View saved contact information | | delete-contact.js | Delete saved contact (with optional --force) |
| Script | Purpose | |--------|---------| | list-domains.js | Show all domains in account | | list-dns.js <domain> | Show DNS records for domain | | check-domain.js <domain> | Check single domain availability + pricing | | suggest-domains.js <name> | Smart domain suggestions with variations | | check-ssl.js | Check SSL certificate status for all domains |
| Script | Purpose | |--------|---------| | add-dns-record.js <domain> <name> <type> <value> [ttl] | Add or update a DNS record | | delete-dns-record.js <domain> <name> <type> [--force] | Delete a DNS record | | update-dns-bulk.js <domain> <records.json> [--no-snapshot] [--force] | Bulk update all DNS records | | list-snapshots.js <domain> | List DNS zone snapshots | | create-snapshot.js <domain> [name] | Create a DNS zone snapshot | | restore-snapshot.js <domain> <snapshot-id> [--force] | Restore DNS zone from snapshot |
| Script | Purpose | |--------|---------| | list-email-forwards.js <domain> | List all email forwards for a domain | | add-email-forward.js <domain> <mailbox> <destination> [dest2...] | Create email forward (use @ for catch-all) | | update-email-forward.js <domain> <mailbox> <destination> [dest2...] | Update email forward destinations | | delete-email-forward.js <domain> <mailbox> [--force] | Delete email forward |
| Script | Purpose | |--------|---------| | gandi-api.js | Core API client (importable) |
~/.config/gandi/api_token (API authentication)~/.config/gandi/contact.json (domain registration info, optional)https://api.gandi.net (production)To use Gandi's sandbox environment:
bash# Create sandbox token at: https://admin.sandbox.gandi.net echo "YOUR_SANDBOX_TOKEN" > ~/.config/gandi/api_token echo "https://api.sandbox.gandi.net" > ~/.config/gandi/api_url
bash# Verify file exists ls -la ~/.config/gandi/api_token # Should show: -rw------- (600 permissions)
If you get "not using Gandi LiveDNS" error:
Gandi allows 1000 requests/minute. If exceeded:
The skill provides importable functions:
javascriptimport { testAuth, listDomains, getDomain, listDnsRecords, getDnsRecord, checkAvailability } from './gandi-api.js'; // Test authentication const auth = await testAuth(); // List domains const domains = await listDomains(); // Get domain info const domain = await getDomain('example.com'); // List DNS records const records = await listDnsRecords('example.com'); // Get specific DNS record const record = await getDnsRecord('example.com', '@', 'A'); // Check availability const available = await checkAvailability(['example.com', 'example.net']);
✅ DO:
~/.config/gandi/api_token❌ DON'T:
Phase 1 (current):
Phase 2+ (future):
gandi-skill/
├── SKILL.md # This file
├── references/ # API documentation
│ ├── api-overview.md
│ ├── authentication.md
│ ├── domains.md
│ ├── livedns.md
│ └── setup.md
└── scripts/ # Helper utilities
├── package.json
├── gandi-api.js # Core API client
├── test-auth.js # Test authentication
├── list-domains.js # List domains
└── list-dns.js # List DNS recordsPhase 1: Read Operations (✅ Current)
Phase 2: DNS Modifications
Phase 3: Domain Management
Phase 4: Multi-Organization (#1)
Phase 5: Advanced Features
See Contributing Guide in the main README.
MIT License - See LICENSE
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-24 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-25 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-23 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +76 percentage points is the difference between those two pass rates over the 25 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.