Namecheap Domain Manager
Manage domains via the Namecheap XML API. All commands require credentials configured in environment variables.
Setup & Authentication
Required environment variables. Put them in a .env file, your shell rc, or
~/.config/claude-skills/namecheap.env. The bundled script will pick them up.
| Variable |
Description |
NAMECHEAP_API_USER |
Your Namecheap username |
NAMECHEAP_API_KEY |
API key from Profile → Tools → API Access |
NAMECHEAP_USERNAME |
Usually same as NAMECHEAP_API_USER |
NAMECHEAP_CLIENT_IP |
Your whitelisted IPv4 address |
NAMECHEAP_USE_SANDBOX |
Set to true for sandbox mode (default: false) |
First-time setup: run scripts/nc_api.sh --setup to be prompted for each value and
have a ~/.config/claude-skills/namecheap.env file written for you.
Get an API key: sign in at namecheap.com, go to Profile → Tools → API Access, enable
API access, then create a key. The key is shown only once — copy it.
IP Whitelisting: Namecheap requires the calling IP to be whitelisted. Only IPv4 is supported. The user must whitelist their IP at Profile > Tools > API Access > Whitelisted IPs.
Production API requirements (at least one must be met):
- 20+ domains in the account
- $50+ account balance
- $50+ in purchases within the last 2 years
Sandbox has no requirements — create a free account at https://www.sandbox.namecheap.com/.
API Base URLs
| Environment |
URL |
| Production |
https://api.namecheap.com/xml.response |
| Sandbox |
https://api.sandbox.namecheap.com/xml.response |
Rate Limits
- 20 requests/minute, 700/hour, 8,000/day
- Batch domain checks using comma-separated lists to conserve quota
Subcommands
/namecheap check <domain1> [domain2] [...]
Check domain availability.
Steps:
- Validate credentials are set (run
scripts/nc_api.sh check-env)
- Accept one or more domain names as arguments (comma or space separated)
- Call
scripts/nc_api.sh check "domain1.com,domain2.com"
- Parse XML response — display results as a table:
| Domain |
Available |
Premium |
Price |
ICANN Fee |
| example.com |
No |
- |
- |
- |
| example.net |
Yes |
No |
- |
$0.18 |
- If any are available, ask if the user wants to register one
/namecheap search <keyword> [tlds]
Search for available domains across multiple TLDs.
Steps:
- Take a keyword and optional TLD list (default:
com,net,org,io,co,dev,app,ai)
- Generate domain combinations:
keyword.com, keyword.net, etc.
- Call
scripts/nc_api.sh check "<comma-separated-list>"
- Display availability table sorted by: available first, then by TLD preference
- Offer to check pricing for available domains
/namecheap register <domain> [years]
Register/purchase a new domain.
Steps:
- Confirm domain is available first (call check if not already confirmed)
- Check pricing:
scripts/nc_api.sh pricing "com" "REGISTER" (use appropriate TLD)
- Display price and ask for confirmation: "Register example.com for N year(s) at $X.XX?"
- Ask the user for contact information OR check if they have a default address configured
- If user wants to use an existing address:
scripts/nc_api.sh get-address-list
- Let user pick an address or enter new contact details
- CRITICAL: Always ask for explicit confirmation before purchasing. Display the total cost.
- Call
scripts/nc_api.sh register "<domain>" "<years>" "<contact_params>"
- Parse response — display: Domain, Order ID, Transaction ID, Charged Amount, WhoisGuard status
- If
AddFreeWhoisguard=yes and WGEnabled=yes were included, confirm privacy is active
Contact fields required (for Registrant, Tech, Admin, AuxBilling — all four):
FirstName, LastName, Address1, City, StateProvince, PostalCode, Country, Phone (+1.2125551234 format), EmailAddress
Optional: OrganizationName, Address2
/namecheap list [filter]
List domains in the account.
Steps:
- Call
scripts/nc_api.sh list "[filter]" where filter can be: all (default), expiring, expired
- Optional search term can be passed to filter by keyword
- Parse XML — display as table:
| Domain |
Created |
Expires |
Auto-Renew |
Locked |
WhoisGuard |
DNS |
| example.com |
2024-01-15 |
2025-01-15 |
Yes |
Yes |
Enabled |
Namecheap |
- Show paging info if more than one page of results
/namecheap info <domain>
Get detailed information about a domain.
Steps:
- Call
scripts/nc_api.sh info "<domain>"
- Parse and display:
- Domain status, ID, owner
- Created/Expires dates, years registered
- WhoisGuard status and expiration
- DNS provider, nameservers list
- Host record count
- Modification rights
/namecheap dns <domain>
Show current DNS records for a domain.
Steps:
- Split domain into SLD and TLD
- Call
scripts/nc_api.sh dns-get "<sld>" "<tld>"
- Display records as table:
| # |
Name |
Type |
Address |
MX Pref |
TTL |
Active |
| 1 |
@ |
A |
1.2.3.4 |
- |
1800 |
Yes |
| 2 |
www |
CNAME |
example.com |
- |
1800 |
Yes |
| 3 |
@ |
MX |
mail.example.com |
10 |
1800 |
Yes |
/namecheap dns-set <domain> <action> [records...]
Manage DNS records for a domain.
Actions:
add — Add a record (merges with existing)
remove — Remove a record by index or match
replace — Replace all records with the provided set
reset — Reset to Namecheap default DNS
Steps for add:
- Export env vars from
~/.claude/settings.local.json (see Critical DNS Gotchas §4)
- Get existing records:
scripts/nc_api.sh dns-get "<sld>" "<tld>"
- Parse existing records into a list
- Ask user for new record details if not provided:
- Type (A, AAAA, CNAME, MX, TXT, URL, URL301, FRAME)
- Host (@ for root, www, subdomain name, * for wildcard)
- Value (IP address, target domain, TXT content, etc.)
- TTL (default: 1800)
- MX Priority (only for MX records, default: 10)
- Merge new record into existing list
- CRITICAL:
setHosts is destructive — it replaces ALL records. Always send the complete desired record set including all existing records.
- If any record contains special characters (+, /, =, spaces) in its value — especially TXT records (DKIM, SPF, DMARC) — use
curl --data-urlencode directly instead of the nc_api.sh script. See safe pattern below.
- If any MX records are present, include
EmailType=MX in the POST body (see Critical DNS Gotchas §2).
- Confirm success and display updated record table
Safe curl pattern for DNS with special characters:
curl -s -X POST "https://api.namecheap.com/xml.response" \
--data-urlencode "ApiUser=${NAMECHEAP_API_USER}" \
--data-urlencode "ApiKey=${NAMECHEAP_API_KEY}" \
--data-urlencode "UserName=${NAMECHEAP_USERNAME}" \
--data-urlencode "ClientIp=${NAMECHEAP_CLIENT_IP}" \
--data-urlencode "Command=namecheap.domains.dns.setHosts" \
--data-urlencode "SLD=example" \
--data-urlencode "TLD=com" \
--data-urlencode "EmailType=MX" \
--data-urlencode "HostName1=@" \
--data-urlencode "RecordType1=A" \
--data-urlencode "Address1=1.2.3.4" \
--data-urlencode "TTL1=1800" \
--data-urlencode "HostName2=resend._domainkey" \
--data-urlencode "RecordType2=TXT" \
--data-urlencode "Address2=p=MIGfMA0GCSqGSIb3DQEB..." \
--data-urlencode "TTL2=1800"
Steps for remove:
- Get and display existing records (numbered)
- Ask which record to remove (by number)
- Remove from list, send remaining records via
dns-set
Steps for reset:
- Confirm with user
- Call
scripts/nc_api.sh dns-default "<sld>" "<tld>"
/namecheap ns <domain> <action> [nameservers]
Manage nameservers.
Actions:
get — Show current nameservers
set — Set custom nameservers (comma-separated)
reset — Reset to Namecheap default nameservers
create — Create a personal/child nameserver (e.g., ns1.example.com -> IP)
Steps for set:
- Call
scripts/nc_api.sh ns-set "<sld>" "<tld>" "ns1.example.com,ns2.example.com"
- Warn: Custom nameservers disable URL forwarding, email forwarding, and dynamic DNS
Steps for create:
- Ask for nameserver hostname and IP
- Call
scripts/nc_api.sh ns-create "<sld>" "<tld>" "<nameserver>" "<ip>"
/namecheap renew <domain> [years]
Renew a domain registration.
Steps:
- Get domain info to check current expiry
- Check renewal pricing:
scripts/nc_api.sh pricing "<tld>" "RENEW"
- Display: "Renew example.com for N year(s) at $X.XX? Current expiry: YYYY-MM-DD"
- Ask for explicit confirmation before charging.
- Call
scripts/nc_api.sh renew "<domain>" "<years>"
- Display: new expiry, order ID, charged amount
/namecheap transfer <domain>
Transfer a domain to Namecheap.
Steps:
- Check transfer pricing:
scripts/nc_api.sh pricing "<tld>" "TRANSFER"
- Ask for the EPP/authorization code from the current registrar
- Display cost and confirm
- Call
scripts/nc_api.sh transfer "<domain>" "<years>" "<epp_code>"
- Display transfer ID and status
- Note: Transfer typically takes 5-7 days
/namecheap pricing <tld> [action]
Check pricing for a TLD.
Steps:
- Action defaults to
REGISTER. Options: REGISTER, RENEW, TRANSFER, REACTIVATE
- Call
scripts/nc_api.sh pricing "<tld>" "<action>"
- Display pricing table:
| Duration |
Regular Price |
Your Price |
Currency |
| 1 year |
$10.98 |
$8.88 |
USD |
| 2 years |
$21.96 |
$17.76 |
USD |
/namecheap email <domain> [action]
Manage email forwarding.
Actions:
get — Show current email forwarding rules
set — Set email forwarding (mailbox -> forward-to pairs)
Steps for set:
- Ask for mailbox name (e.g.,
info) and forward-to address
- Can set multiple rules at once
- Call
scripts/nc_api.sh email-set "<domain>" "<mailbox1>=<forward1>,<mailbox2>=<forward2>"
/namecheap balance
Check account balance.
Steps:
- Call
scripts/nc_api.sh balance
- Display: Available Balance, Account Balance, Earned Amount, Withdrawable Amount
Critical DNS Gotchas
These are hard-won lessons. Read before touching DNS records.
1. setHosts is DESTRUCTIVE
The setHosts API replaces ALL records on the domain. If you send 2 records, every other record is deleted. Always read existing records first (dns-get), then include them in the dns-set call alongside new records.
2. MX records silently dropped in EmailType=FWD mode
By default, Namecheap domains use EmailType=FWD (email forwarding). In this mode, MX records are silently dropped — the API returns IsSuccess="true" but the MX record is simply not created. To fix: include EmailType=MX in the setHosts POST body when any MX record is present. This disables Namecheap's email forwarding feature.
3. Special characters in TXT values break curl -d
DKIM keys, SPF records, and other TXT values often contain +, /, =, spaces, and ~. These are special in URL-encoded form data (+ becomes space, = delimits params). The nc_api.sh script uses plain curl -d which does NOT encode values.
For DNS operations with TXT/DKIM/SPF values, use curl --data-urlencode directly instead of going through the script. See the dns-set section for the safe pattern.
4. Env vars must be exported to the script's process
Some users put credentials in a Claude settings file or a vault. Those files don't
automatically export to a shell. Either source them into the shell before invoking
nc_api.sh, or rely on the ~/.config/claude-skills/namecheap.env file the --setup
flow creates.
Anti-patterns
- Registering or renewing a domain without explicit user confirmation and a price display.
- Calling
dns-set without first reading existing records. It is destructive — all
records not included in the call get deleted.
- Storing API keys in skill files or scripts. They belong in environment variables.
- Hammering the API. Batch domain checks. Add delays for bulk operations.
- Testing against production. Always sandbox-first.
- Guessing contact information. Ask the user or use a saved address.
Error handling
- If API returns
Status="ERROR", extract Error@Number and Error text
- Common errors:
2011150 — Missing required parameter
2030280 — Domain not available
2011170 — Invalid domain name
2016166 — Domain locked / cannot modify
4022288 — API access disabled
5050900 — Too many requests (rate limited)
- On rate limit: wait 60 seconds, then retry once
- On auth error: prompt user to verify credentials and IP whitelist
Known gotchas
setHosts is destructive — replaces ALL DNS records on the domain. Read existing
records first, then send the complete desired set.
- MX records silently dropped in
EmailType=FWD mode. API returns success but the
record is never created. Include EmailType=MX in the call when any MX is present.
- Special characters in TXT values break
curl -d. DKIM, SPF, and DMARC values
contain +, /, =, spaces. Use curl --data-urlencode for DNS writes.
- Production API requirements: 20+ domains, $50+ balance, or $50+ in 2-year
purchases. Sandbox is unrestricted.
Validated patterns
- Always check availability and price before registering. Display the total cost and
ask for explicit confirmation. The 30-second pause between check and register has
saved registrations more than once.
- Use the sandbox endpoint for the first run of any new DNS script. The XML API errors
in production are not always clear; the sandbox surfaces them faster.
Self-improvement
This skill ships with a lightweight feedback loop. Adopt or ignore — the skill works
without it.
Trigger a review when:
- The user explicitly disagrees with a DNS change (strongest signal — log immediately;
2–3 corrections on the same theme → promote to body).
- A new Namecheap API behavior surfaces (silent dropped records, new auth error code).
learnings.md crosses ~100 bullets (consolidation time).
- The skill mis-triggers or fails to trigger.
- Namecheap publishes a breaking API change.
Consolidation pass (5–10 min, weekly or threshold-driven):
- Each entry gets one fate: apply, capture, or dismiss.
- Apply = merge into Known gotchas / Anti-patterns / Validated patterns.
- Capture = leave in
learnings.md for now.
- Dismiss = delete.
- Bump
last-consolidated: in frontmatter.
1---2name: namecheap3description: Namecheap domain management via the Namecheap XML API. Check domain availability, register/transfer/renew domains, manage DNS records (A, AAAA, CNAME, MX, TXT, etc.), list domains, set custom nameservers, manage email forwarding, and check pricing. Use when the user says "namecheap", "check domain", "register domain", "DNS records", "nameservers", "domain transfer", "renew domain", or "domain pricing".4---56# Namecheap Domain Manager78Manage domains via the Namecheap XML API. All commands require credentials configured in environment variables.910## Setup & Authentication1112**Required environment variables.** Put them in a `.env` file, your shell rc, or13`~/.config/claude-skills/namecheap.env`. The bundled script will pick them up.1415| Variable | Description |16|---|---|17| `NAMECHEAP_API_USER` | Your Namecheap username |18| `NAMECHEAP_API_KEY` | API key from Profile → Tools → API Access |19| `NAMECHEAP_USERNAME` | Usually same as `NAMECHEAP_API_USER` |20| `NAMECHEAP_CLIENT_IP` | Your whitelisted IPv4 address |21| `NAMECHEAP_USE_SANDBOX` | Set to `true` for sandbox mode (default: `false`) |2223**First-time setup:** run `scripts/nc_api.sh --setup` to be prompted for each value and24have a `~/.config/claude-skills/namecheap.env` file written for you.2526**Get an API key:** sign in at namecheap.com, go to Profile → Tools → API Access, enable27API access, then create a key. The key is shown only once — copy it.2829**IP Whitelisting:** Namecheap requires the calling IP to be whitelisted. Only IPv4 is supported. The user must whitelist their IP at Profile > Tools > API Access > Whitelisted IPs.3031**Production API requirements** (at least one must be met):32- 20+ domains in the account33- $50+ account balance34- $50+ in purchases within the last 2 years3536Sandbox has no requirements — create a free account at `https://www.sandbox.namecheap.com/`.3738## API Base URLs3940| Environment | URL |41|---|---|42| Production | `https://api.namecheap.com/xml.response` |43| Sandbox | `https://api.sandbox.namecheap.com/xml.response` |4445## Rate Limits4647- **20 requests/minute**, 700/hour, 8,000/day48- Batch domain checks using comma-separated lists to conserve quota4950---5152## Subcommands5354### `/namecheap check <domain1> [domain2] [...]`5556Check domain availability.5758**Steps:**591. Validate credentials are set (run `scripts/nc_api.sh check-env`)602. Accept one or more domain names as arguments (comma or space separated)613. Call `scripts/nc_api.sh check "domain1.com,domain2.com"`624. Parse XML response — display results as a table:6364| Domain | Available | Premium | Price | ICANN Fee |65|---|---|---|---|---|66| example.com | No | - | - | - |67| example.net | Yes | No | - | $0.18 |68695. If any are available, ask if the user wants to register one7071---7273### `/namecheap search <keyword> [tlds]`7475Search for available domains across multiple TLDs.7677**Steps:**781. Take a keyword and optional TLD list (default: `com,net,org,io,co,dev,app,ai`)792. Generate domain combinations: `keyword.com`, `keyword.net`, etc.803. Call `scripts/nc_api.sh check "<comma-separated-list>"`814. Display availability table sorted by: available first, then by TLD preference825. Offer to check pricing for available domains8384---8586### `/namecheap register <domain> [years]`8788Register/purchase a new domain.8990**Steps:**911. Confirm domain is available first (call check if not already confirmed)922. Check pricing: `scripts/nc_api.sh pricing "com" "REGISTER"` (use appropriate TLD)933. Display price and ask for confirmation: "Register **example.com** for **N year(s)** at **$X.XX**?"944. Ask the user for contact information OR check if they have a default address configured95 - If user wants to use an existing address: `scripts/nc_api.sh get-address-list`96 - Let user pick an address or enter new contact details975. **CRITICAL: Always ask for explicit confirmation before purchasing.** Display the total cost.986. Call `scripts/nc_api.sh register "<domain>" "<years>" "<contact_params>"`997. Parse response — display: Domain, Order ID, Transaction ID, Charged Amount, WhoisGuard status1008. If `AddFreeWhoisguard=yes` and `WGEnabled=yes` were included, confirm privacy is active101102**Contact fields required** (for Registrant, Tech, Admin, AuxBilling — all four):103`FirstName, LastName, Address1, City, StateProvince, PostalCode, Country, Phone (+1.2125551234 format), EmailAddress`104105**Optional:** `OrganizationName, Address2`106107---108109### `/namecheap list [filter]`110111List domains in the account.112113**Steps:**1141. Call `scripts/nc_api.sh list "[filter]"` where filter can be: `all` (default), `expiring`, `expired`1152. Optional search term can be passed to filter by keyword1163. Parse XML — display as table:117118| Domain | Created | Expires | Auto-Renew | Locked | WhoisGuard | DNS |119|---|---|---|---|---|---|---|120| example.com | 2024-01-15 | 2025-01-15 | Yes | Yes | Enabled | Namecheap |1211224. Show paging info if more than one page of results123124---125126### `/namecheap info <domain>`127128Get detailed information about a domain.129130**Steps:**1311. Call `scripts/nc_api.sh info "<domain>"`1322. Parse and display:133 - Domain status, ID, owner134 - Created/Expires dates, years registered135 - WhoisGuard status and expiration136 - DNS provider, nameservers list137 - Host record count138 - Modification rights139140---141142### `/namecheap dns <domain>`143144Show current DNS records for a domain.145146**Steps:**1471. Split domain into SLD and TLD1482. Call `scripts/nc_api.sh dns-get "<sld>" "<tld>"`1493. Display records as table:150151| # | Name | Type | Address | MX Pref | TTL | Active |152|---|---|---|---|---|---|---|153| 1 | @ | A | 1.2.3.4 | - | 1800 | Yes |154| 2 | www | CNAME | example.com | - | 1800 | Yes |155| 3 | @ | MX | mail.example.com | 10 | 1800 | Yes |156157---158159### `/namecheap dns-set <domain> <action> [records...]`160161Manage DNS records for a domain.162163**Actions:**164- `add` — Add a record (merges with existing)165- `remove` — Remove a record by index or match166- `replace` — Replace all records with the provided set167- `reset` — Reset to Namecheap default DNS168169**Steps for `add`:**1701. Export env vars from `~/.claude/settings.local.json` (see Critical DNS Gotchas §4)1712. Get existing records: `scripts/nc_api.sh dns-get "<sld>" "<tld>"`1723. Parse existing records into a list1734. Ask user for new record details if not provided:174 - Type (A, AAAA, CNAME, MX, TXT, URL, URL301, FRAME)175 - Host (@ for root, www, subdomain name, * for wildcard)176 - Value (IP address, target domain, TXT content, etc.)177 - TTL (default: 1800)178 - MX Priority (only for MX records, default: 10)1795. Merge new record into existing list1806. **CRITICAL: `setHosts` is destructive — it replaces ALL records.** Always send the complete desired record set including all existing records.1817. **If any record contains special characters (+, /, =, spaces) in its value — especially TXT records (DKIM, SPF, DMARC) — use `curl --data-urlencode` directly** instead of the `nc_api.sh` script. See safe pattern below.1828. **If any MX records are present, include `EmailType=MX`** in the POST body (see Critical DNS Gotchas §2).1839. Confirm success and display updated record table184185**Safe curl pattern for DNS with special characters:**186```bash187curl -s -X POST "https://api.namecheap.com/xml.response" \188 --data-urlencode "ApiUser=${NAMECHEAP_API_USER}" \189 --data-urlencode "ApiKey=${NAMECHEAP_API_KEY}" \190 --data-urlencode "UserName=${NAMECHEAP_USERNAME}" \191 --data-urlencode "ClientIp=${NAMECHEAP_CLIENT_IP}" \192 --data-urlencode "Command=namecheap.domains.dns.setHosts" \193 --data-urlencode "SLD=example" \194 --data-urlencode "TLD=com" \195 --data-urlencode "EmailType=MX" \196 --data-urlencode "HostName1=@" \197 --data-urlencode "RecordType1=A" \198 --data-urlencode "Address1=1.2.3.4" \199 --data-urlencode "TTL1=1800" \200 --data-urlencode "HostName2=resend._domainkey" \201 --data-urlencode "RecordType2=TXT" \202 --data-urlencode "Address2=p=MIGfMA0GCSqGSIb3DQEB..." \203 --data-urlencode "TTL2=1800"204```205206**Steps for `remove`:**2071. Get and display existing records (numbered)2082. Ask which record to remove (by number)2093. Remove from list, send remaining records via `dns-set`210211**Steps for `reset`:**2121. Confirm with user2132. Call `scripts/nc_api.sh dns-default "<sld>" "<tld>"`214215---216217### `/namecheap ns <domain> <action> [nameservers]`218219Manage nameservers.220221**Actions:**222- `get` — Show current nameservers223- `set` — Set custom nameservers (comma-separated)224- `reset` — Reset to Namecheap default nameservers225- `create` — Create a personal/child nameserver (e.g., ns1.example.com -> IP)226227**Steps for `set`:**2281. Call `scripts/nc_api.sh ns-set "<sld>" "<tld>" "ns1.example.com,ns2.example.com"`2292. **Warn:** Custom nameservers disable URL forwarding, email forwarding, and dynamic DNS230231**Steps for `create`:**2321. Ask for nameserver hostname and IP2332. Call `scripts/nc_api.sh ns-create "<sld>" "<tld>" "<nameserver>" "<ip>"`234235---236237### `/namecheap renew <domain> [years]`238239Renew a domain registration.240241**Steps:**2421. Get domain info to check current expiry2432. Check renewal pricing: `scripts/nc_api.sh pricing "<tld>" "RENEW"`2443. Display: "Renew **example.com** for **N year(s)** at **$X.XX**? Current expiry: YYYY-MM-DD"2454. **Ask for explicit confirmation before charging.**2465. Call `scripts/nc_api.sh renew "<domain>" "<years>"`2476. Display: new expiry, order ID, charged amount248249---250251### `/namecheap transfer <domain>`252253Transfer a domain to Namecheap.254255**Steps:**2561. Check transfer pricing: `scripts/nc_api.sh pricing "<tld>" "TRANSFER"`2572. Ask for the EPP/authorization code from the current registrar2583. Display cost and confirm2594. Call `scripts/nc_api.sh transfer "<domain>" "<years>" "<epp_code>"`2605. Display transfer ID and status2616. Note: Transfer typically takes 5-7 days262263---264265### `/namecheap pricing <tld> [action]`266267Check pricing for a TLD.268269**Steps:**2701. Action defaults to `REGISTER`. Options: `REGISTER`, `RENEW`, `TRANSFER`, `REACTIVATE`2712. Call `scripts/nc_api.sh pricing "<tld>" "<action>"`2723. Display pricing table:273274| Duration | Regular Price | Your Price | Currency |275|---|---|---|---|276| 1 year | $10.98 | $8.88 | USD |277| 2 years | $21.96 | $17.76 | USD |278279---280281### `/namecheap email <domain> [action]`282283Manage email forwarding.284285**Actions:**286- `get` — Show current email forwarding rules287- `set` — Set email forwarding (mailbox -> forward-to pairs)288289**Steps for `set`:**2901. Ask for mailbox name (e.g., `info`) and forward-to address2912. Can set multiple rules at once2923. Call `scripts/nc_api.sh email-set "<domain>" "<mailbox1>=<forward1>,<mailbox2>=<forward2>"`293294---295296### `/namecheap balance`297298Check account balance.299300**Steps:**3011. Call `scripts/nc_api.sh balance`3022. Display: Available Balance, Account Balance, Earned Amount, Withdrawable Amount303304---305306## Critical DNS Gotchas307308These are hard-won lessons. Read before touching DNS records.309310### 1. `setHosts` is DESTRUCTIVE311The `setHosts` API **replaces ALL records** on the domain. If you send 2 records, every other record is deleted. **Always** read existing records first (`dns-get`), then include them in the `dns-set` call alongside new records.312313### 2. MX records silently dropped in EmailType=FWD mode314By default, Namecheap domains use `EmailType=FWD` (email forwarding). In this mode, **MX records are silently dropped** — the API returns `IsSuccess="true"` but the MX record is simply not created. To fix: include `EmailType=MX` in the setHosts POST body when any MX record is present. This disables Namecheap's email forwarding feature.315316### 3. Special characters in TXT values break `curl -d`317DKIM keys, SPF records, and other TXT values often contain `+`, `/`, `=`, spaces, and `~`. These are special in URL-encoded form data (`+` becomes space, `=` delimits params). The `nc_api.sh` script uses plain `curl -d` which does NOT encode values.318319**For DNS operations with TXT/DKIM/SPF values, use `curl --data-urlencode` directly** instead of going through the script. See the dns-set section for the safe pattern.320321### 4. Env vars must be exported to the script's process322Some users put credentials in a Claude settings file or a vault. Those files don't323automatically export to a shell. Either source them into the shell before invoking324`nc_api.sh`, or rely on the `~/.config/claude-skills/namecheap.env` file the `--setup`325flow creates.326327## Anti-patterns328329- Registering or renewing a domain without explicit user confirmation and a price display.330- Calling `dns-set` without first reading existing records. It is destructive — all331 records not included in the call get deleted.332- Storing API keys in skill files or scripts. They belong in environment variables.333- Hammering the API. Batch domain checks. Add delays for bulk operations.334- Testing against production. Always sandbox-first.335- Guessing contact information. Ask the user or use a saved address.336337## Error handling338339- If API returns `Status="ERROR"`, extract `Error@Number` and `Error` text340- Common errors:341 - `2011150` — Missing required parameter342 - `2030280` — Domain not available343 - `2011170` — Invalid domain name344 - `2016166` — Domain locked / cannot modify345 - `4022288` — API access disabled346 - `5050900` — Too many requests (rate limited)347- On rate limit: wait 60 seconds, then retry once348- On auth error: prompt user to verify credentials and IP whitelist349350## Known gotchas351352- **`setHosts` is destructive** — replaces ALL DNS records on the domain. Read existing353 records first, then send the complete desired set.354- **MX records silently dropped in `EmailType=FWD` mode.** API returns success but the355 record is never created. Include `EmailType=MX` in the call when any MX is present.356- **Special characters in TXT values break `curl -d`.** DKIM, SPF, and DMARC values357 contain `+`, `/`, `=`, spaces. Use `curl --data-urlencode` for DNS writes.358- **Production API requirements:** 20+ domains, $50+ balance, or $50+ in 2-year359 purchases. Sandbox is unrestricted.360361## Validated patterns362363- Always check availability and price *before* registering. Display the total cost and364 ask for explicit confirmation. The 30-second pause between check and register has365 saved registrations more than once.366- Use the sandbox endpoint for the first run of any new DNS script. The XML API errors367 in production are not always clear; the sandbox surfaces them faster.368369## Self-improvement370371This skill ships with a lightweight feedback loop. Adopt or ignore — the skill works372without it.373374Trigger a review when:375376- The user explicitly disagrees with a DNS change (strongest signal — log immediately;377 2–3 corrections on the same theme → promote to body).378- A new Namecheap API behavior surfaces (silent dropped records, new auth error code).379- `learnings.md` crosses ~100 bullets (consolidation time).380- The skill mis-triggers or fails to trigger.381- Namecheap publishes a breaking API change.382383Consolidation pass (5–10 min, weekly or threshold-driven):384385- Each entry gets one fate: apply, capture, or dismiss.386- Apply = merge into Known gotchas / Anti-patterns / Validated patterns.387- Capture = leave in `learnings.md` for now.388- Dismiss = delete.389- Bump `last-consolidated:` in frontmatter.