This guide is the authoritative procedure for building, installing, and verifying Senpi
2026.7.30-2 on:
mengmotaMac— the local Apple Silicon development machinemengmotaHost/ Jobdori — the remote Apple Silicon machine
The procedure deliberately does not publish to npm, create a Git tag, create a commit, push a branch, or modify Senpi configuration. Both machines receive the same locally built npm tarball, verified by SHA-256 before installation.
Senpi 2026.7.30-2 packages the post-v2026.7.30 runtime work and updates the bundled MCP
SDK integration:
- recovers Kimi XML thinking channels and retries one empty assistant response
- reuses the active runtime API key for automatic session titles
- compacts proactively when an agent becomes idle above the configured threshold
- starts a freshly created durable goal immediately while preserving user grace for side questions on existing goals
- serializes multi-file apply-patch mutations and reports concrete failure reasons
- warns when high-reasoning and risky main-model selections are likely to waste capacity
- expands OMO workflow tips in interactive sessions
- updates
@modelcontextprotocol/sdkfrom1.29.0to1.30.0 - updates
brace-expansionfrom vulnerable5.0.7to patched5.0.8 - preserves every bundled extension registration and the separate hooks plugin loader
Read the package changelogs for the complete package-by-package breakdown.
Do not run release QA against the real Senpi agent directory.
The real directory is normally:
~/.senpi/agent/
Every runtime command in this guide uses a disposable HOME and
SENPI_CODING_AGENT_DIR. Global npm installation changes the executable and package files
only; it does not need to read or write Senpi settings, credentials, sessions, extensions,
models, provider state, or authentication data.
Do not use these commands during this release procedure:
senpi install ...
senpi remove ...
senpi update
senpi --no-extensionsPackage-management commands can change configured extension resources or use the normal agent directory. They are unnecessary for verifying the bundled release.
Both machines must have:
- macOS on
arm64 - Node.js
>=24 - npm
- a working
senpiglobal bin directory onPATH
The source machine additionally needs:
- the Senpi repository checkout
- Bun
- Git
- the repository dependencies
tmuxfor the POSIX TUI smoke channel
Binary builds use the Bun 1.4+ canary channel. Local builders should run bun upgrade --canary first to ensure the toolchain matches CI.
Verify the local toolchain:
cd /Users/yeongyu/local-workspaces/senpi
uname -m
node --version
npm --version
bun upgrade --canary
bun --version
git status --short --branchVerify Jobdori without entering its shared Senpi checkout:
ssh mengmotaHost 'uname -m; node --version; npm --version; command -v senpi'Expected architecture on both machines is arm64.
This release uses CalVer:
2026.7.30-2
The seven lockstep package manifests are:
packages/ai/package.jsonpackages/agent/package.jsonpackages/coding-agent/package.jsonpackages/server/package.jsonpackages/pty/package.jsonpackages/senpi-codemode/package.jsonpackages/tui/package.json
@earendil-works/pi-storage-sqlite-node remains on its independent semver line and is not
part of the CalVer bump.
Confirm the source CLI identity without using real configuration:
QA_ROOT="$(mktemp -d)"
HOME="$QA_ROOT/home" \
SENPI_CODING_AGENT_DIR="$QA_ROOT/agent" \
PI_OFFLINE=1 \
node --import tsx packages/coding-agent/src/cli.ts --version
rm -rf "$QA_ROOT"Expected output:
2026.7.30-2
Senpi has several extension surfaces. They must not be conflated.
The authoritative builtinExtensions registration order contains 31 extensions:
hookspermission-systemgpt-apply-patchprompt-presettodowriteredrawsanthropic-web-searchanthropic-bashopenai-web-searchservice-tiermodel-fallbackrecommended-modelsbash-timeoutterminaltool-pair-guardcompactionhistory-searchhelpimport-reprowebsearchwebfetchvideo-inlook-atnested-agents-mdrulesgoalttsrbtwclaude-sdk-oauthconfig-reloadmcp
mcp remains last because its load order is intentional and load-bearing.
Four global default extension factories load separately:
difffilesprompt-url-widgettps
codemodeis bundled as@code-yeongyu/senpi-codemode.llama.cppis a hidden inline extension..codex-plugin/plugin.jsonbelongs to the hooks plugin-manifest loader. Runtime-discovered hook plugins are user resources; no hook plugin is bundled by this repository.
| Surface | Release status |
|---|---|
@modelcontextprotocol/sdk |
updated from exact 1.29.0 to exact 1.30.0 |
brace-expansion |
updated from vulnerable exact 5.0.7 to patched exact 5.0.8 |
@anthropic-ai/claude-agent-sdk |
current at exact 0.3.220 |
@code-yeongyu/senpi-codemode |
lockstep 2026.7.30-2 |
| eight vendored builtin snapshots | preserved from external-versions.json |
The vendored snapshot sources are mostly unpublished on npm. The configured sibling
../pi-extensions checkout and an accessible code-yeongyu/pi-extensions GitHub repository
were unavailable during this release. Their checked-in source plus
external-versions.json therefore remain authoritative; no version was guessed or fabricated.
The isolated Bun package installation on the release machine reports
incorrect peer dependency "@anthropic-ai/sdk@0.91.1". The source and packed manifests both
pin that exact SDK version, while the isolated npm installation, npm audit, standalone Bun
binary, and npm/Bun package CLIs all pass. Treat this as a Bun resolver warning; it does not
change the supported Node/npm installation path or require a configuration migration.
release:local stages the publish manifest and bundled package tree inside the source checkout
while packing. Run it from a clean, dedicated release checkout rather than a shared dirty
worktree. After packing, verify packages/coding-agent/package.json still has only the five
intentional internal bundle entries and run npm install --ignore-scripts before resuming
development so workspace dependency resolution is restored. Do not use destructive Git cleanup
when other work is present.
Run from the repository root:
npm run check
npm run build
CI=1 npm test
npm audit --omit=devThe release-script checks are:
node scripts/generate-coding-agent-shrinkwrap.mjs --check
node scripts/generate-coding-agent-install-lock.mjs --check
node scripts/upstream-release-worthy.mjs
npm run release -- --dry-run
node scripts/release-notes.mjs extract \
--version 2026.7.30-2 \
--tag v2026.7.30-2npm run release -- --dry-run is safe for this workflow. Do not run the live release command:
the live path commits, tags, and pushes.
Run the focused extension suites:
npm --prefix packages/coding-agent exec vitest -- \
--run \
test/suite/builtin-extension-sync.test.ts \
test/suite/vendored-builtins.test.ts \
test/extensions/loader-concurrency.test.ts \
test/mcp/ \
test/suite/claude-sdk-oauth-extension.test.ts \
test/suite/terminal-extension.test.ts \
test/compaction/ \
test/ttsr/The tests import the extension registry or use temporary fixtures. They do not discover extensions from the real Senpi agent directory.
The repository QA harness creates isolated homes, sets offline mode, and guards real authentication state.
Run:
node .agents/skills/senpi-qa/scripts/lib/common.mjs --self-check
node .agents/skills/senpi-qa/scripts/cli-smoke.mjs --self-test
node .agents/skills/senpi-qa/scripts/rpc-drive.mjs --self-test
node .agents/skills/senpi-qa/scripts/rpc-drive.mjs --state
node .agents/skills/senpi-qa/scripts/mock-loop.mjs --self-test
node .agents/skills/senpi-qa/scripts/mock-loop.mjs \
--with-tool \
--api openai-responses
node .agents/skills/senpi-qa/scripts/tui-smoke.mjs \
--self-test \
--driver tmux \
--evidence senpi-2026.7.30-2-tui
node .agents/skills/senpi-qa/scripts/pty-drive.mjs \
--self-test \
--evidence senpi-2026.7.30-2-ptyEvidence belongs under:
local-ignore/qa-evidence/20260730-senpi-release-2026-7-30-2/
Choose one durable output directory outside the repository:
cd /Users/yeongyu/local-workspaces/senpi
ARTIFACT_ROOT="$HOME/.local/share/senpi-releases/2026.7.30-2"
npm run release:local -- --force --out "$ARTIFACT_ROOT"The canonical npm tarball is:
~/.local/share/senpi-releases/2026.7.30-2/tarballs/code-yeongyu-senpi-2026.7.30-2.tgz
Set variables and calculate its checksum:
ARTIFACT_ROOT="$HOME/.local/share/senpi-releases/2026.7.30-2"
TARBALL="$ARTIFACT_ROOT/tarballs/code-yeongyu-senpi-2026.7.30-2.tgz"
shasum -a 256 "$TARBALL"Retain the checksum with the QA evidence. Jobdori must receive this exact file.
An upgrade uses the same checksum-verified tarball as a first installation. It replaces package files only; Senpi settings, credentials, providers, models, permissions, sessions, and plugin enablement files do not need a migration.
Record executable discovery before upgrading:
command -v senpi
senpi --version
npm prefix -gInstall the verified tarball through npm without lifecycle scripts, then refresh the shell’s command cache:
npm install -g --ignore-scripts "$TARBALL"
hash -r
command -v senpi
senpi --versionThe final version must be 2026.7.30-2. If command -v senpi still points at another package
manager’s prefix, inspect that manager’s global package list and remove only its stale
@code-yeongyu/senpi package. Do not edit shell startup files or Senpi configuration merely to
change executable precedence. Re-run the isolated verification commands below after every
upgrade.
Install the verified tarball:
npm install -g --ignore-scripts "$TARBALL"Create an isolated runtime home:
LOCAL_QA="$(mktemp -d)"
mkdir -p "$LOCAL_QA/home" "$LOCAL_QA/agent"Exercise the installed CLI:
HOME="$LOCAL_QA/home" \
SENPI_CODING_AGENT_DIR="$LOCAL_QA/agent" \
PI_OFFLINE=1 \
senpi --version
HOME="$LOCAL_QA/home" \
SENPI_CODING_AGENT_DIR="$LOCAL_QA/agent" \
PI_OFFLINE=1 \
senpi --help
HOME="$LOCAL_QA/home" \
SENPI_CODING_AGENT_DIR="$LOCAL_QA/agent" \
PI_OFFLINE=1 \
senpi --list-modelsThe malformed-input scenario must fail:
HOME="$LOCAL_QA/home" \
SENPI_CODING_AGENT_DIR="$LOCAL_QA/agent" \
PI_OFFLINE=1 \
senpi --definitely-invalidExpected results:
--versionprints exactly2026.7.30-2--helpexits 0 and shows usage--list-modelsexits 0 offline and prints at least one model- the invalid option exits nonzero and identifies the option as unknown
Remove the isolated runtime home after evidence is captured:
rm -rf "$LOCAL_QA"Do not use or clean Jobdori’s shared Senpi source checkout.
Create a remote transfer directory and copy the tarball:
ssh mengmotaHost 'mkdir -p /tmp/senpi-2026.7.30-2'
scp "$TARBALL" \
mengmotaHost:/tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgzCompare checksums:
shasum -a 256 "$TARBALL"
ssh mengmotaHost \
'shasum -a 256 /tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgz'Do not install unless the two hashes are identical.
Install the transferred artifact:
ssh mengmotaHost \
'npm install -g --ignore-scripts \
/tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgz'Exercise the remote CLI inside an isolated home:
ssh mengmotaHost '
REMOTE_QA=$(mktemp -d)
mkdir -p "$REMOTE_QA/home" "$REMOTE_QA/agent"
HOME="$REMOTE_QA/home" \
SENPI_CODING_AGENT_DIR="$REMOTE_QA/agent" \
PI_OFFLINE=1 \
senpi --version
HOME="$REMOTE_QA/home" \
SENPI_CODING_AGENT_DIR="$REMOTE_QA/agent" \
PI_OFFLINE=1 \
senpi --help
HOME="$REMOTE_QA/home" \
SENPI_CODING_AGENT_DIR="$REMOTE_QA/agent" \
PI_OFFLINE=1 \
senpi --list-models
if HOME="$REMOTE_QA/home" \
SENPI_CODING_AGENT_DIR="$REMOTE_QA/agent" \
PI_OFFLINE=1 \
senpi --definitely-invalid
then
echo "invalid option unexpectedly succeeded" >&2
rm -rf "$REMOTE_QA"
exit 1
fi
rm -rf "$REMOTE_QA"
'The expected observables are identical to the local installation.
Before installation, calculate one composite digest for every regular file under the real agent directory. Do not print individual file names, file contents, or per-file hashes.
Local:
CONFIG_DIR="$HOME/.senpi/agent"
find "$CONFIG_DIR" -type f -print0 |
sort -z |
xargs -0 shasum -a 256 |
shasum -a 256Jobdori:
ssh mengmotaHost '
CONFIG_DIR="$HOME/.senpi/agent"
find "$CONFIG_DIR" -type f -print0 |
sort -z |
xargs -0 shasum -a 256 |
shasum -a 256
'Repeat after all installation and QA steps. The before and after composite digests and file counts must match exactly on each machine.
Re-run version synchronization and lock generation:
node scripts/sync-versions.js
PI_ALLOW_LOCKFILE_CHANGE=1 npm install --package-lock-only --ignore-scripts
node scripts/generate-coding-agent-shrinkwrap.mjs
node scripts/generate-coding-agent-install-lock.mjsThen rebuild before packaging.
Confirm the tarball name and inspect npm’s global package:
npm list -g @code-yeongyu/senpi
command -v senpi
senpi --versionReinstall the exact local tarball, not the registry’s latest tag.
Delete only the remote transfer file, copy it again, and re-run both hashes:
ssh mengmotaHost \
'rm -f /tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgz'
scp "$TARBALL" \
mengmotaHost:/tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgzDo not install a mismatched artifact.
Stop immediately. Confirm the command sets:
HOME=<temporary directory>
SENPI_CODING_AGENT_DIR=<temporary directory>/agent
PI_OFFLINE=1
The repository QA harness sets its own isolation variables. Do not override them with real configuration paths.
Run the MCP suite directly:
npm --prefix packages/coding-agent exec vitest -- --run test/mcp/Make only compatibility changes required by a reproduced failure. Do not add fallback logic for unsupported scenarios.
Rollback changes the executable package only. It does not remove or modify
~/.senpi/agent/.
Reinstall the prior published version:
npm install -g @code-yeongyu/senpi@2026.7.30Verify rollback from an isolated home:
ROLLBACK_QA="$(mktemp -d)"
HOME="$ROLLBACK_QA/home" \
SENPI_CODING_AGENT_DIR="$ROLLBACK_QA/agent" \
PI_OFFLINE=1 \
senpi --version
rm -rf "$ROLLBACK_QA"If only Jobdori must be rolled back, run the same install and isolated verification through
ssh mengmotaHost.
After Jobdori is installed and verified:
ssh mengmotaHost 'rm -rf /tmp/senpi-2026.7.30-2'Remove every temporary QA home. Keep:
- the installed
2026.7.30-2package on both machines - the canonical tarball
- its checksum
- the release notes
- the QA evidence directory
Do not remove the real Senpi agent directory.
For the next release:
- Start from a clean, current
main. - Audit every commit since the latest tag.
- Update all affected package
[Unreleased]sections. - Duplicate user-facing AI, agent, and TUI changes into the coding-agent changelog.
- Query registry-verifiable plugin dependencies for newer exact versions.
- Preserve vendored snapshots when no authoritative upstream source is available.
- Update the seven lockstep package versions.
- Regenerate package-lock, publish-deps lock, and install lock.
- Run focused plugin tests.
- Run
check,build, and the full test suite. - Run the real Senpi QA channels.
- Build one canonical local tarball.
- Install that same checksum-identical tarball on every target machine.
- Verify through isolated runtime homes.
- Prove real Senpi configuration stayed unchanged.
- Publish, tag, commit, or push only when separately authorized.