# @haloforge/plugin-pack

`@haloforge/plugin-pack` is the public HaloForge plugin packager CLI.

Use it to validate a plugin directory, inspect an existing `.hfpkg`, and produce a distributable package that HaloForge can install.

## Run With npx

```bash
npx @haloforge/plugin-pack check .
npx @haloforge/plugin-pack pack . --release
npx @haloforge/plugin-pack metadata dist/dev.haloforge.git-1.1.0.hfpkg --pretty --output dist/catalog-draft.json
npx @haloforge/plugin-pack metadata dist/dev.haloforge.git-1.1.0.hfpkg --signing-key-id haloforge-official-2026-05 --signing-key-env HF_PLUGIN_SIGNING_PRIVATE_KEY --pretty --output dist/catalog-draft.json
```

## Commands

```bash
hf-pack check <plugin-dir>
hf-pack info <plugin-dir-or-.hfpkg>
hf-pack pack <plugin-dir> [--out dist] [--release] [--no-backend] [--no-frontend] [--target <triple>]
hf-pack metadata <path.hfpkg> [--artifact-url <url>] [--source official] [--signing-key-id <id>] [--signing-key-env HF_PLUGIN_SIGNING_PRIVATE_KEY] [--output <path>] [--pretty]
hf-pack submit <catalog-draft.json> [--api-base-url https://admin.haloforge.dev] [--token-env HF_ADMIN_TOKEN]
```

## Supported Layout

```text
my-plugin/
  manifest.json
  backend/
    Cargo.toml
    src/
  app/
    package.json
    src/
  assets/
  LICENSE
```

The Rust backend can also live at the plugin root as `Cargo.toml` and `src/`.

The CLI also accepts these common variants:

- Backend in `backend/`, `native/`, `rust/`, or the plugin root.
- Frontend in `frontend/`, `app/`, `ui/`, `web/`, or the plugin root.
- Frontend builds emitted to `dist/`, `build/`, or `.output/`.

## Black-box compatibility checks

`hf-pack check` and `hf-pack pack` validate `host_capabilities` and `compatibility.min_host_api_version` when present.

They also validate `manifest.permissions`. For AI Chat access, the only accepted permission name is `host_aichat_access`; `host_a_i_chat_access` is rejected with a direct error.

They also warn when plugin source code appears to depend on:

- direct `__HF_HOST` access
- direct host IPC calls such as `aichat_send_message`
- direct `plugin_invoke` usage with manually constructed wire names

Those warnings are meant to steer plugins toward the documented `@haloforge/plugin-sdk` host APIs.

## What the CLI Does

1. Validates `manifest.json`.
2. Builds the Rust backend with `cargo build` unless `--no-backend` is used.
3. Builds the frontend app with the detected package manager unless `--no-frontend` is used.
4. Copies declared frontend outputs, packaged native binaries, optional `assets/`, and `LICENSE` into a staging directory.
5. Writes `<plugin-id>-<version>.hfpkg` and `<plugin-id>-<version>.hfpkg.sha256` to the output directory.

## Frontend Build Notes

- The CLI detects `npm`, `pnpm`, `yarn`, and `bun` from lockfiles.
- If `package.json` declares a `packageManager` field, the CLI prefers that over lockfile heuristics.
- By default, a frontend `dist/` directory is packaged under the top-level directory declared by `entry.frontend`, usually `frontend/`.
- This lets a repository keep source in `app/` while still packaging `frontend/index.js` for HaloForge.

## Catalog Metadata

`hf-pack metadata` emits the JSON draft accepted by the HaloForge catalog admin API. It can now sign plugin metadata directly with `--signing-key-id` plus either `--signing-key-base64` or `--signing-key-env`.

`hf-pack submit` accepts `HF_ADMIN_TOKEN`, and also falls back to `HF_SESSION_TOKEN` / `HF_SESSION` for local operator flows that already hold an `hfsess_...` token.

When `hf-pack pack` builds a targeted native artifact, it rewrites the staged manifest so `entry.native` and `compatibility.platforms` only describe the actual packaged target instead of every source-declared platform.
