@streetraceing/packageThis document is the operational contract for AI coding agents that create,
inspect, modify, or apply archives handled by @streetraceing/package.
Public URL: https://streetraceing.github.io/package/AGENTS.md
Use this guide when an AI system receives a project ZIP, changes source files, and must return an archive that can be validated, reviewed, and applied by the CLI.
@streetraceing/package is a dependency-free Node.js CLI for transporting
project source state safely.
It supports three related archive types:
package zip.package shift <base.zip>.The tool is not an npm package bundler and does not replace npm pack. It is a
project-source packaging, comparison, update, and rollback system.
Typical commands:
package zip
package shift base.zip --output update.zip
package metadata base.zip --message "Prepare handoff metadata"
package check update.zip
package diff update.zip
package apply update.zip --dry-run
package apply update.zip
The same CLI can be used without global installation:
npx @streetraceing/package zip
npx @streetraceing/package apply update.zip
When an AI agent receives a source archive and must return modified source code, follow this sequence.
Confirm that the archive contains project files and inspect these metadata files when present:
.packagemanifest.json
.packageshift
.packagerc
Run:
package check input.zip
package inspect input.zip
package list input.zip
Do not assume that .packageshift is project source. It is CLI metadata and an
instruction file.
Extract the archive into a clean temporary directory. Never edit directly inside an existing unrelated repository.
Preserve:
.packagerc unless the user explicitly asks to modify it.Do not add generated dependencies, caches, .git, local backups, or temporary
build output unless the task explicitly requires them.
Follow project-local instructions such as AGENTS.md, contributing guides,
formatter settings, tests, and build scripts.
Prefer minimal edits over broad rewrites. Do not change the project structure merely to make packaging easier.
Use the project’s own verification commands. Common examples:
npm run typecheck
npm test
npm run build
The exact commands come from the project, not from this guide.
Prefer the CLI instead of manually calculating hashes and structural changes:
# Use the original snapshot archive as the baseline.
package metadata /path/to/input.zip --message "Describe the delivered changes"
# Or, after extracting an archive that left its old manifest in the project root:
package metadata --message "Describe the delivered changes"
The command reads the baseline before replacing metadata, scans the current
project with .packagerc rules, and writes both .packagemanifest.json and
.packageshift. The short alias is package meta. If no baseline is supplied
and no existing manifest is present, it writes a current snapshot manifest and
an empty structural .packageshift.
The output archive for an AI-delivered change set should contain a valid
.packageshift, even when the only operations are payload additions or
replacements.
At minimum:
PACKAGESHIFT 1
MESSAGE "Describe the delivered changes"
Add explicit structural operations for removals, moves, copies, guarded replacements, and mode changes.
Minimal starter configuration:
{
"$schema": "https://streetraceing.github.io/package/schema.json",
"name": "{folder}.zip",
"strategy": "git",
"gitignore": true
}
An expanded configuration may contain:
PACKAGESHIFT 1
MESSAGE "Add unified menu handling and remove the obsolete view"
BASE sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
REMOVE "src/bot/legacy-menu.ts" IF sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
MOVE "src/bot/menu-old.ts" TO "src/bot/menu.ts" IF sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
REPLACE "src/bot/handlers.ts" IF sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
CHMOD "scripts/deploy.sh" 755
Use forward slashes in archive paths on every operating system.
.packagemanifest.jsonNever return a stale manifest copied from the input archive after source files
have changed. package metadata performs this regeneration automatically; an
agent should still inspect the result before packaging.
The manifest must describe the output archive’s actual payload, including:
Example shape:
{
"schemaVersion": 1,
"kind": "snapshot",
"project": "example-project",
"createdAt": "2026-07-31T00:00:00.000Z",
"rootHash": "sha256:...",
"config": {
"strategy": "git",
"gitignore": true,
"npmignore": false,
"dot": true
},
"files": [
{
"path": "src/index.ts",
"size": 143,
"mode": 438,
"sha256": "sha256:..."
}
]
}
.packagemanifest.json, .packagemanifest, and .packageshift are reserved
metadata and must not appear in manifest.files as project payload.
The output archive must include all retained project files plus the refreshed metadata.
Required for the AI handoff workflow:
.packagemanifest.json
.packageshift
The archive should not contain an extra top-level wrapper directory unless the input format or user explicitly requires one.
Before returning it, run:
package check output.zip
package inspect output.zip
For update archives, also run:
package diff output.zip --cwd /path/to/base-project
package apply output.zip --cwd /path/to/base-project --dry-run
The final answer to the user should identify the archive, summarize changes, and include a concise Git commit message.
.packagemanifest.jsonThis file is generated metadata. It is used for integrity checks, comparison, base verification, source-snapshot identification, and safe application.
Rules for AI agents:
files array.schemaVersion at a supported value.sha256:.A patch manifest may additionally contain:
{
"kind": "patch",
"baseRootHash": "sha256:...",
"baseFiles": [],
"sourcePackage": {
"name": "base.zip",
"sha256": "sha256:..."
}
}
sourcePackage lets deleteSourcePackageOnApply safely identify the snapshot
used to generate the patch. It records a filename and hash, not an absolute path.
.packageshift.packageshift is parsed by the CLI and is never copied into the target project.
It is not a source file, configuration file, or payload file.
The first non-comment instruction must be:
PACKAGESHIFT 1
Supported instructions:
MESSAGE "Description"
BASE sha256:<64-hex-hash>
REMOVE "path" [IF sha256:<hash>]
MOVE "source" TO "destination" [IF sha256:<hash>]
COPY "source" TO "destination"
REPLACE "path" [IF sha256:<hash>]
CHMOD "path" <octal-mode>
Use IF sha256: guards for destructive operations whenever the base content is
known. A guard prevents silently deleting or replacing a locally changed file.
Reserved paths may not be targeted:
.packageshift
.packagemanifest.json
.packagemanifest
See the full format reference: https://streetraceing.github.io/package/PACKAGESHIFT.md
.packagerc.packagerc is strict JSON. It does not allow comments, single-quoted strings,
unquoted keys, or trailing commas.
Schema URL: https://streetraceing.github.io/package/schema.json
Example:
{
"$schema": "https://streetraceing.github.io/package/schema.json",
"strategy": "git",
"gitignore": true,
"dot": true,
"ignore": ["coverage/**"],
"forceInclude": [],
"forceIgnore": [],
"packageManager": "npm",
"packageManagerIgnore": false,
"packageManagerIgnoreFile": ".npmignore",
"beforePackage": [],
"afterPackage": [],
"beforeApply": [],
"afterApply": [],
"deletePackageOnApply": false,
"deleteSourcePackageOnApply": false,
"saveDeletedCache": true
}
package init creates the minimal form and also creates or updates .gitignore
with a generated *.zip rule so locally created package archives are not
committed accidentally. Omitted fields still use validated defaults. Use
package config --json to inspect the effective configuration and
package init --full only when an expanded template is intentionally wanted.
Unless the user specifically requests a configuration change, preserve the
existing .packagerc exactly. AI agents should not silently enable cleanup,
force overwrite behavior, disable backups, or add shell hooks.
package zip
With an explicit output:
package zip --output project-base.zip
The snapshot contains the selected project files and a generated manifest. File selection uses Git when possible:
git ls-files --cached --others --exclude-standard
If Git is unavailable or strategy is walk, the CLI uses its own ignore-aware
walker.
Always excluded from ordinary source payload are Git metadata, dependencies, backup/cache directories, generated package metadata, and the output archive itself.
When an entry project’s .packagerc contains depends_on, treat the archive as
one composed delivery made from several independently configured projects.
Example entry configuration in codeissue/website/.packagerc:
{
"depends_on": [
{
"path": "../backend",
"name": "@codeissue/backend"
}
]
}
Inspect the graph before packaging:
cd codeissue/website
package projects
package projects --json
Then use the normal commands from the entry project:
package zip
package shift website.zip --output update.zip
package apply update.zip --dry-run
package apply update.zip --yes
Important invariants for agents:
website/** and backend/**; archive paths stay relative to
their shared parent directory;depends_on.path relative to the .packagerc that declares it,
not relative to that configuration’s optional project root;.packagerc unless the user explicitly requests a
configuration change; Package carries discovered local config files even when
an ordinary project ignore rule would omit them;manifest.composition and preserve its entry project, project paths,
names, and dependency edges throughout a snapshot/patch chain;cwd;The entry project owns archive-level policies such as output, compression,
conflict behavior, backups, and cleanup. Agents should run apply from the entry
project so those policies are loaded; Package itself resolves the shared target
root and updates all composed project directories.
depends_on and legacy workspace selection are intentionally mutually exclusive.
Use explicit composition when projects have their own .packagerc files and
must be delivered together.
Before packaging a package-manager monorepo without depends_on, inspect
discovery and resolve the intended scope:
package workspaces
package workspaces @scope/api --json
Create a scoped snapshot by package name, root-relative workspace path, basename, or glob. Add local graph expansion only when the requested deliverable needs it:
package zip --workspace @scope/api --with-dependencies
package zip -w apps/web -w packages/ui
package zip --all-workspaces --no-root-files
Workspace payload paths remain relative to the monorepo root. Root lockfiles and
shared configuration are controlled by monorepo.shared and
includeRootFiles.
The snapshot manifest stores monorepo.root, selected workspace names/paths, and
the root-file policy. shift and metadata inherit that scope and reject a
conflicting explicit selection with WORKSPACE_SCOPE_MISMATCH.
After changing the project:
package shift project-base.zip --output project-update.zip \
--message "Implement the requested update"
A generated patch contains:
.packagemanifest.json with base metadata;.packageshift for removals, moves, replacements, and mode changes.The CLI accepts a ZIP containing payload and .packageshift without an embedded
manifest. This is useful for interoperability, but base-project verification is
limited.
The CLI prints a warning and derives temporary file metadata from ZIP entries. AI agents should prefer a real generated manifest whenever possible.
Never apply an untrusted archive blindly.
Validate syntax and integrity:
package check update.zip
Inspect metadata:
package inspect update.zip
package inspect update.zip --json
Preview differences:
package diff update.zip
package apply update.zip --dry-run
Machine-readable output is available where documented:
package diff update.zip --json
package list update.zip --json
Interactive apply:
package apply update.zip
Non-interactive apply after prior review:
package apply update.zip --yes
Important options:
--dry-run
--yes
--force
--allow-project-mismatch
--rewrite-all
--backup / --no-backup
--conflict abort|overwrite|skip
--delete-package / --keep-package
--delete-source-package / --keep-source-package
--save-deleted-cache / --no-save-deleted-cache
abort — safest default; stop before changes are written.overwrite — replace conflicting local content.skip — keep conflicting local paths and apply the remaining operations.--force bypasses base and per-file hash guards. An AI agent should not use it
unless the user explicitly accepts the risk or the agent has independently
verified the target state.
Before a real apply, the CLI evaluates whether the archive belongs to the target.
A verified patch base is treated as authoritative. Otherwise it compares
package.json names, embedded manifest project metadata, and whether archive
payload paths overlap the existing project structure.
When the archive appears to target another project, interactive apply prints both
identities and requires the operator to type the target directory name before the
normal apply confirmation. --yes does not suppress this extra guard. In a
non-interactive environment, the command fails with PROJECT_MISMATCH unless
--allow-project-mismatch is passed explicitly.
AI agents should follow this sequence:
package apply update.zip --cwd /path/to/target --dry-run
package inspect update.zip
# Only after confirming the target intentionally differs:
package apply update.zip --cwd /path/to/target --yes --allow-project-mismatch
Do not add --allow-project-mismatch automatically. Treat it as a user-approved
safety override, separate from --force. A dry run only warns and remains
non-destructive.
Applying a snapshot is an overlay. Files present in the archive are added or updated. Files absent from the archive are not automatically deleted.
The default write policy is selective: Package hashes current payload files and writes only additions, content changes, and mode changes. Unchanged files are not opened for writing, keep their timestamps, and are excluded from apply backups and deleted-file cache sessions.
Use --rewrite-all only when a full payload rewrite is intentional:
package apply snapshot.zip --rewrite-all
This flag rewrites every payload file even when its content and mode already
match. It does not delete extra target files; deletion still requires an explicit
.packageshift REMOVE instruction.
The CLI validates the archive before writing. With backups enabled, it records the affected pre-apply state. If the file transaction fails, it attempts to roll back partial changes.
beforeApply is strict and runs before file changes. If it fails, apply stops.
afterApply is best-effort and runs after successful file changes. If a command
fails, the CLI prints a warning, continues later afterApply commands, keeps the
applied files, and proceeds with configured cleanup.
Hooks may be one shell command string or an array of commands.
{
"packageManager": "npm",
"beforePackage": ["{packageManager} run typecheck"],
"afterPackage": ["node scripts/report-package.mjs"],
"beforeApply": ["{packageManager} run preapply"],
"afterApply": ["{packageManager} install", "{packageManager} run build"]
}
Execution rules:
depends_on composition, hooks run dependency-first and each command’s
working directory is the project that declared it;beforePackage and afterPackage wrap zip and shift;beforeApply runs after validation and confirmation, before writes;afterApply runs after successful writes;--dry-run;Available environment variables:
PACKAGE_HOOK
PACKAGE_COMMAND
PACKAGE_ROOT
PACKAGE_ARCHIVE
PACKAGE_MANAGER
PACKAGE_PROJECT_NAME
PACKAGE_PROJECT_PATH
PACKAGE_COMPOSITION_ROOT
packageManager defaults to npm, but may name pnpm, yarn, bun, or any
other shell command. {packageManager} is replaced before a hook starts.
Security rule for AI agents: do not add or modify hooks without explicit user approval. Hooks execute arbitrary shell commands.
Both cleanup options are disabled by default.
{
"deletePackageOnApply": false,
"deleteSourcePackageOnApply": false
}
deletePackageOnApplyAfter a successful apply lifecycle, the CLI may delete the archive that was just applied.
An absolute external path can therefore be deleted when this setting or the
--delete-package flag is enabled.
deleteSourcePackageOnApplyFor a generated patch, the CLI first uses the source snapshot filename and SHA-256 stored in the patch manifest.
It searches:
If explicit source metadata is unavailable, it may safely identify exactly one snapshot whose manifest matches the project state before apply. Ambiguous, changed, missing, or symbolic-link candidates are preserved.
AI agents should keep both cleanup settings false unless the user asks for
automatic deletion.
saveDeletedCache defaults to true.
Before the CLI removes or replaces a regular file, it saves the previous content under the user’s data directory:
~/streetraceing/.package/cache/<project-id>/<operation-id>
On Windows:
%USERPROFILE%\streetraceing\.package\cache\<project-id>\<operation-id>
Each operation includes .packagecache.json with original paths, cached paths,
reasons, sizes, modes, and SHA-256 values.
The cache covers CLI-managed destructive operations such as:
init --force;Files larger than 10 MiB are still cached, but the CLI prints an explicit warning before continuing.
Commands executed inside hooks are separate processes. The CLI cannot intercept or cache files deleted by arbitrary hook scripts.
Apply backups are stored outside the project:
~/streetraceing/.package/backups/<project-id>
On Windows the root is below %USERPROFILE%.
Commands:
package backup list
package backup inspect 1
package backup inspect 1 --json
package backup restore latest
package backup restore 3 --yes
A restore creates a recovery backup of the current state first. It then applies the selected rollback version and every newer delta in reverse order. The recovery version can later undo the rollback.
Set STREETRACEING_PACKAGE_HOME to isolate or relocate package-managed storage:
STREETRACEING_PACKAGE_HOME=/tmp/package-data package backup list
PowerShell:
$env:STREETRACEING_PACKAGE_HOME = "C:\Temp\package-data"
package backup list
Packaging source may accidentally include secrets. Review at least:
.env
.env.*
*.pem
*.key
id_rsa
.npmrc
service-account*.json
The sensitiveFiles configuration supports warn, error, or allow.
AI agents must never invent, expose, or preserve real secrets merely to make an
archive complete. When a secret-looking file is present, follow the user’s
security requirements and prefer placeholders such as .env.example.
Archive and .packageshift paths always use / separators:
src/api/client.ts
Do not use:
C:\project\src\api\client.ts
/src/api/client.ts
../outside.txt
The CLI rejects absolute paths, drive-prefixed paths, NUL bytes, traversal, and unsafe symbolic-link boundaries.
When showing shell examples, account for platform quoting:
package apply "C:\Users\name\Downloads\update.zip"
package apply "/home/name/Downloads/update.zip"
With default configuration:
{
"deterministic": true,
"preserveMode": true,
"preserveMtime": false,
"compressionLevel": 9
}
Deterministic archives stabilize metadata so equivalent payloads produce repeatable package content. File hashes and root hashes remain the authoritative integrity values.
An AI agent should not disable deterministic behavior without a specific reason.
Do not:
.packageshift into the target project;manifest.files;.packagemanifest.json;.packagerc without user approval;.git, node_modules, local backup/cache directories, or temporary
workspace files;.packageshift;Before returning an archive, verify all of the following:
.packageshift..packagerc is unchanged unless requested..packageshift starts with PACKAGESHIFT 1..packageshift is not listed as payload..packagemanifest.json matches actual archive contents.package check succeeds on the output ZIP.package apply --dry-run was used when a base project was available.Assume the agent receives website-base.zip and must add a health endpoint,
modify the application entry point, and remove an obsolete module.
Extract and edit:
mkdir work
cd work
unzip ../website-base.zip
# Edit files here.
Create .packageshift:
PACKAGESHIFT 1
MESSAGE "Add health endpoint and remove obsolete status module"
REMOVE "src/status-old.ts" IF sha256:1111111111111111111111111111111111111111111111111111111111111111
REPLACE "src/index.ts" IF sha256:2222222222222222222222222222222222222222222222222222222222222222
The new payload contains:
src/index.ts
src/api/health.ts
Regenerate .packagemanifest.json, create website-update.zip, then verify:
package check website-update.zip
package diff website-update.zip --cwd ../website-base-project
package apply website-update.zip --cwd ../website-base-project --dry-run
Expected review output should identify:
MODIFY src/index.ts
ADD src/api/health.ts
REMOVE src/status-old.ts
Return the archive with a concise summary and commit message, for example:
feat: add health endpoint and remove obsolete status module
The safest way to generate metadata is to let the CLI do it.
Create the base snapshot:
package zip --output project-base.zip
Change the project, then create the patch:
package shift project-base.zip \
--output project-update.zip \
--message "Implement requested project changes"
Review and apply:
package check project-update.zip
package diff project-update.zip
package apply project-update.zip --dry-run
package apply project-update.zip
This workflow automatically generates file hashes, base metadata, source-package
identity, and .packageshift operations.
For CI or agent automation:
--json when structured output is supported;--dry-run before a destructive command;--yes only after review;conflictStrategy at abort unless a different strategy is intentional;beforeApply failure as a blocked apply;afterApply warnings as post-apply task failures, not failed file
application;Interactive output distinguishes documentation from active operations. Help
output (package -h) uses only white and gray shades. Operational commands use
one consistent tree: ┌─ starts a section, ├─ and └─ list details, and ┞─
marks warnings and changes. Semantic colors help an agent or human scan results
quickly: green means successful work or additions, cyan/blue means information
or modifications, magenta means structural actions, yellow means caution or mode
changes, and red means removals or errors. Color is
automatically disabled when output is redirected or JSON is requested. Set
NO_COLOR=1 to disable ANSI output explicitly.
AI agents should account for these implementation limits:
--rewrite-all rewrites payload files but still does not remove extra target
files..packageshift reference:
https://streetraceing.github.io/package/PACKAGESHIFT.md@streetraceing/packageWhen this guide and project-local instructions differ, follow the more specific
project-local instruction unless it would make the archive invalid or unsafe.
When uncertain, preserve data, avoid destructive options, run package check,
and ask the user before enabling cleanup, force, overwrite, or shell hooks.