AGENTS¶
Guidance for AI coding agents and automation contributors working in this repository.
Scope¶
- Keep changes small, targeted, and testable.
- Do not refactor unrelated areas in the same change.
- Prefer extending existing modules/patterns over introducing new abstractions.
Commit Expectations¶
- Use scoped commit subjects consistent with repository history, for example
dtx: Fix queue shutdown on Python 3.12. - Keep a behavior change and its corresponding tests in the same commit.
- Split unrelated documentation or contributor-guidance changes into their own commits.
Project Conventions¶
- Python: 3.9+. No
X | Yunion syntax in annotations evaluated at runtime (useOptional/Union); builtin generics (list[str],dict[str, int]) are fine. - The repository must stay pyright-clean:
pyright --venvpath .(pinned to 1.1.411 in CI) must report 0 errors after any change. Suppressions must be rule-specific (# pyright: ignore[ruleName]) and reserved for inherently dynamic APIs. - CLI commands are Typer-based and typically use dependency injection via
ServiceProviderDepfrompymobiledevice3/cli/cli_common.py. - Async CLI handlers should use
@async_command. - Device-facing logic should live in
pymobiledevice3/services/*, not directly in CLI handlers. - Use async context managers (
async with) for long-lived service connections.
Where To Add Things¶
- New CLI command in existing group:
- Update or add function in
pymobiledevice3/cli/<group>.py. - New top-level CLI group:
- Add module under
pymobiledevice3/cli/. - Register group in
CLI_GROUPSinpymobiledevice3/__main__.py. - New protocol/service integration:
- Add service wrapper under
pymobiledevice3/services/(usually subclassingLockdownService). - DVT-related functionality:
- Use
DtxServiceProvider/DvtProviderpatterns inpymobiledevice3/services/dvt/.
Running Developer Commands Against Devices¶
- Developer/DVT commands on iOS 17+ devices require an RSD tunnel. Prefer
--userspaceover atunneldtunnel: it establishes the tunnel in-process with a pure-Python userspace network stack and needs nosudo/root, so agents can run unattended. - Example:
pymobiledevice3 developer dvt oslog --userspace. - You can also set
PYMOBILEDEVICE3_USERSPACE=1instead of passing the flag. - Only fall back to a privileged
tunneld(which needs root) when--userspaceis not viable — e.g. when you need higher host->device throughput, since userspace host->device transfers (DDI mounts, file pushes) are deliberately slower. --userspaceis mutually exclusive with--rsd/--tunnel.
Testing Expectations¶
- Add or update tests when behavior changes.
- Prefer tests that exercise real physical devices over monkeypatched or fully mocked coverage when the behavior depends on device interaction.
- Reuse fixtures from
tests/conftest.py, especiallyservice_provider. - Run at least targeted tests for touched areas; run full
pytestwhen practical. - Verify relevant linting for touched files when practical.
Skills¶
Repo-local agent skills (SKILL.md + optional references/) are discoverable by both
Claude Code and Codex: .claude/skills/ and .codex/skills/ mirror each other via
relative symlinks. Each skill has exactly one canonical directory — the other tree holds
a symlink to it — so edit the canonical files only:
.codex/skills/pymobiledevice3-device-operator/— operate a connected device through the local checkout (task routing, transport selection, safety gates)..codex/skills/tss-batch-prefetch/— maintainPREFETCHABLE_UPDATERSinpymobiledevice3/restore/tss.py..claude/skills/release/— cut a GitHub release (which publishes to PyPI).
When adding a skill, create it in one tree and symlink it from the other. When changing user-facing CLI layout, transports, or safety-relevant behavior, review whether the device-operator skill guidance needs updating.
The device-operator skill is also published as a Claude Code plugin: the repo is a
plugin marketplace (.claude-plugin/marketplace.json) whose plugin package at
misc/claude-plugin/ ships a vendored real copy of the skill (symlinks get
flattened by ZIP-based consumers such as plugin review pipelines). The canonical files
remain the single source of truth: after editing them, the sync-claude-plugin-skill
pre-commit hook refreshes the copy (misc/claude-plugin/sync_skill.py), and CI blocks
out-of-sync merges.
Documentation Expectations¶
- Update docs for user-facing command/API changes.
- Keep root
README.mdconcise; place deep guides underdocs/guides/. - Add new guides to the
navsection ofmkdocs.yml.
Safety¶
- Avoid destructive actions (for example wiping/restoring devices) unless explicitly requested.
- Do not commit secrets, pair records, or device-identifying artifacts.