# .packageshift format A `.packageshift` file contains one instruction per line. Blank lines and lines beginning with `#` are ignored. When `package zip` finds the configured `shiftFile`, it validates the file and embeds it in the archive as `.packageshift`, independently of dotfile, include, ignore, and Git ignore filtering. The first instruction is mandatory: ```text PACKAGESHIFT 1 ``` ## Metadata ```text MESSAGE "Human-readable update description" BASE sha256:<64 hexadecimal characters> ``` `MESSAGE` is human-facing update text. Every message is printed after a successful `package apply` (and after a dry-run preview). It is never executed. Valid `MESSAGE` lines are also preserved when Package reconstructs stale snapshot metadata. `BASE` identifies the snapshot from which a generated patch was created. The CLI also stores the base file manifest in the update archive so it can verify the target project before applying changes. ## Suggested Git commit message A suggested commit message belongs in `.packagemanifest.json`, not in the shift instruction language: ```json { "gitMessage": "fix: handle expired sessions" } ``` `gitMessage` is optional descriptive metadata. Package prints it after apply next to `MESSAGE` notes and never executes it. Use `--git-message` with `package shift` or `package metadata` when generating metadata with the CLI. ## File instructions Remove a file only when its current content still matches the expected hash: ```text REMOVE "src/api/unused.ts" IF sha256: ``` Move or rename a file: ```text MOVE "src/api/old.ts" TO "src/api/new.ts" IF sha256: ``` Copy an existing project file: ```text COPY "src/config/default.ts" TO "src/config/production.ts" ``` Require an existing file to match a hash before replacing it with the payload stored in the archive: ```text REPLACE "src/index.ts" IF sha256: ``` Change Unix permissions: ```text CHMOD "scripts/deploy.sh" 755 ``` The `IF sha256:...` condition is optional, but recommended for destructive operations. When a local hash differs, interactive `package apply` asks whether to abort, overwrite, or skip. The same behavior can be selected directly with `--conflict abort|overwrite|skip`; `--force` bypasses all base and per-file hash guards. ## Paths Paths are always relative to the selected project root: ```text src/api/client.ts ``` For a workspace-scoped monorepo archive, the selected project root is still the monorepo root. A file in the API workspace therefore remains: ```text apps/api/src/client.ts ``` The workspace scope is stored in `.packagemanifest.json`, not repeated in the instruction language. Generated `shift` and `metadata` operations inherit the base manifest scope and reject a different explicit scope. Use forward slashes on every operating system. Absolute paths, drive-letter paths, NUL bytes, and paths containing `..` are rejected. `.packageshift`, `.packagemanifest.json`, and `.packagemanifest` are reserved CLI metadata paths. Instructions cannot target them, and `.packageshift` is never extracted into the project as payload. Older archives that incorrectly list reserved metadata in their manifest are accepted with a warning and those entries are ignored during `diff` and `apply`. ## Generate the file automatically Use `package metadata` to calculate structural instructions and write both `.packageshift` and `.packagemanifest.json` into the project root: ```bash package metadata base.zip --message "Describe the update" package metadata --message "Use the existing manifest as baseline" ``` The first form compares the current project with a snapshot ZIP. The second form loads the existing project-root `.packagemanifest.json` before replacing it. The short alias is `package meta`. Added and modified file contents are represented by the generated manifest and eventual archive payload; `.packageshift` records the structural operations that payload alone cannot express. ## Metadata recovery for AI-edited snapshots A coding agent does not need to manually derive `.packageshift` if it cannot do so reliably. When a **full snapshot archive** still contains a valid original snapshot manifest but its payload was edited, Package treats the old manifest as the trusted base and reconstructs the update in memory. It derives a `BASE` guard, `REMOVE` operations for deleted files, guarded `REPLACE` operations for changed files, and mode changes. Added files are represented directly by payload. Normalize the recovered archive with: ```bash package repair ai-output.zip --output fixed.zip ``` If the agent omitted or corrupted both metadata files, use the original snapshot as an explicit baseline: ```bash package repair ai-output.zip --base original-snapshot.zip --output fixed.zip ``` Automatic recovery never silently trusts stale patch metadata. Without a valid snapshot baseline, Package fails closed. The shortest receiver workflow is: ```bash package auto update.zip package auto ai-output.zip --base original-snapshot.zip ``` The first command validates and applies a normal update with the usual confirmation. The second reconstructs missing/broken metadata from the trusted base in memory before entering the same apply flow. ## Validation Validate an archive and parse its shift file without changing the project: ```bash package check update.zip ``` A manually created archive may contain `.packageshift` without `.packagemanifest.json`. In that case the CLI validates the ZIP payload and .packageshift syntax, generates temporary file metadata in memory, and reports that embedded manifest/base verification is unavailable. Legacy JSON metadata stored as `.packagemanifest` is also supported. Preview the complete application plan: ```bash package apply update.zip --dry-run ``` Parser errors include the source line, column, error code, failing line, and a correction hint. ## Source snapshot cleanup Shift archives created by `package shift` record the source snapshot filename and SHA-256 in `.packagemanifest.json`. This metadata is separate from the `.packageshift` instruction language. When `deleteSourcePackageOnApply` or `--delete-source-package` is enabled, Package searches for that snapshot beside the applied update archive and in the target project root. It deletes only a regular file whose filename and SHA-256 both match the recorded source. The default is `false`; symlinks, mismatches, missing snapshots, dry runs, and failed applies are retained.