codex-chief-of-staff / distribution
Operational guide · Node 24 / npm 11

How our Git-based npm install works

The Chief-of-Staff MCP is installed straight from an immutable Git revision. The repository already carries its compiled runtime, so npm only has to fetch, place, and link the package—never build it on the consumer machine.

ImmutableRelease tag or 40-character commit only.
Precompileddist/src is committed in Git.
Script-freeConsumer install uses --ignore-scripts.
PATH stableNormal global prefix; registration is unchanged.

The distribution model

A Git dependency behaves differently from a registry tarball when npm sees build lifecycle hooks. Our package deliberately avoids those hooks and treats Git as a transport for an already-built npm package.

Why the original Git install failed

  • dist was ignored, although the executable pointed to dist/src/index.js.
  • Lifecycle preparation could run in npm's temporary Git clone.
  • The clone did not reliably contain the TypeScript development toolchain.
  • The resulting install could be missing its runtime or link back to deleted temporary storage.

The selected design

  • Track only compiled dist/src/**; keep compiled tests and other output ignored.
  • Use maintainer-only compile and pack:verified scripts.
  • Define no prepare, prepack, install, or related Git build triggers.
  • Install the immutable revision with lifecycle scripts disabled.
Git-based npm installation flow A release commit contains source, package metadata and prebuilt runtime. A tag selects it. npm clones it into temporary storage, copies a real package into the global prefix, and links the executable on PATH for Codex. Git revision package.json README.md dist/src/** tag or full SHA npm fetches Temporary clone No build runs No TypeScript needed --ignore-scripts npm places Global prefix Real package directory Executable resolves inside normal global PATH Codex starts MCP stdio server 4 tools App Server
!
The temporary Git clone is not the installed package.

The verifier rejects symlinked package roots and confirms that both the package and executable resolve inside an isolated global prefix—not inside npm's cache or temporary clone.

Installation procedure

Run the verifier from the source checkout first. Only after it passes should the exact same immutable package spec be installed into the normal global prefix.

01

Preflight Git access and the release tag

This proves the host is reachable and the selected tag exists without putting credentials in the package spec.

git ls-remote --exit-code \
  https://git.bodicsek.host/bodicsek/codex-chief-of-staff.git \
  refs/tags/v0.1.1
02

Verify the immutable Git package in isolation

The verifier creates a disposable global prefix, installs with lifecycle scripts disabled, probes the executable over MCP, and then removes the prefix.

npm run verify:git-package -- \
  'git+https://git.bodicsek.host/bodicsek/codex-chief-of-staff.git#v0.1.1'
03

Install into the normal global npm prefix

There is intentionally no --prefix here. The executable must land on the PATH inherited by Codex. The dedicated cache avoids the known ownership problem in the user npm cache.

npm install --global \
  --ignore-scripts \
  --cache /private/tmp/codex-chief-of-staff-npm-cache \
  'git+https://git.bodicsek.host/bodicsek/codex-chief-of-staff.git#v0.1.1'
04

Confirm version, PATH, and registration

The registration stays PATH-based, so upgrading the package does not require a configuration edit.

command -v codex-chief-of-staff
npm list --global --depth=0 codex-chief-of-staff
codex mcp get codex-chief-of-staff --json
05

Restart Codex CLI

MCP processes are initialized by a Codex client. Exit and relaunch the CLI so the existing registration starts the newly installed executable, then inspect /mcp or invoke overview.

codex mcp get codex-chief-of-staff --json
# Restart the Codex CLI, then call the overview MCP tool.

What the verifier proves

verify-git-package.mjs tests the install as a consumer would experience it, while keeping the machine's current global package untouched.

  • Exactly one Git package spec is supplied.
  • The URL uses git+https, git+ssh, or git+file.
  • The revision is a vX.Y.Z tag or full 40-character SHA.
  • npm installs globally inside a newly created temporary prefix.
  • Lifecycle scripts are disabled during the install.
  • A dedicated cache is used outside the global package directory.
  • The package root is a real directory, not a temporary symlink.
  • The executable resolves inside the installed package.
  • The package name and bin mapping match the contract.
  • MCP initialization instructions contain “call overview first”.
  • The exposed inventory is exactly the four observational tools.
  • Raw npm failures are not echoed with credential-bearing arguments.
Contract surfaceRequired valueWhy it matters
Node engine>=24 <25Keeps the supported runtime explicit and reproducible.
Package filesdist/src, README.mdShips runtime and user documentation, excluding TypeScript and tests.
Executablecodex-chief-of-staff → dist/src/index.jsAllows npm to create the stable PATH command.
Git lifecycleNoneConsumer installation never compiles in npm's temporary clone.
MCP toolsoverview, list_threads, inspect_thread, wait_for_changePrevents accidental protocol-surface drift.
App Server URLws://127.0.0.1:4500Preserves the existing loopback registration and shared runtime.

Maintainer release flow

The maintainer still builds and tests. The consumer does not. Release validation makes the committed runtime and immutable tag trustworthy.

Source-to-release sequence

Compile

npm run compile produces dist/src/**.

Test and compare

The full suite runs and verify:runtime fails if rebuilding changes the committed runtime.

Package locally

pack:verified runs gates, then calls npm pack --ignore-scripts.

Commit and tag

The release commit is pushed to both remotes; an immutable version tag points to that commit.

Verify the actual remote

The Git-package verifier runs against the canonical HTTPS tag before rollout.

Release commands

npm run typecheck
npm run compile
npm test
npm run verify:runtime

npm run pack:verified -- \
  --pack-destination /Users/dnabracz/Work/packages \
  --cache /private/tmp/codex-chief-of-staff-npm-cache

npm run verify:package -- \
  /Users/dnabracz/Work/packages/codex-chief-of-staff-0.1.1.tgz

npm run verify:git-package -- \
  'git+https://git.bodicsek.host/bodicsek/codex-chief-of-staff.git#v0.1.1'

Upgrade, rollback, removal

All three operations replace or remove the global npm package. The MCP registration is independent and remains stable unless removal is intentional.

Upgrade or restore v0.1.1

Install the immutable Git tag through the normal global prefix, then restart Codex CLI.

npm install --global \
  --ignore-scripts \
  --cache /private/tmp/codex-chief-of-staff-npm-cache \
  'git+https://git.bodicsek.host/bodicsek/codex-chief-of-staff.git#v0.1.1'

Roll back to 0.1.0

Reinstall the previously verified local tarball, verify the version, then restart Codex CLI.

npm install --global \
  --ignore-scripts \
  --cache /private/tmp/codex-chief-of-staff-npm-cache \
  /Users/dnabracz/Work/packages/codex-chief-of-staff-0.1.0.tgz
×

Remove

Remove the package alone, or also remove the Codex registration when decommissioning the MCP entirely.

npm uninstall --global codex-chief-of-staff

# Optional full decommission:
codex mcp remove codex-chief-of-staff

Troubleshooting map

Diagnose the first failing boundary: Git access, npm placement, PATH resolution, MCP initialization, or App Server connectivity.

SymptomLikely boundaryAction
git ls-remote failsGit authentication, CA trust, or repository accessFix host access first. Do not embed credentials in the Git package URL.
Verifier rejects #mainImmutable input validationUse #vX.Y.Z or the full 40-character commit SHA.
npm reports cache EPERMRoot-owned user cache entriesUse /private/tmp/codex-chief-of-staff-npm-cache; do not change cache ownership automatically.
Executable is missingPackage payload or bin mappingInspect package.json, confirm dist/src/index.js exists, and rerun the isolated verifier.
Executable resolves under a temp pathBroken Git package placementReject the revision. A valid install resolves within the chosen global prefix.
command -v is emptyGlobal npm bin directory not on PATHInspect the normal npm prefix and the PATH inherited by the process launching Codex.
Codex shows old behavior after upgradeExisting MCP child processRestart Codex CLI so it launches the replacement PATH executable.
MCP tools list, but overview is unavailableShared App Server connectivityConfirm CODEX_APP_SERVER_URL=ws://127.0.0.1:4500 and that the listener uses the same CODEX_HOME.

Rules worth remembering

Git is the transport

The revision must already be a complete runnable npm package.

Verification precedes installation

Test in an isolated prefix before changing the normal global package.

Registration is stable

Keep the PATH command and App Server environment unchanged across upgrades.