Comprehensive guide for AI agents working on the DDNS (Dynamic DNS) project
DDNS is a Python-based Dynamic DNS client that automatically updates DNS records to match the current IP address. It supports:
DDNS/
├── .github/ # GitHub configuration
│ ├── workflows/ # CI/CD workflows (build, publish, test)
│ ├── instructions/ # Agent instructions (python.instructions.md)
│ └── copilot-instructions.md # GitHub Copilot instructions
│
├── ddns/ # Main application code
│ ├── __init__.py # Package initialization and version info
│ ├── __main__.py # Entry point for module execution
│ ├── cache.py # Cache management
│ ├── ip.py # IP address detection logic
│ │
│ ├── config/ # Configuration management
│ │ ├── __init__.py
│ │ ├── cli.py # Command-line argument parsing
│ │ ├── config.py # Configuration loading and merging
│ │ ├── env.py # Environment variable parsing
│ │ └── file.py # JSON file configuration
│ │
│ ├── provider/ # DNS provider implementations
│ │ ├── __init__.py # Provider registry
│ │ ├── _base.py # Abstract base classes (SimpleProvider, BaseProvider)
│ │ ├── _signature.py # HMAC signature utilities
│ │ ├── alidns.py # Alibaba Cloud DNS
│ │ ├── aliesa.py # Alibaba Cloud ESA
│ │ ├── callback.py # Custom webhook callbacks
│ │ ├── cloudflare.py # Cloudflare DNS
│ │ ├── debug.py # Debug provider
│ │ ├── dnscom.py # DNS.COM
│ │ ├── dnspod.py # DNSPod (China)
│ │ ├── dnspod_com.py # DNSPod International
│ │ ├── edgeone.py # Tencent EdgeOne
│ │ ├── edgeone_dns.py # Tencent EdgeOne DNS
│ │ ├── he.py # Hurricane Electric
│ │ ├── huaweidns.py # Huawei Cloud DNS
│ │ ├── namesilo.py # NameSilo
│ │ ├── noip.py # No-IP
│ │ └── tencentcloud.py # Tencent Cloud DNS
│ │
│ ├── scheduler/ # Task scheduling implementations
│ │ ├── __init__.py
│ │ ├── _base.py # Base scheduler class
│ │ ├── cron.py # Cron-based scheduler (Linux/macOS)
│ │ ├── launchd.py # macOS launchd scheduler
│ │ ├── schtasks.py # Windows Task Scheduler
│ │ └── systemd.py # Linux systemd timer
│ │
│ └── util/ # Utility modules
│ ├── __init__.py
│ ├── comment.py # Comment handling
│ ├── fileio.py # File I/O operations
│ ├── http.py # HTTP client with proxy support
│ └── try_run.py # Safe command execution
│
├── tests/ # Unit tests
│ ├── __init__.py # Test initialization (path setup)
│ ├── base_test.py # Shared test utilities and base classes
│ ├── README.md # Testing documentation
│ ├── config/ # Test configuration files
│ ├── scripts/ # Test helper scripts
│ ├── test_cache.py # Cache tests
│ ├── test_config_*.py # Configuration tests
│ ├── test_ip.py # IP detection tests
│ ├── test_provider_*.py # Provider-specific tests
│ ├── test_scheduler_*.py # Scheduler tests
│ └── test_util_*.py # Utility tests
│
├── doc/ # Documentation
│ ├── config/ # Configuration documentation
│ │ ├── cli.md # CLI usage (Chinese)
│ │ ├── cli.en.md # CLI usage (English)
│ │ ├── env.md # Environment variables (Chinese)
│ │ ├── env.en.md # Environment variables (English)
│ │ ├── json.md # JSON config (Chinese)
│ │ └── json.en.md # JSON config (English)
│ │
│ ├── dev/ # Developer documentation
│ │ ├── provider.md # Provider development guide (Chinese)
│ │ ├── provider.en.md # Provider development guide (English)
│ │ ├── config.md # Config system (Chinese)
│ │ └── config.en.md # Config system (English)
│ │
│ ├── providers/ # Provider-specific documentation
│ │ ├── README.md # Provider list (Chinese)
│ │ ├── README.en.md # Provider list (English)
│ │ ├── alidns.md # AliDNS guide (Chinese)
│ │ ├── alidns.en.md # AliDNS guide (English)
│ │ └── ... # Other providers (Chinese & English versions)
│ │
│ ├── docker.md # Docker documentation (Chinese)
│ ├── docker.en.md # Docker documentation (English)
│ ├── install.md # Installation guide (Chinese)
│ ├── install.en.md # Installation guide (English)
│ └── img/ # Images and diagrams
│
├── docker/ # Docker configuration
│ ├── Dockerfile # Main Dockerfile
│ ├── glibc.Dockerfile # glibc-based build
│ ├── musl.Dockerfile # musl-based build
│ └── entrypoint.sh # Container entrypoint script
│
├── schema/ # JSON schemas
│ ├── v2.json # Legacy schema v2
│ ├── v2.8.json # Legacy schema v2.8
│ ├── v4.0.json # Previous schema v4.0
│ └── v4.1.json # Latest schema v4.1
│
├── run.py # Direct run script
├── install.sh # One-click install script
├── pyproject.toml # Python project configuration
├── setup.cfg # Setup configuration
├── .gitignore # Git ignore rules
├── LICENSE # MIT License
├── README.md # Main README (Chinese)
└── README.en.md # Main README (English)
ddns/__main__.py
├── ddns.config.* # Configuration loading
│ ├── cli # Command-line parsing
│ ├── env # Environment variables
│ ├── file # JSON file loading
│ └── config # Config merging and validation
│
├── ddns.ip # IP address detection
│ └── ddns.util.http # HTTP client for public IP APIs
│
├── ddns.provider.* # DNS provider implementations
│ ├── _base # Base classes (SimpleProvider, BaseProvider)
│ ├── _signature # HMAC signature for cloud APIs
│ └── ddns.util.http # HTTP client for API requests
│
├── ddns.cache # Caching to reduce API calls
│ └── ddns.util.fileio # File operations
│
└── ddns.scheduler.* # Task scheduling
└── ddns.util.try_run # Safe command execution
BaseProvider: Full CRUD DNS provider (query, create, update records)
SimpleProvider: Simple update-only DNS provider
Three-layer priority system:
ddns.config.cliddns.config.fileddns.config.envMultiple methods supported (via ddns.ip):
Platform-specific implementations:
From Source (Python 2.7+/3.6+)
git clone https://github.com/NewFuture/DDNS.git
cd DDNS
python -m ddns --help
PyPI
pip install ddns
ddns --help
Docker
docker pull newfuture/ddns:latest
docker run --rm newfuture/ddns:latest --help
Binary (no Python required)
curl -fsSL https://ddns.newfuture.cc/install.sh | sh
ddns --help
# Run with config file
python -m ddns -c config.json
# Run with command-line args
python -m ddns --dns=cloudflare --id=EMAIL --token=TOKEN --ipv4=domain.com
# Enable debug mode
python -m ddns --debug
Linux/macOS/Raspberry Pi: Set up scheduled task
ddns task --install 5 # Update every 5 minutes
ddns task --enable
# Uses systemd/cron on Linux, launchd on macOS
Windows: Download binary from releases, then ddns task --install 5
CRITICAL: Follow .github/instructions/python.instructions.md
# type: (...) -> ReturnTyperuff check --fix --unsafe-fixes . && ruff format .# Entry point
cat ddns/__main__.py
# Providers
ls ddns/provider/
cat ddns/provider/_base.py
# Find code
find ddns/provider -name "*.py" -not -name "_*"
grep -r "def set_record" ddns/provider/
ddns/provider/myprovider.py inheriting from BaseProvider or SimpleProviderdoc/dev/provider.md)ddns/provider/__init__.pytests/test_provider_myprovider.pydoc/providers/myprovider.md and doc/providers/myprovider.en.mdTemplate:
from ._base import BaseProvider
class MyProvider(BaseProvider):
API = 'https://api.provider.com'
def _query_zone_id(self, domain):
# type: (str) -> str | None
pass
def _query_record(self, zone_id, subdomain, main_domain, record_type, line, extra):
# type: (str, str, str, str, str | None, dict | None) -> dict | None
pass
def _create_record(self, zone_id, subdomain, main_domain, value, record_type, ttl, line, extra):
# type: (str, str, str, str, str, int | None, str | None, dict | None) -> bool
pass
def _update_record(self, zone_id, old_record, value, record_type, ttl, line, extra):
# type: (str, dict, str, str, int | None, str | None, dict | None) -> bool
pass
Bilingual: Always update both Chinese (.md) and English (.en.md) versions
Structure: Keep same headings, code examples identical, translate only text
Links: Link to Chinese versions in Chinese docs, English in English docs
Format: <type>(<scope>): <description>
Types: feat, fix, docs, test, refactor, perf, chore, ci
Examples:
feat(provider.cloudflare): add IPv6 support
fix(util.http): handle proxy authentication errors
docs(providers): update provider documentation
pip install ruff pytestcopilot/feature-name or copilot/issue-descriptionpython3 -m unittest discover tests -vruff check --fix --unsafe-fixes . && ruff format .unittest (recommended - no dependencies)
python -m unittest discover tests -v
python -m unittest tests.test_provider_cloudflare -v
pytest (optional)
pip install pytest
pytest tests/ -v
from base_test import BaseProviderTestCase, patch, MagicMock
from ddns.provider.myprovider import MyProvider
class TestMyProvider(BaseProviderTestCase):
def setUp(self):
super(TestMyProvider, self).setUp()
self.provider = MyProvider(self.id, self.token)
@patch.object(MyProvider, "_http")
def test_query_zone_id_success(self, mock_http):
mock_http.return_value = {"zone_id": "zone123"}
result = self.provider._query_zone_id("example.com")
self.assertEqual(result, "zone123")
# Syntax
python3 -m py_compile ddns/provider/mynewprovider.py
ruff check .
# Tests
python3 -m unittest discover tests -v
# Config
python3 -c "import json; json.load(open('config.json'))"
# Provider
python3 -m ddns --dns=debug --ipv4=test.com --debug
ruff check .Import Error: Check file exists, provider registered in __init__.py, PYTHONPATH set
Syntax Error: Check Python 2.7 compatibility (no f-strings, async/await, use type comments)
Test Failure: Verify mock setup returns correct values, check mock_http.call_args
Linting Error: Run ruff check --fix --unsafe-fixes . && ruff format .
python -m ddns --debug --dns=myprovider --ipv4=test.com
python -m ddns --debug --log_file=debug.log
Common Issues:
--debug, test API manuallyrm -f /tmp/ddns.cache), check IP detection--proxy=DIRECT or --ssl=false.format() not f-strings, type comments not annotationsgit revert HEAD # Revert last commit
git checkout -- file.py # Undo uncommitted changes
git checkout HEAD -- deleted_file # Restore deleted file
Don't:
Do:
Before refactoring: Is this broken or just different style? Will this break users? Is there test coverage?
Request confirmation before:
Explain what, why, impacts, and alternatives.
This guide provides comprehensive instructions for AI agents working on the DDNS project. Key points:
For detailed information on specific topics, refer to:
.github/instructions/python.instructions.md.github/copilot-instructions.mddoc/dev/provider.mdtests/README.mddoc/config/*.mdVersion: 1.0.1
Last Updated: 2025-11-29
Maintained by: DDNS Project Contributors