---
title: "Publish the current Artifacts git HEAD for a saved package after a packageGetGitRemote clone/edit/push workflow and s..."
method: POST
path: "/v1/packages/{package_id}/external-push"
tags: ["packages"]
---

# Publish the current Artifacts git HEAD for a saved package after a packageGetGitRemote clone/edit/push workflow and s...

`POST /v1/packages/{package_id}/external-push`

## Request

- Base URL: `https://api.kody.codes`
- URL: `https://api.kody.codes/v1/packages/{package_id}/external-push`
- Auth: HTTP bearer

Publish the current Artifacts git HEAD for a saved package after a packageGetGitRemote clone/edit/push workflow and server-side checks pass. Non-fast-forward publishes require explicit destructive overwrite confirmation and a verified restorable backup snapshot. Full check-time esbuild is deferred to the published artifact rebuild so callable and importable targets are bundled once; unchanged targets are copied from the previous published commit when their reachable inputs match, and a rebuild failure returns checks_failed with a bundle check. Published and already_published responses include hosted_app_url when the package declares an app, plus bounded static dependent metadata so agents can decide whether stale kody:@ bundled snapshots need inspection or dependent republish; Kody does not republish dependents automatically. already_published means the package tip already matched HEAD before this request began (a true no-op tip); it still runs the artifact rebuild and sets artifacts_rebuilt true when any target needed rebuild or a forced snapshot repair ran. If published_commit moved relative to that pre-request tip — including durable re-entry after an overlapping inline attempt advanced the tip — the status is published with previous_commit set to the baseline tip, even when RepoSession reported tip==HEAD. Those success results also include phase_timings with optional millisecond fields clone_ms, checks_typecheck_ms, checks_bundle_ms, rebuild_ms, dependents_ms, and total_ms — omitted keys did not run; checks_bundle_ms is omitted when bundle validation is deferred to rebuild; checks_bundle_ms and rebuild_ms stay separate. Common cases return the full synchronous result. If the publish exceeds the inline budget (~35s), the work is dispatched once to a durable workflow (idempotent per acting caller plus the full semantic publish input, including force/overwrite flags) and this capability returns status dispatched with a workflow_id to poll via workflowRunList instead of hanging until an opaque execute timeout. Active and succeeded durable runs still dedupe; a terminal failure (for example Durable Object reset because its code was updated) releases the idempotency key so the same commit can be published again. dispatched includes phase_timings.total_ms as time-to-dispatch.

Org permission: `package:write`.

## Path parameters

- `package_id` string, required

## Request body

- object
  - `kody_id` string
  - `allow_force` boolean
  - `confirm_destructive_overwrite` boolean: Set to true only when the user explicitly approved destructive overwrite of existing package source history. Promoting publishes replace advertised history with a new root commit (and drop leftover session refs); promotePublished:false stays additive. Restorable backups retain prior content — secret scrub of backups still needs packageDelete or an explicit purge.
  - `baseline_published_commit` string, nullable

## Response `200`

Success.

