Let an AI coding assistant work on your local Git repository through verified ZIP bundles.
PatchHarbor connects an assistant running elsewhere with a repository on your Linux or Windows machine. Send the assistant a repository snapshot as a Result Bundle; receive a Task Bundle containing code changes and an entrypoint. PatchHarbor checks the bundle against the intended repository state, executes it locally, and returns updated files and execution logs for the next iteration.
Use it when your coding assistant cannot access the repository directly, or when you want an explicit, reviewable handoff between development and execution. The entrypoint defines the project's tests, commits and optional push.
Install · Quick start · Monitor · Python API
- Export: Run
patchharbor bundleto capture the repository in a Result Bundle. - Develop: Give that bundle to the assistant so it can inspect the actual files and prepare changes.
- Transfer: Pack a Task Bundle bound to that Result and place the verified ZIP in the local Exchange directory.
- Execute: Run
patchharbor execute, or let the watcher validate the bundle, write its payloads and run its entrypoint. - Review: Read the new Result Bundle and execution log before starting the next iteration.
- Verified handoffs:
pack,inspectandvalidatecheck package integrity and repository binding before execution. - Useful feedback: Result Bundles contain repository snapshots, changes and execution diagnostics.
- Manual or watched execution: Use filesystem notifications or explicit polling for CIFS and other mounts without reliable notifications.
- Live visibility:
patchharbor monitordisplays repository and Exchange activity, a five-line event history, active entrypoints and bundle numbers in a read-only terminal UI. - Portable runtime: Results normally include a Core-PYZ that compatible Python environments can use without installing PatchHarbor. The watcher comes with the full installation.
- Python integration: The public API supports verified snapshot reading, bundle creation and guarded execution for host applications.
This checkout contains the unpublished 2.0.0 release candidate. The release badge links to the latest published GitHub release; it is not a test-status badge for this checkout. See the 2.0 integration guide before upgrading: Task and Result formats and the Python API have changed.
PatchHarbor requires CPython 3.10+. Official builds provide a wheel, sdist and Core-PYZ, with a runtime manifest and checksums for complete releases. See runtime export and the release procedure. The specialized safe reference export supports Linux x86-64 with CPython 3.10–3.14.
This development source requires Python 3.10 or newer. Repository operations also require Git;
executing a patch requires its declared Bash or PowerShell interpreter.
Static pack, inspect, reference-based validate and the public snapshot
reader need neither Git nor the target shell. The Core has no third-party runtime dependencies.
For the normal CLI and watcher, install a reviewed wheel or source checkout. For example, with an existing Python 3.10+ and pipx:
pipx install --python python3 /absolute/path/patchharbor-VERSION-py3-none-any.whl
patchharbor --version
patchharbor --helpThe wheel path is an artifact you obtain and verify; this command does not assume that any version has been published on a package index. pipx is optional: a dedicated virtual environment is another installation route. Wheel and sdist remain supported for normal installations; the PYZ replaces the runtime embedded in new Results, not the installed watcher. See installation and safe updates, especially if a watcher is already running. Updating repository files alone does not upgrade it.
Use a local Git repository with an existing committed HEAD. Choose an Exchange
directory outside every registered repository. In a POSIX shell:
cd /absolute/path/to/repository
patchharbor register
patchharbor configure exchange-directory /absolute/path/to/exchange
patchharbor configure show
patchharbor bundleRegistration is needed once per local repository instance. Settings belong to
.patchharbor/config.json in that instance; there is no global Exchange fallback.
An existing registered repository with valid settings can start at bundle.
See repository setup for clones, moves, shared
Exchanges, old configuration migration and automatic archival.
-
Give the resulting ZIP to the developer or chat. Its
CHAT_INSTRUCTIONS.md,context.jsonandenvironment.jsoncontain the handoff and full binding. -
Develop and test from that actual state. Prepare the payload files and an entrypoint, then use
packas below. A bundle may have zero commits for diagnosis, one commit, or several genuine sequential commit states. -
Inspect the finished patch and publish exactly one complete ZIP in Exchange.
-
Let the existing watcher process it, or, in manual mode, run:
patchharbor execute --dry-run patchharbor execute
-
Read the new Result and execution log. A Dry Run checks the package; it does not prove a successful actual Execute. A failed Execute may leave changed files or completed commits, which become the basis of the next patch.
The entrypoint defines the target project's tests, commits and optional push. The watcher does not invent that policy. Do not run a second watcher or another Execute orchestrator for the same repositories.
Prepare an explicit contents directory containing only the desired payloads and the entrypoint. The output directory must already exist outside that contents tree. For example:
patchharbor pack /work/contents --reference-bundle /work/result.zip \
--entrypoint run.sh --output-dir /work/ready --json
patchharbor inspect /work/ready/NAME.zip --json
patchharbor validate /work/ready/NAME.zip \
--reference-bundle /work/result.zip --jsonReplace NAME.zip with the path returned by pack. Windows targets may use a
PowerShell entrypoint such as run.ps1. The entrypoint must satisfy the existing
Bash/PowerShell marker contract; pack neither writes nor executes it.
Pack copies all permitted files in the chosen directory; it does not use
.gitignore to select a diff. Ordinary payloads are written into the repository
before the entrypoint runs. A diff is a payload that the entrypoint must
explicitly execute. task.json and PATCHHARBOR_META are generated/reserved.
Pack validates the final ZIP and its complete Result binding, but does not prove
shell syntax, target tests, replay eligibility or a future Execute.
The same operation is available to Python callers:
from patchharbor import api
packed = api.pack_task(
"/work/contents",
reference_bundle="/work/result.zip",
entrypoint="run.sh",
output_directory="/work/ready",
)
print(packed.path, packed.package_sha256)See the pack contract, working examples
and public Python API. A normal import uses the calling
interpreter's installation; an isolated CLI installation is not automatically
visible to a different Python environment. The verified PYZ bootstrap also
provides import_api(prepared) for API use without installing PatchHarbor.
New Results use format 4, Task Bundles use format 2, and Execute JSON
uses version 2. When runtime embedding succeeds, a Result contains exactly
one runtime/patchharbor-<version>.pyz with runtime metadata format 3. A valid
unavailable status contains metadata and a reason, without executable bytes.
Version 2 rejects old Patch/Result formats and removed Python API names.
Generate a fresh Result from the actual repository after a deliberate upgrade;
do not relabel an old archive. apply remains a deprecated CLI alias for
execute. The independent ScriptBundle / api.run_scripts and fs run path
is deprecated and has no repository-state binding. See the
protocol and integration upgrade.
Use the executable bootstrap from the trusted Result's handoff, or a separately
reviewed copy of scripts/pyz_bootstrap.py, to assess and prepare its exact PYZ.
After source trust and integrity checks, Python 3.10+ can run it directly:
python -I -S -B /private/runtime/patchharbor-VERSION.pyz inspect /work/patch.zip --json
python -I -S -B /private/runtime/patchharbor-VERSION.pyz validate /work/patch.zip \
--reference-bundle /work/result.zip --json
python -I -S -B /private/runtime/patchharbor-VERSION.pyz pack /work/contents \
--reference-bundle /work/result.zip --entrypoint run.sh --output-dir /work/readyUse the actual prepared path/version, not an arbitrary neighboring archive. This requires no pip, venv, network or host installation. The PYZ contains Core operations, no watcher or service installer. Git/execute operations still have their normal repository and interpreter requirements.
If the runtime is absent or technically unusable, use the documented previous handoff procedure with trusted compatible tools and record the reason. A semantic validation failure or invalid binding remains an error; fallback is not a bypass. The bootstrap guide covers trust, extraction, Python-only API use and the safe runtime-unavailable fallback. Its old wheel procedure is retained as historical documentation.
Manual patchharbor execute selects an eligible patch only for the registered
repository containing the current working directory. An explicit path,
patchharbor execute /path/to/patch.zip, selects the repository from its manifest
and still checks the full binding. --output-dir changes only the Result
destination. See selection, retries and recovery.
The watcher observes all configured Exchanges of registered repositories;
its working directory is not a repository filter. It has no Exchange argument.
Linux uses inotify and Windows uses ReadDirectoryChangesW. Start it in the
foreground with patchharbor-watcher, or install the optional Linux user unit:
patchharbor-watcher --install-systemd-user-unit
systemctl --user daemon-reload
systemctl --user enable --now patchharbor-watcher.serviceEach Exchange root is scanned after five seconds without a relevant change.
Existing files receive an initial quiet period on startup. Reads and changes
inside existing subdirectories do not trigger scans. There is no idle
one-second polling in event mode; its old bare --poll-interval option remains invalid. Results may trigger a scan
but are never executed as patches. Repeated identical no_candidate messages
are suppressed. Failed unchanged packages are not automatically retried.
Native event delivery on network/virtual filesystems depends on that filesystem; select polling explicitly for CIFS or other mounts without reliable notifications:
patchharbor watcher poll # default: 4 seconds
patchharbor watcher poll --interval 10 # custom interval, in seconds
patchharbor watcher poll --interval 0.5 # fractions are supportedThe equivalent standalone command is patchharbor-watcher poll. Polling checks
immediately, then waits the configured interval after each completed check or
Execute. It refreshes registered Exchanges every cycle, runs one worker at a time,
and retains Core's binding, integrity, locking and replay checks. Stop it with
Ctrl+C. The monitor shows polling mode, interval and the next planned scan.
Use one watcher mode for a deployment; stop an existing watcher after its active
Execute finishes before switching. Polling needs the full wheel/source installation;
the Core-PYZ still excludes the watcher. There is no silent polling fallback.
See watcher behavior.
Termux/Android should use manual Execute; a reliable Android background service
is not part of the supported watcher contract. Windows supports the foreground
watcher; the systemd unit is Linux-specific.
Five seconds of quiet is not proof that a download finished. Build and validate the ZIP outside the watched root. If copying across filesystems, copy into a staging subdirectory on the Exchange filesystem, finish and verify that copy, then publish it with a same-filesystem atomic operation without overwriting an existing file. An ordinary cross-filesystem move can become a partial copy.
pack performs its own exclusive, verified publication into an explicitly
chosen output directory. If its safe filesystem primitives are unsupported,
it fails instead of falling back to an unsafe copy. Choose one canonical final
ZIP and preserve its bytes and full SHA-256 during handoff.
Result names follow <Repository>_Result_Bundle_<HHMMSS>_<MMDD>_<ID6>.zip; patch names
follow <Repository>_Task_Bundle_<HHMMSS>_<MMDD>_<ID6>.zip (UTC). Filenames are not
repository-binding evidence. To use a transport suffix such as .zip.txt:
patchharbor configure bundle-suffix .txt
patchharbor configure bundle-suffix --clearThese are alternative settings, applied from the registered repository. The
bundle_suffix is naming metadata in a fresh Result's context.json, not a field
in task.json. Content remains ZIP. Old and new names may coexist.
Results contain a full base snapshot without Git history, staged/unstaged
deltas and non-ignored untracked regular files. .git, local .patchharbor
metadata and ignored untracked files are excluded. Review Results before sharing:
there is no general secret detector.
| Resource | Limit |
|---|---|
| Stored repository files in one Result (base + untracked) | 250,000 |
| Outer ZIP entries, including auxiliary data | 250,010 |
| Input ZIP and each expanded outer member | 256 MiB each |
| Total expanded content, including inspected inner runtime content | 512 MiB |
| Pack contents scan (files and directories) | 10,000 nodes |
| Inner runtime archive | 1,000 entries; separate artifact/profile byte limits |
These limits execute together: 250,000 files does not allow unlimited total bytes. Outer Result ZIP64 is supported. The larger outer limit does not enlarge pack's scan budget or the runtime archive budget. See pack limits and runtime limits.
For a failed Execute, inspect logs/run.json and logs/execution.log when present.
If Result creation itself fails, preserve the reported emergency diagnostics
directory. An entrypoint may already have committed or pushed: missing Result
does not mean rollback. Check the actual repository and logs before retrying;
after fixing the publication problem, patchharbor bundle captures its current
state. See error codes and recovery, including
Linux-to-Windows CIFS publication.
PatchHarbor is not a sandbox. Entrypoints run with the current user's rights. Hashes, repository ID, base commit and fingerprint check integrity and state; they do not authenticate the package's author. Execute only trusted packages. Payload replacement is atomic per file, not a package transaction: earlier successful writes are not automatically rolled back.
PatchHarbor does not run target-project tests or create Git commits as an
independent Core policy. An authorized entrypoint can run tests, make zero or
several commits, and push according to that project's workflow. Static checks
and successful pack creation do not establish those execution results.
The explicit legacy patchharbor fs run script runner remains available; it
does not replace repository-bound Execute.
- Installation and updates
- Repository configuration, archives, retries and permissions
- Troubleshooting
- Pack, examples, Python API
- Runtime bootstrap, Task / Execute / Result protocol
- Monitor, watcher, CIFS publication
- 2.0 integration and upgrade, release procedure
- Development tests and manual CI policy
- Joint requirements: main specification, PYZ/PACK extension and CPython extension
- Implementation and acceptance record
For development, install .[dev] in a dedicated environment and run only a
change-focused parallel selection, for example
python tools/run_tests.py -- tests/test_runtime_pyz.py. Document the selection
and its results. Execute runs the full parallel suite before every commit with
python tools/run_tests.py --suite all, including the final commit of a bundle.
GitHub CI is manual and started only by the project owner. Local tests
do not substitute for native Windows acceptance or release publication.
For available options, use patchharbor --help, patchharbor COMMAND --help
and patchharbor-watcher --help.
Current 1.6.0 integration plan, behavior matrix and delivery record separate prepared source, actual Execute and external acceptance.
patchharbor runtime export --output-dir /absolute/existing/output --json
python -I -S -B patchharbor-VERSION.pyz runtime export --output-dir /another/existing/output --jsonThis exports the running distribution's canonical PYZ without Git, a Result,
registration, network or build tools. It never replaces an existing file.
Unprepared source/editable trees report unavailable; build with
python scripts/build_release.py --outdir dist and install the wheel normally.
The public Python API is api.export_runtime(output_directory).
Every release from 1.8.0 requires PYZ, wheel, built sdist, runtime-manifest.json
and SHA256SUMS. Version strings alone are not a publication or platform proof.
See the release plan and main spec §44.
The read-only Monitor observes registered repositories and Exchanges; run patchharbor monitor.
Start collection explicitly from a development checkout with the development dependencies installed:
python tools/profile_tests.py run --modes baseline -- tests/test_selected.py
python tools/profile_tests.py report --phase setup --format markdown
python tools/profile_tests.py report --phase call --format markdown
python tools/profile_tests.py report --phase teardown --format markdownReplace the selection with your actual test path or node ID. Worker selection
defaults to auto. Add cprofile, memory or Linux-only strace to --modes
only when you want that diagnostic overhead. The SQLite history and raw data
stay local under build/test-profile/; --database selects another local path.
No collector runs on import, during a normal user command, or in a separate
CI profiling job. Reports distinguish preparation, test body, cleanup,
measurement modes and unknown coverage. See test diagnostics.