- union
  - object
    - `status` 'already_published', required
    - `published_commit` string, nullable, required
    - `artifacts_rebuilt` boolean, required: True when this already_published result still rebuilt one or more package bundle artifacts (true no-op tip that still repaired leftovers). False when every target was already current. Only present on already_published; a tip move relative to the pre-request tip always returns published.
    - `hosted_app_url` string, nullable, required
    - `test_hints` object
      - `app` string
      - `subscriptions` object[]
        - `topic` string, required
        - `snippet` string, required
      - `enablements` object
        - `message` string, required: Agent-directed message: ask the user whether to enable each listed trigger, with the exact enablementEnable call (or Approve for webhooks/email).
        - `triggers` object[], required
          - `kind` 'cron' | 'subscription' | 'webhook', required
          - `name` string, required
          - `reason` 'missing' | 'paused', required
          - `call` string, nullable, required: Exact enablementEnable call when applicable; null for Approve-only triggers.
    - `static_dependents` object, required: Bounded summary of saved packages whose published bundles statically captured this package through kody:@ imports.
      - `total` integer, required: Total direct static dependent packages found.
      - `stale` integer, required: Count of direct static dependent packages with stale bundled snapshots.
      - `truncated` boolean, required: True when more dependent packages exist than are returned in items.
      - `items` object[], required: Bounded direct static dependent package summaries.
        - `package_id` string, required: Saved package id of the dependent package.
        - `kody_id` string, required: Package name leaf of the dependent package.
        - `name` string, required: Scoped package.json name of the dependent package.
        - `source_id` string, required: Repo-backed source id for the dependent package.
        - `published_commit` string, nullable, required: Current published commit of the dependent package.
        - `stale` boolean, required: True when at least one dependent bundle artifact captured a dependency commit that differs from the package's current published commit.
        - `artifact_count` integer, required: Number of published bundle artifacts that reference this dependency.
        - `entrypoints` string[], required: Bounded list of dependent bundle entrypoints referencing this dependency.
        - `entrypoints_truncated` boolean, required: True when the dependent has more matching entrypoints than returned.
        - `bundled_dependency_commit` string, nullable, required: Dependency commit captured in the dependent bundle, or null when matching artifacts have mixed or missing commits.
        - `current_dependency_commit` string, required: Current published commit for the referenced dependency package.
        - `recommended_action` string, required: Agent guidance for this dependent package.
      - `recommended_next_action` string, required: Agent guidance explaining whether to inspect or republish dependents. Kody does not republish dependents automatically.
    - `pending_secret_package_approvals` object, nullable, required: Pending user-secret package approvals detected from secretMounts and secret placeholders. Null when none are pending. Do not treat the package as ready to run until the user approves these and a static-import smoke test from execute succeeds against a read-only export or dry-run input that actually uses the approved secret.
      - `package_id` string, required: Saved package id that needs approvals.
      - `kody_id` string, required: Package name leaf that needs approvals (same value as `slug`).
      - `slug` string, required: Package name leaf that needs approvals.
      - `secrets` object[], required: User secrets that still need package approval.
        - `secret_name` string, required
        - `approval_url` string, required: Per-secret package approval URL in the account UI.
      - `bulk_approval_url` string, nullable, required: One-click bulk approval URL when two or more secrets still need package approval; prefer this over individual links.
    - `allowed_packages_publish_notice` string, nullable: Advance warning when this package fills a user credential whose allowed-packages list excludes it. Stricter enforcement of that setting starts Wednesday, Oct 21, 2026. Null/omitted when there is nothing to warn about. Does not block publish.
    - `listing` object: Present when this package has a public community listing whose pinned snapshot is still behind the published commit after promote auto-sync. Rare; a background backfill retries. No manual republish step is required.
      - `pinnedVersion` string, nullable, required
      - `promotedVersion` string, nullable, required
      - `behind` true, required
      - `updateHint` string, required
      - `updateUrl` string, required
    - `phase_timings` object, required: Coarse packagePublishExternalPush phase timings in milliseconds. Field names are stable. Omitted keys mean that phase did not run in this result. checks_bundle_ms and rebuild_ms stay separate.
      - `clone_ms` integer: Milliseconds spent cloning Artifacts HEAD into the publish workspace. Omitted when this attempt did not clone.
      - `checks_typecheck_ms` integer: Milliseconds spent in the publish typecheck phase. Omitted when typecheck did not run (for example already_published).
      - `checks_bundle_ms` integer: Milliseconds spent in the publish bundle-check phase. Distinct from rebuild_ms. Omitted when bundle check did not run, including when full esbuild validation is deferred to rebuild.
      - `rebuild_ms` integer: Milliseconds spent rebuilding published package artifacts after checks, or confirming they match this commit. Distinct from checks_bundle_ms.
      - `dependents_ms` integer: Milliseconds spent indexing static dependents, hosted app URL, test hints, and pending secret approvals.
      - `total_ms` integer: Milliseconds from the start of this publish attempt until the result was ready. On status dispatched, this is time-to-dispatch.
  - object
    - `status` 'not_fast_forward', required
    - `previous_commit` string, required
    - `published_commit` string, required
    - `message` string, required
  - object
    - `status` 'locked', required
    - `previous_commit` string, nullable, required
    - `pending_commit` string, required: Full 40-character SHA-1 of the HEAD commit that passed checks. Promote it on the website approval page. Do not abbreviate it.
    - `approval_url` string, required: Owner page for pending_commit. The commit query is that full 40-character SHA-1.
    - `message` string, required
  - object
    - `status` 'approval_required', required
    - `previous_commit` string, nullable, required
    - `pending_commit` string, required: HEAD commit that passed checks. The previously published commit keeps serving until the owner approves this one.
    - `approval_url` string, required
    - `approval_bundle_url` string: Present when other paused publishes also wait on the owner: one page that approves them together.
    - `credential_need_changes` union[], required
      - union
        - object
          - `key` string, required
          - `change` 'added', required
          - `after` object, required
            - `kind` 'secret' | 'oauth' | 'mcp' | 'url' | 'login' | 'signing': Omitted when the need accepts any fetch-capable credential for the provider.
            - `provider` string, required
            - `multiple` boolean, required
          - `from` string: The dependency that declared an inherited need.
        - object
          - `key` string, required
          - `change` 'changed', required
          - `before` object, required
            - `kind` 'secret' | 'oauth' | 'mcp' | 'url' | 'login' | 'signing': Omitted when the need accepts any fetch-capable credential for the provider.
            - `provider` string, required
            - `multiple` boolean, required
          - `after` object, required
            - `kind` 'secret' | 'oauth' | 'mcp' | 'url' | 'login' | 'signing': Omitted when the need accepts any fetch-capable credential for the provider.
            - `provider` string, required
            - `multiple` boolean, required
          - `from` string: The dependency that declared an inherited need.
    - `message` string, required
  - object
    - `status` 'checks_failed', required
    - `failed_checks` object[], required
      - `kind` 'manifest' | 'docs' | 'skills' | 'dependencies' | 'bundle' | 'typecheck' | 'lint' | 'credentials' | 'smoke', required
      - `ok` boolean, required
      - `message` string, required
    - `manifest` unknown, required
    - `run_id` string, required
  - object
    - `status` 'published', required
    - `previous_commit` string, nullable, required
    - `published_commit` string, required
    - `manifest` unknown, required
    - `checks` object[], required
      - `kind` 'manifest' | 'docs' | 'skills' | 'dependencies' | 'bundle' | 'typecheck' | 'lint' | 'credentials' | 'smoke', required
      - `ok` boolean, required
      - `message` string, required
    - `hosted_app_url` string, nullable, required
    - `test_hints` object
      - `app` string
      - `subscriptions` object[]
        - `topic` string, required
        - `snippet` string, required
      - `enablements` object
        - `message` string, required: Agent-directed message: ask the user whether to enable each listed trigger, with the exact enablementEnable call (or Approve for webhooks/email).
        - `triggers` object[], required
          - `kind` 'cron' | 'subscription' | 'webhook', required
          - `name` string, required
          - `reason` 'missing' | 'paused', required
          - `call` string, nullable, required: Exact enablementEnable call when applicable; null for Approve-only triggers.
    - `static_dependents` object, required: Bounded summary of saved packages whose published bundles statically captured this package through kody:@ imports.
      - `total` integer, required: Total direct static dependent packages found.
      - `stale` integer, required: Count of direct static dependent packages with stale bundled snapshots.
      - `truncated` boolean, required: True when more dependent packages exist than are returned in items.
      - `items` object[], required: Bounded direct static dependent package summaries.
        - `package_id` string, required: Saved package id of the dependent package.
        - `kody_id` string, required: Package name leaf of the dependent package.
        - `name` string, required: Scoped package.json name of the dependent package.
        - `source_id` string, required: Repo-backed source id for the dependent package.
        - `published_commit` string, nullable, required: Current published commit of the dependent package.
        - `stale` boolean, required: True when at least one dependent bundle artifact captured a dependency commit that differs from the package's current published commit.
        - `artifact_count` integer, required: Number of published bundle artifacts that reference this dependency.
        - `entrypoints` string[], required: Bounded list of dependent bundle entrypoints referencing this dependency.
        - `entrypoints_truncated` boolean, required: True when the dependent has more matching entrypoints than returned.
        - `bundled_dependency_commit` string, nullable, required: Dependency commit captured in the dependent bundle, or null when matching artifacts have mixed or missing commits.
        - `current_dependency_commit` string, required: Current published commit for the referenced dependency package.
        - `recommended_action` string, required: Agent guidance for this dependent package.
      - `recommended_next_action` string, required: Agent guidance explaining whether to inspect or republish dependents. Kody does not republish dependents automatically.
    - `pending_secret_package_approvals` object, nullable, required: Pending user-secret package approvals detected from secretMounts and secret placeholders. Null when none are pending. Do not treat the package as ready to run until the user approves these and a static-import smoke test from execute succeeds against a read-only export or dry-run input that actually uses the approved secret.
      - `package_id` string, required: Saved package id that needs approvals.
      - `kody_id` string, required: Package name leaf that needs approvals (same value as `slug`).
      - `slug` string, required: Package name leaf that needs approvals.
      - `secrets` object[], required: User secrets that still need package approval.
        - `secret_name` string, required
        - `approval_url` string, required: Per-secret package approval URL in the account UI.
      - `bulk_approval_url` string, nullable, required: One-click bulk approval URL when two or more secrets still need package approval; prefer this over individual links.
    - `allowed_packages_publish_notice` string, nullable: Advance warning when this package fills a user credential whose allowed-packages list excludes it. Stricter enforcement of that setting starts Wednesday, Oct 21, 2026. Null/omitted when there is nothing to warn about. Does not block publish.
    - `listing` object: Present when this package has a public community listing whose pinned snapshot is still behind the published commit after promote auto-sync. Rare; a background backfill retries. No manual republish step is required.
      - `pinnedVersion` string, nullable, required
      - `promotedVersion` string, nullable, required
      - `behind` true, required
      - `updateHint` string, required
      - `updateUrl` string, required
    - `phase_timings` object, required: Coarse packagePublishExternalPush phase timings in milliseconds. Field names are stable. Omitted keys mean that phase did not run in this result. checks_bundle_ms and rebuild_ms stay separate.
      - `clone_ms` integer: Milliseconds spent cloning Artifacts HEAD into the publish workspace. Omitted when this attempt did not clone.
      - `checks_typecheck_ms` integer: Milliseconds spent in the publish typecheck phase. Omitted when typecheck did not run (for example already_published).
      - `checks_bundle_ms` integer: Milliseconds spent in the publish bundle-check phase. Distinct from rebuild_ms. Omitted when bundle check did not run, including when full esbuild validation is deferred to rebuild.
      - `rebuild_ms` integer: Milliseconds spent rebuilding published package artifacts after checks, or confirming they match this commit. Distinct from checks_bundle_ms.
      - `dependents_ms` integer: Milliseconds spent indexing static dependents, hosted app URL, test hints, and pending secret approvals.
      - `total_ms` integer: Milliseconds from the start of this publish attempt until the result was ready. On status dispatched, this is time-to-dispatch.
  - object
    - `status` 'dispatched', required
    - `workflow_id` string, required
    - `workflow_name` string, required
    - `idempotency_key` string, required
    - `run_status` string, nullable, required
    - `message` string, required
    - `phase_timings` object, required: Coarse packagePublishExternalPush phase timings in milliseconds. Field names are stable. Omitted keys mean that phase did not run in this result. checks_bundle_ms and rebuild_ms stay separate.
      - `clone_ms` integer: Milliseconds spent cloning Artifacts HEAD into the publish workspace. Omitted when this attempt did not clone.
      - `checks_typecheck_ms` integer: Milliseconds spent in the publish typecheck phase. Omitted when typecheck did not run (for example already_published).
      - `checks_bundle_ms` integer: Milliseconds spent in the publish bundle-check phase. Distinct from rebuild_ms. Omitted when bundle check did not run, including when full esbuild validation is deferred to rebuild.
      - `rebuild_ms` integer: Milliseconds spent rebuilding published package artifacts after checks, or confirming they match this commit. Distinct from checks_bundle_ms.
      - `dependents_ms` integer: Milliseconds spent indexing static dependents, hosted app URL, test hints, and pending secret approvals.
      - `total_ms` integer: Milliseconds from the start of this publish attempt until the result was ready. On status dispatched, this is time-to-dispatch.

## Other responses

- `400`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `401`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `403`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `404`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `409`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `413`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `429`: Too many requests (edge IP/token limit) or an entitlement / plan-cap limit. Wait at least `Retry-After` seconds before retrying.
- `500`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `503`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `default`: Error envelope `{ "error": { "code", "message", "details"? } }`.

## Changes

- **2026-10-20** `a020ecedb82b`: 2 info
  - added the new optional request property `baseline_published_commit`
  - added the required property `oneOf[subschema #1]/artifacts_rebuilt` to the response with the `200` status

[Operation history](https://skmtc.dev/kody/apis/kody-api/changes/v1/packages/:package_id/external-push/post.md)

---

[API](https://skmtc.dev/kody/apis/kody-api.md) · [All operations](https://skmtc.dev/kody/apis/kody-api/llms.txt) · [OpenAPI document](https://skmtc.dev/kody/apis/kody-api/revisions/a020ecedb82b?raw)
