## Summary
Refreshes the safe TypeScript, Python, and GitHub Actions dependency
surface in one maintainer-owned change. Effect 4 rc.115, Vitest 5, the
vendored Effect source, CLI migrations, and agent guidance move
together, while known incompatible boundaries stay pinned. The Effect v4
config schemas preserve unknown fields across `config.json` and
`user_data.json` read-update-write cycles.
Fixes#4535
## Changes
- Keeps Cloudflare Workers fixtures on Vitest 4 until
`@cloudflare/vitest-pool-workers` supports Vitest 5.
- Keeps Mastra on the Workers-compatible versions and AG2 below 1.0
because AG2 1.x no longer ships the imported `autogen` module.
- Removes the unused package-level `pnpm` dependency instead of changing
the repository's pinned pnpm 11 toolchain.
- Migrates the Effect CLI APIs, Eve callback contract, provider peer
ranges, and repository skills required by the selected upgrades.
- Preserves unknown CLI settings when `config.json` and `user_data.json`
are read, updated, and written back.
- Uses immutable SHA pins for the refreshed Claude Code actions and adds
release metadata for the affected published TypeScript packages.
## Type of change
- [x] Bug fix
- [ ] New feature
- [x] Refactor/Chore
- [x] Documentation
- [ ] Breaking change
## How Has This Been Tested?
- `pnpm install --frozen-lockfile` with pnpm 11.8.0
- `pnpm typecheck`
- `pnpm build:packages`
- `pnpm --filter @composio/cli test` — 1,400 passed, 1 skipped,
including targeted persistence regressions for `config.json` and
`user_data.json`
- Package tests — 28 workspace tasks passed
- Example typechecks/tests and all Cloudflare dry-runs
- Provider compatibility, experimental/Eve, Mastra, CLI keyring, and
JSON-schema Effect checks
- Agent-skill validation, routing validation, Effect skill example
compilation, and peer-dependency checks
- All three Python `uv lock --check` runs
- `nox -s tst_autogen`, `nox -s snt`, and `nox -s chk type_inference`
- Production dependency audit completed with the repository's three
existing ignored advisories
Docker CLI E2E was not run locally because the Docker daemon is
unavailable. The exact root lint command also enters the vendored Effect
submodule, whose checkout does not install its `@effect/oxc/oxlint`
plugin; scoped lint over the changed non-vendor files passed.
## Screenshots (if applicable)
Not applicable.
## Checklist
- [x] I have read the Code of Conduct and this PR adheres to it
- [ ] I ran linters/tests locally and they passed
- [x] I updated documentation as needed
- [x] I added tests or explain why not applicable
- [x] I added a changeset if this change affects published packages
The dependency migrations are covered by the focused and workspace
suites. Two targeted regression tests verify that CLI updates preserve
unknown fields in `config.json` and `user_data.json`.
## Additional context
The Connect client sync retains its existing `Bash(curl *)` permission
while moving the removed `allowed_tools` input to `claude_args`. A
separate hardening change should move logo downloads outside the
model-controlled shell boundary.
---
[](https://github.com/EveryInc/compound-engineering-plugin)
`composio execute` stored a response in a session file once js-tiktoken
counted more than 10,000 o200k tokens. Nothing reads that count as a number,
and o200k is not the tokenizer of the model reading the output, so the exact
count only moved the cutoff while costing the 2.3MB rank table, ~330ms after
large tool calls, and a separately shipped companion file with its own repair
path.
Responses over 40,000 UTF-8 bytes are stored now. The summary keeps
`tokenCount`, now estimated at four bytes per token, and gains `sizeBytes`.
The execute-output-encoder-runtime companion, js-tiktoken, and their build,
packaging and test entries are removed. The uninstall lists keep the
companion's file name so installs that shipped it can still remove it.
- Import an in-process companion before checking the rest of the set, so a
missing unrelated companion cannot fail generate or run through an offline
repair. Repair runs only when the requested module fails to load.
- Check each companion's required exports, so a file left by another release
fails with a typed reinstall error instead of calling a missing export.
- When the tokenizer cannot load, store any response past the byte pre-filter.
The four-bytes-per-token estimate can undercount, so it no longer keeps a
response inline.
- Bundle the executable graph check with the release build's env inlining,
defines, NODE_ENV and syntax minification.
Claude-Session: https://claude.ai/code/session_01MTb47vexN35pLGsSZwBmrJ
A large execute measured its output after the tool call had already succeeded,
so a missing encoder companion whose repair download failed turned a successful
call into a failed command. Fall back to a byte-based token estimate instead.
Load companion modules with Effect.tryPromise so an unloadable file is a typed
RunCompanionRepairError rather than a defect, and add the two companions as
tsdown entries so the dist build can resolve them.
The executable graph check listed @composio/core's root entry with a pattern
that could never match Bun's relative module paths. The root entry is still
bundled behind the file-upload dynamic import, so drop that entry and correct
the constants comment.
`composio --version` goes from 288ms to 199ms, peak RSS from 97.8MB to
77.3MB, and the executable from 85.9MB to 79.7MB. Every command benefits.
A compiled Bun binary parses its whole embedded bundle before the first
line of JavaScript runs, and #4468 had already made sure the TypeScript
compiler and the tokenizer rank table were never *evaluated* unless
`generate`, `run`, or a large `execute` response needed them. They were
still *parsed* on every start: the compiler alone was 44% of the
executable's JavaScript and the o200k rank table another 28%, so
`--version` spent ~75ms reading code it could never call.
Both now ship as companion modules next to the executable, through the
mechanism `composio run` already uses for its own runtime helpers:
- `generation-runtime.mjs` carries `src/generation/*`, the `composio run`
source rewrites, `typescript`, `@composio/ts-builders` and
`openapi-typescript`. `generate ts`, `generate py` and `run` load it
with `loadInstalledCompanionModule`; from a source checkout the loader
resolves the `.ts` next to `run-companion-modules.ts` instead, so tests
and `bun run src/bin.ts` need no build step.
- `execute-output-encoder-runtime.mjs` carries `js-tiktoken/lite` and the
rank table. `execute` loads it only once a response exceeds the 10KB
byte pre-filter.
A companion bundles its own copy of `effect`, and a fiber cannot run
primitives built by another copy of the runtime, so nothing Effect-shaped
crosses the boundary: the generation companion exposes plain functions
and promises, runs its pipelines on its own runtime, and returns failures
as values that `src/generation/errors.ts` rebuilds as the CLI's own error
classes, stack included. Generated output is byte-identical to #4468 for
`generate ts`, `generate ts --transpiled` and `generate py`.
Both modules join `RUN_COMPANION_MODULE_BASENAMES`, so the build, release
packaging, install verification, `upgrade` and the self-repair download
pick them up unchanged. The three hand-maintained uninstall lists and the
upgrade E2E fixture gain the two file names.
Two smaller startup costs go with it:
- `src/constants.ts` imported `constants` from `@composio/core`'s root
entry for two strings and two URLs, which evaluated the whole SDK at
startup (~25ms of module-scope work, mostly zod schemas). The four
values are spelled out and pinned to core's by a test.
- `tool-file-uploads.ts` imported three core helpers at module scope that
only a file upload reaches; they are imported on that path now.
The binary build gains a guard: after bundling the companions it bundles
`src/bin.ts` once more unminified and fails if the executable's graph
reaches `typescript`, `js-tiktoken`, core's root entry, `src/generation/*`
or a companion entry. Without it a stray static import would put the
compiler back into the executable with nothing to notice.
Building also surfaced that `assertBundledRuntimeFiles` blanked string
literals to same-length runs of spaces, which made the import patterns'
`^\s*` backtrack quadratically across the compiler's multi-megabyte
embedded lib strings and stalled the build for over ten minutes. String
bodies are dropped now. (The check itself has never matched a specifier,
since the specifiers it looks for are the string literals it removes;
that is left as it was.)
Measured on the pinned toolchain, Bun 1.4.1+4661e494f, linux-x64, best
of 15, telemetry disabled, both binaries built in the same session:
composio --version 288ms -> 199ms
tools execute --help 287ms -> 202ms
peak RSS 97.8MB -> 77.3MB
executable 85.9MB -> 79.7MB
executable JavaScript 8.3MB -> 2.1MB (minified)
The `execute` tail after `execute.tool_call.end` is unchanged for
responses under 10KB (~10ms) and ~20ms slower above it (351 -> 374ms),
which is the on-demand parse of the 2.2MB encoder companion.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wx9gEjuiHux2weiHjdNcDs
Rebuilds the Effect v4 port on top of `next` at `effect@4.0.0-rc.112`
(the newest release that clears the repository's 3-day
`minimumReleaseAge` gate). The three v3-compatible preparation PRs
(#4358, #4359, #4360) already landed on `next`, so this PR is now only
the cutover.
## What changes
- Pins `effect`, `@effect/platform-bun`, and `@effect/vitest` to exact
`4.0.0-rc.112`; drops `@effect/cli`, `@effect/platform`,
`@effect/platform-node`, and the `toml` override that existed only for
`@effect/cli`. The `ts/vendor/effect` source oracle moves to the
`effect@4.0.0-rc.112` release commit.
- Services become `Context.Service` classes with explicit `Default`
layers; `Either` becomes `Result`; `ParseResult` becomes
`Schema.SchemaError`; platform modules come from `effect/FileSystem`,
`effect/Path`, `effect/PlatformError`, `effect/unstable/process`, and
`effect/unstable/http`.
- The runner drives `Command.runWith` with v4's default help and error
rendering. `CliError.ShowHelp` carries its own exit code, help for
non-explicit invocations renders on stderr, and "Did you mean?"
suggestions render. `command-introspection.ts` is gone: v4 renders the
resolved command's help and the "missing value" tip itself.
- `composio --version`, `composio -v`, and `composio version` print the
same bare semver (`GlobalFlag.Version` is not enabled; the flag
spellings are rewritten to the `version` command before parsing).
- Root `--log-level` is a shared flag applied after the subcommand tree
is attached, so `composio --log-level Debug <subcommand>` both parses
and takes effect.
- Every `Flag.boolean` carries an explicit default, because rc.112 makes
boolean flags required when omitted.
- A `Result` is not an `Effect` at runtime in rc.112 even though the
type checker accepts `yield*` on it (the fiber dies with "Not a valid
effect"); every `Result` is lifted with `Effect.fromResult`, and the
skill/AGENTS guidance says so.
- Every `ChildProcess.make` site passes `extendEnv: true`, because
rc.112 no longer inherits the parent environment by default.
- `--log-level` and `COMPOSIO_LOG_LEVEL` are exact-match on the
`LogLevel` names (`All`, `Fatal`, `Error`, `Warn`, `Info`, `Debug`,
`Trace`, `None`) with no case folding, per the earlier review decision;
README updated.
- Spawned children pass `extendEnv: true`, because rc.112's
`ChildProcess` no longer inherits the parent environment by default.
- ISO timestamps decode through `Schema.DateTimeUtcFromString`;
`Schema.DateTimeUtc` is no longer a string codec in rc.112.
- `ConfigProvider.fromEnv()` snapshots the environment at construction
in v4, so providers that must observe later changes are built per read
(`plugin-hint.ts`, `install.cmd.ts`, `config.ts`) and tests use a
live-env provider helper.
- `cli-keyring` and `json-schema-to-effect-schema` are ported alongside
(the latter on `Schema.makeFilter`).
- The `effect-v4` skill, the `cli-command` and `typescript-testing`
references, `ts/packages/cli/AGENTS.md`, and the oxlint config are
updated to the rc.112 reality. The skill's example checker
(`.agents/skills/effect-v4/scripts/check-examples.mjs`, lifted from
#3851) compiles every TypeScript block in the skill against the pinned
packages.
- The `js-yaml` overrides move to the 4.3.2 / 3.15.2 lines that
GHSA-2883-xcg3-v3hh requires; `pnpm audit --prod` is clean apart from
the already-ignored `extract-zip` advisory.
## Behaviour notes
- `composio <unknown> --help` now prints the root help with exit 0 (v4's
global `--help` handling); `composio <unknown>` without `--help` still
fails with the unknown-subcommand error.
## Validation
- `pnpm --filter @composio/cli typecheck` (src + test): 0 errors
- `pnpm --filter @composio/cli test`: 127 files, 1325 tests pass, 1
skipped; `validate:boundaries` and `validate:skills` pass
- `@composio/cli-keyring` and `@composio/json-schema-to-effect-schema`
typecheck, test, and build pass
- `pnpm validate:agent-skills` and `pnpm validate:skill-routing` pass
(19 skills)
- oxlint clean on `ts/packages/cli`, `cli-keyring`,
`json-schema-to-effect-schema`
- CLI bundle and standalone binary build; smoke-checked `version`,
`--version`, `-v`, `--help`, unknown subcommand, unrecognized flag,
missing flag value
- Docker CLI e2e suites pass against an image built from this branch:
`version`, `toolkits-list`, `toolkits-info`, `toolkits-search`,
`setup-plugins`, `run`. `whoami` (needs an API key), `install` (needs a
release dir), and `upgrade` (needs network) were not run.
No changeset: `@composio/cli` is Changesets-ignored and the ported
sibling packages are private. Human-facing notes are in
`ts/packages/cli/CHANGELOG.md`.
https://claude.ai/code/session_01AW7ZPhfZuni6PrCJ9X86DX
This PR:
- rebases onto `next` now that
https://github.com/ComposioHQ/composio/pull/4358 and
https://github.com/ComposioHQ/composio/pull/4359 are merged
- rewrites every `@effect/platform` and `@effect/platform-bun` barrel
import under `ts/packages/cli` (155 statements in 112 files) as a
per-module namespace import, e.g. `import * as FileSystem from
'@effect/platform/FileSystem'`
- adds both barrels to the `no-restricted-imports` lists for
`ts/packages/cli/src`, with messages pointing at the subpath form
- updates the boundary guidance in `ts/packages/cli/AGENTS.md` and the
`cli-command` skill to the subpath form
## Context
Both barrels are pure namespace re-exports (60 and 19 modules), so this
is import-only with no runtime change. Effect v4 spreads these modules
across `effect` (`FileSystem`, `Path`, `PlatformError`),
`effect/unstable/http`, and `effect/unstable/process`; with per-module
imports the port becomes a scripted path rewrite instead of
hand-splitting each barrel line. Third of three preparation PRs.
## Validation
- `pnpm --filter @composio/cli typecheck` and oxlint clean; a probe
barrel import in `src/` is rejected by the new rule
- `pnpm --filter @composio/cli test`: 127 files, 1318 tests pass, 1
skipped
The release build downloads four `@zed-industries/codex-acp-<platform>`
tarballs itself, because pnpm will only install the one matching the runner's
platform and the archive has to name all four. Those bytes were extracted and
copied, executable, into the published CLI archive without ever being checked
against a known hash — the one dependency in the release that got none of the
integrity verification `pnpm install --frozen-lockfile` applies to everything
else.
`pnpm-lock.yaml` already pins a sha512 for each of them, so the fix is to use
it. The hash is read from the lockfile rather than the registry's own
`dist.integrity`, since whoever can serve a tarball can serve the metadata
vouching for it, and it is looked up before the download so a package the
lockfile never resolved aborts the build instead of shipping unverified bytes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
## Problem
`composio upgrade` from `0.3.4-beta.351` to `0.4.0-beta.359` looked hung
for several minutes:
```
◐ New version available: @composio/cli@0.4.0-beta.359 (current: @composio/cli@0.3.4-beta.351). Downloading.
```
Two independent defects behind that.
**No feedback.** `upgrade-binary.ts` printed that message once and then
said nothing until the download finished. The only byte-level signal was
a `logDebug`, invisible in a normal run, because the body was read with
a single buffered `response.arrayBuffer`.
**Mostly wasted payload.** The archive is 338 MB, and ~651 MB of what it
unpacks is `codex-acp` binaries for the three platforms the host cannot
execute. Measured on a darwin-arm64 install:
```
~/.composio 967 MB total
codex/darwin-arm64 180 MB ← the only one this Mac can run
codex/darwin-x64 190 MB ┐
codex/linux-arm64 208 MB ├─ 620 MB of dead weight
codex/linux-x64 222 MB ┘
```
## Changes
**Progress reporting.** The response is streamed and reported on a 250
ms interval: `Downloading... 42% (142.0 MB / 338.0 MB)`. The total comes
from the release asset's `size` (newly decoded — the field was being
dropped), falling back to `content-length`, and falling back again to a
plain byte count so an unknown size degrades instead of failing.
**Half the payload.** Each archive now carries real bytes only for the
`codex-acp` binary its own platform can execute.
The other three paths cannot simply be dropped — that is exactly the
break #4186 just repaired. A CLI released before 2026-08-18 verifies a
downloaded package against all four codex-acp paths and refuses one
missing any of them. So they ship as **empty placeholders**: the
existence check passes at zero bytes, and since no host ever executes a
foreign codex-acp, the placeholder is never read. Once no supported
client performs that check, placeholders become plain omissions —
`archiveCompanionEntries` is where that switch lives.
As a guard, codex adapter resolution now requires a non-empty file, so a
zero-byte binary resolves as absent and falls through to the existing
bundled → PATH → npx chain rather than trying to exec it.
Expected effect: download 338 MB → ~165 MB, install footprint 967 MB →
~347 MB.
## Verification
- Full CLI suite: **122 files, 1262 passed, 1 skipped**
- `pnpm --filter @composio/cli typecheck` — clean
- The existing `upgrade-binary` download tests run against a real HTTP
server and pass unchanged, covering the buffered → streamed rewrite
- New tests: progress formatting (known total, unknown total, zero
total, overshoot) and `archiveCompanionEntries` (all four paths named,
exactly one copied, three placeholdered, portable assets copied)
- `pnpm validate:changesets` — passes; note lands in
`ts/packages/cli/CHANGELOG.md`
Not verifiable locally: actual archive sizes and a real upgrade against
a pre-2026-08-18 client. Both need a beta build — worth confirming on
the beta cut from this branch before it goes near a stable promotion.
Independent of the `0.4.0` release in flight; `0.4.0-beta.359` is
unaffected.
https://claude.ai/code/session_01JkwtxPHfobZxzvAqe53x62
## Problem
`composio upgrade` fails on every CLI currently in the field, including
stable `0.3.3`:
```
💥 services/UpgradeBinaryError • Downloaded binary package is incomplete
Caused by: Missing companion module: …/extract/composio-darwin-aarch64/acp-adapters/codex/darwin-x64/codex-acp
```
`archiveCompanionRelativePaths` (added 2026-08-18 in #4134) narrows each
release archive to the shared ACP assets plus only the one `codex-acp`
its platform can execute. That is a sound optimisation, but it shipped
writer-first: a CLI released *before* it verifies a downloaded package
against `RUN_COMPANION_STATIC_ASSET_RELATIVE_PATHS` — shared assets plus
**all four** codex target paths — with no parameter to relax the check,
and hard-fails on any archive missing one.
Stable `0.3.3` shipped 2026-08-11, a week before that change, so the
entire installed stable base is affected. Recovery today means
re-running `install.sh` by hand.
Evidence:
| Archive | codex binaries shipped |
| --- | --- |
| `0.3.4-beta.351` (pre-#4134) | `darwin-arm64`, `darwin-x64`,
`linux-arm64`, `linux-x64` |
| `0.4.0-beta.357` (post-#4134) | `darwin-arm64` only |
## Fix
The reader has to become tolerant before the writer narrows, and the
already-installed reader cannot be patched retroactively. Packaging
ships the full companion set again.
`archiveCompanionRelativePaths` stays in place with its tests,
documented as deliberately uncalled. Re-wiring it into
`package-binaries.ts` is a one-line change once no supported client
still validates all four paths — worth roughly 651 MB per archive.
## Why CI missed it
`cli.test-installation.yml` only exercises fresh `install.sh` installs,
which are unaffected: each archive is internally consistent. Nothing
covers an in-place upgrade from a previously released binary. Worth
closing separately — it needs a real prior-stable binary in the matrix,
not a unit test.
## Verification
- `vitest run test/src/scripts/release-artifacts.test.ts` — 29 passed
- `pnpm --filter @composio/cli typecheck` — clean
- `pnpm validate:changesets` — passes (CLI is Changesets-ignored; note
lands in `ts/packages/cli/CHANGELOG.md`)
- Added coverage asserting every release artifact's codex-acp binary is
in the packaged set
- Final check is the archive itself: the beta cut from this branch must
contain all four `acp-adapters/codex/*/codex-acp` entries, and `composio
upgrade` must succeed from a pre-#4134 install
`@composio/cli@0.4.0-beta.357` should be abandoned rather than promoted.
https://claude.ai/code/session_01JkwtxPHfobZxzvAqe53x62
Bumps the mise-pinned Bun toolchain from 1.3.10 to 1.4.0 and replaces
the one CLI dependency that a Bun 1.4 built-in can verifiably take over.
## Binary size: Linux shrinks a lot, macOS grows a little
Measured per target, byte counts from `build:binary:all` on a
darwin-arm64 host.
| Target | Before (1.3.10) | After runtime (1.4.0) | After full | Δ
total | Δ % |
|---|---:|---:|---:|---:|---:|
| `composio-darwin-aarch64` | 80,850,704 (77.1 MiB) | 83,790,962 (79.9
MiB) | 83,790,962 (79.9 MiB) | +2,940,258 (+2.8 MiB) | +3.6% |
| `composio-darwin-x64` | 85,710,240 (81.7 MiB) | 90,430,880 (86.2 MiB)
| 90,430,880 (86.2 MiB) | +4,720,640 (+4.5 MiB) | +5.5% |
| `composio-linux-x64` | 123,666,298 (117.9 MiB) | 102,270,152 (97.5
MiB) | 102,270,152 (97.5 MiB) | -21,396,146 (-20.4 MiB) | -17.3% |
| `composio-linux-aarch64` | 121,153,270 (115.5 MiB) | 102,221,816 (97.5
MiB) | 102,221,816 (97.5 MiB) | -18,931,454 (-18.1 MiB) | -15.6% |
**Attribution — read this before quoting the numbers.** Every byte of
movement above comes from the **Bun runtime bump**, not from dependency
removal. The "after runtime" and "after full" columns are
byte-identical: the only dependency dropped here is `tar`, a
devDependency used by one build script that never reaches the binary.
Its size contribution is exactly **0 bytes**. (The identical columns
also confirm the compiled build is reproducible across runs.)
Linux users — the large majority of installs — get a ~18-20 MiB smaller
binary. macOS grows 2.8-4.5 MiB. This matches the direction upstream
reports for the standalone Bun binary.
## What changed
- `mise.toml` pins `bun = "1.4.0"`; `mise.lock` regenerated with the
exact platform list `ts.audit` uses.
- `scripts/_acp-adapters.ts` extracts npm tarballs with `Bun.Archive`
instead of the `tar` package.
- `tar` dropped from `@composio/cli` devDependencies (plus
`@isaacs/fs-minipass`, `chownr`, `minizlib`, `yallist` from the
lockfile).
## Verified negative results
These are the two adjacent candidates a reviewer would expect to see
replaced. Both were probed against a real Bun 1.4.0 binary and both fail
— recorded here so nobody re-derives the dead ends:
- **`extract-zip` stays.** `Bun.Archive` cannot read zip: `new
Bun.Archive(zipBytes)` throws `Unrecognized archive format`, and
`ArchiveOptions.compress` accepts only `"gzip"`. Still used at three
call sites.
- **`semver` stays.** `Object.keys(Bun.semver)` returns exactly
`["satisfies", "order"]`. The CLI also needs `valid`, `prerelease`,
`compare`, `gt`, and `lt`. `valid` and `prerelease` have no equivalent,
so a partial migration would only add a second semver dialect.
## `json5` → `Bun.JSON5` was attempted and backed out
`parse-json.ts` is covered by the CLI's Vitest suite, which runs on
**Node**, where the `Bun` global does not exist — `Bun.JSON5.parse`
throws `ReferenceError` under test. The suite cannot move to the Bun
runtime (88 of 122 files fail there on unrelated zod resolution errors),
and `bun test` for a single file would conflict with the repo's
`@effect/vitest` lint rule.
The swap itself is sound — `Bun.JSON5.parse` matched the `json5` package
on all nine contract cases against a real 1.4.0 binary, including
`SyntaxError` on malformed input. It is the test harness, not the
parser, that blocks it. Deferred rather than shipped with weakened
coverage.
For sizing the follow-up: `--metafile-md` puts `json5` at **28,045 bytes
(0.1%)** of the JS bundle, imported only by `src/utils/parse-json.ts` —
roughly 0.03% of a compiled binary. Worth doing for dependency-surface
reasons, not for size.
## Verification
- All four release targets cross-compile on Bun 1.4.0.
- `mise lock --platform linux-x64,linux-arm64,macos-arm64,macos-x64`
then `git diff --exit-code mise.lock` is clean, replayed in a CI-like
environment.
- `pnpm typecheck` clean; CLI suite green (122 files, 1248 passed, 1
skipped).
- `Bun.Archive` adapter build against the live npm registry produces
codex-acp binaries **byte-identical** (SHA-256) to the `tar`-produced
ones, at the same `package/bin/<name>` paths, executable after `chmod`,
extracted concurrently. A truncated tarball throws `ReadError` rather
than silently yielding an empty directory.
- Runtime smoke on the 1.4.0 binary: `composio version`, `composio
--help`, and the `composio run` companion-module spawn path (reports
`process.version` v26.3.0 — no Node 26 stream regression). `extract-zip`
verified working under the new runtime.
### Not run locally
`pnpm test:e2e:cli` needs Docker, which was unavailable on this machine.
CI covers it. Worth a look at that job: the e2e image is version-keyed
and has served a stale Bun binary from a cached layer before, so confirm
the container reports 1.4.0.
## Notes
- `@types/bun` is deliberately not bumped: `Bun.JSON5` and `Bun.Archive`
are already declared in the installed `bun-types@1.3.14`, no
`@types/bun` 1.4.x exists yet, and `minimumReleaseAge` would block a
fresh pin anyway.
- No changeset: `@composio/cli` is in `.changeset/config.json`'s
`ignore` list and no published package is touched.
- `mise lock` locally adds a stray `[[tools.node]] 24.19.0` block
sourced from the developer's global mise config. It was stripped; the
committed lock is stable under the audit gate's exact command.
This PR:
- routes Composio-prefixed runtime configuration through `APP_CONFIG`
and normalizes unprefixed host values through `HOST_CONFIG` in
`app-config.ts`
- removes `loadOptionalAppConfig`-style fallback loading so optional
strings, booleans, and CLI flag precedence resolve at the configuration
boundary
- removes every executable `process.env` reference from CLI source;
child commands inherit the ambient environment through
`@effect/platform` and receive explicit normalized overrides
- preserves arbitrary `CODEX_*`, `CLAUDE_*`, and `OPENCLAW_*` detection
through Effect config enumeration without exposing the raw environment
map
- propagates telemetry debug state through worker arguments instead of
mutating the process environment
- replaces removable filesystem, OS, subprocess, and error-handling
exceptions with Effect services and typed control flow
- documents supported and internal CLI environment variables, including
their `user_data.json` and `config.json` mappings
- reduces registered CLI lint boundaries from 45 to 4; the retained
entries are the detached-spawn, Node OS, synchronous preload filesystem,
and MD5 checksum implementations
- verifies the result with 1,201 passing CLI tests (1 skipped), strict
Oxlint, boundary validation, root typechecking across 19 packages, the
CLI build, and real `composio run` child-process checks
Resolving a tool slug to its toolkit needs the catalog, but the catalog
is ~800 KB of metadata to learn ~11 KB of slugs. Check the slugs in as
generated source so the CLI starts out knowing them.
Adds the generator (paginates the production catalog, keeps native
toolkits, sorts and dedupes), the checked-in list, a guard test, and a
weekly workflow that opens a refresh PR when the catalog moves. The
generator refuses to write a list that is short, malformed, or missing
staple toolkits, so a bad or wrong-scoped credential aborts before
overwriting a good list. The binary build warns when the list is older
than two weeks, and never fails on it.
Nothing reads the list yet.
This PR:
- fixes https://github.com/ComposioHQ/composio/issues/3932
- replaces the private CLI package semver with the non-release
`0.0.0-development` sentinel
- injects the exact GitHub release tag version into every standalone
binary and verifies it during the build
- makes every push to `next` a beta, with explicit semver selection for
intentional minor or major betas and stable releases only through beta
promotion
- resolves skill installation, setup repair, companion repair, and
upgrades from packaged `release-tag.txt` metadata
- adds regression coverage for release selection, compiled version
identity, and packaged-tag asset lookup; all 1,009 CLI tests and the
monorepo typecheck pass
- updates the direct CLI changelog and release guidance; no Changeset is
added because CLI packages are excluded from Changesets
This PR:
- fixes
https://github.com/ComposioHQ/composio/actions/runs/30535159056/job/90850055191
by keeping checksum generation independent of unbuilt CLI runtime
packages
- extracts the shared Effect teardown into a dependency-light module
while preserving existing script imports
- adds an executable release regression that generates a checksum
manifest from a clean fixture
- verifies the fix with `pnpm test:release-workflow`, `pnpm
build:packages`, CLI typecheck, the full CLI test suite, and `pnpm
validate:changesets`
Teach non-interactive login to reuse an existing READY agent identity without creating one implicitly. Preserve explicit --no-browser and --no-wait contracts, and branch on TerminalUI.canPrompt so piping stdout alone remains interactive.
Add unattended guidance, installer analytics attribution, and focused unit and Docker E2E coverage. Exclude host node_modules from Docker build contexts.
This PR:
- replaces ESLint with oxlint across the pnpm workspace and the
Bun-based docs site, porting the rules to `.oxlintrc.json` /
`docs/.oxlintrc.json` with behavior parity (restricted-syntax selectors
kept via `oxlint-plugin-eslint`)
- migrates typecheck to TypeScript 7 (`typescript@^7.0.2` catalog) and
keeps a TS6 pin for JS compiler API consumers via a named `ts6` pnpm
catalog (`ts/scripts/validate-examples.ts`, the `@composio/cli` generate
pipeline). The CLI's `typescript` dependency rebinds only the
compiler-API import — its typecheck still runs the root TS7 `tsc`, since
the alias package only ships a `tsc6` bin (documented in
`ts/packages/cli/AGENTS.md`)
- removes the `paths` mappings that pointed `@composio/core` (and, in
`experimental`, `@composio/json-schema-to-zod` plus core-internal
`#`-imports) at sibling `src` directories: under TS7, tsdown's
tsgo-based dts step emitted stray `.d.ts` files next to those
out-of-root sources on every dependent package build. Workspace deps now
resolve through their built dist types, which turbo's `dependsOn:
^build` already guarantees exist — and which the deep-path exports
(`@composio/core/*`) always used anyway
- renames the cli boundary tooling `eslint-boundaries*` →
`lint-boundaries*` and hardens the scanner to reject `oxlint-disable`
spellings so the disable manifest cannot be bypassed
- rewrites inline `eslint-disable` comments to oxlint rule names
(comment-only; no runtime changes), and adds **one new** declared
boundary: `tool-file-uploads.ts` needs `no-restricted-imports` disabled
for `node:crypto` (MD5 for the presigned-upload checksum is not in Web
Crypto), because oxlint also catches dynamic `await import()` where
ESLint did not. The manifest grows 46 → 47 deliberately
- updates CI path filters, `turbo.jsonc` lint inputs, and the docs
typescript-check workflow (renamed to "Docs - Lint and TypeScript
Validation" since it now lints too); drops `eslint`,
`typescript-eslint`, `eslint-config-next`, and `globals` from the
dependency graphs
- ships no changeset: I built `@composio/core` and `@composio/anthropic`
on this branch and on the pre-migration base and diffed the emitted
`dist/**/*.d.mts`. The provider output is byte-identical. Core's output
is **semantically identical but not byte-identical**: TS7 changes quote
style (`"x"` → `'x'`), object-property and union-member ordering in
inferred types, and picks equivalent shorter re-export alias paths for
five signatures (e.g. `OpenAI.Beta.Threads.Runs.Run` →
`OpenAI.Beta.Threads.Run` — verified both names alias the same type in
the shipped typings). Chunk-name hashes shift as a consequence. No type
gains, losses, or shape changes; `attw` and `publint` pass on the TS7
build
## Context
First of a three-PR split of #3958. The type-safety refactors are
stacked on this branch and merge after it:
- docs: https://github.com/ComposioHQ/composio/pull/3967
- `@composio/core`: https://github.com/ComposioHQ/composio/pull/3968
PostHog's own term for the public write-only phc_* credential is the
project API key; the old name read like a secret. Covers the env var,
the build-time bake define, the baked constant, and the workflow env.
The GitHub repo variable itself must be renamed manually.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Revert the gratuitous restructuring of the three binary build scripts. The
earlier version pulled `'bun'` out of the args array and dropped
`as const satisfies ReadonlyArray<string>` to work around a typecheck error —
but a variadic tuple (`['bun', ...posthogBakeArgs(), ...] as const`) keeps its
first element known, so `Command.make(...args)` still typechecks. Each script's
diff is now just the `posthogBakeArgs` import plus the one inserted spread.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review feedback (KJ):
- Strip the added explanatory comments across dispatch.ts, constants.ts,
_shared.ts, build-binary.ts and the workflow; keep only pre-existing ones.
- Shorten the CHANGELOG entry to a single line.
- Revert the .gitignore addition.
Bugbot findings:
- Already-authenticated installs never stitched (events stayed anonymous after
upgrade, since only `login` persisted the id). Backfill now runs from any
command that already resolves a session: whoami, init, connected-accounts
link, plus the existing login paths.
- `composio login --agent` skipped the stitch; the agent branch now resolves
session info best-effort and links.
- `composio logout` left `apollo_user_id` behind, so later events kept
attributing to the previous person. Added clearApolloIdentityForAnalytics.
- A failed alias was never retried, because any persisted `apollo_user_id`
counted as "already aliased" — including when nothing was ever enqueued (no
project key / telemetry off). Track `aliased_apollo_user_id` separately and
only record it once the enqueue actually happened.
Tests: alias retry after a skipped enqueue, and logout reverting to install_id.
Full suite 956 passed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hygiene pass on the direct-to-PostHog telemetry: condense verbose block
comments in dispatch.ts/constants.ts.
Source the public write-only PostHog project key from a build-time
COMPOSIO_POSTHOG_KEY env var, baked into the binary via `bun build --define`
(scripts/_shared.ts posthogBakeArgs), instead of a committed source literal.
This mirrors the dashboard's env-driven NEXT_PUBLIC_POSTHOG_TOKEN pattern and,
for this OSS repo, keeps the key out of public git history and out of fork/local
builds (they compile a no-op binary). `--define` is used rather than a second
`--env` because Bun honors only one `--env` and it would clobber the existing
DEBUG_OVERRIDE_* inline. CI passes the key as an Actions variable on the
cross-compile step; empty -> telemetry no-ops.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This PR:
- activates the final rule group: `TryStatement` and `process.env` are
now ESLint-banned in CLI source, completing the enforcement ramp started
in the first PR of this stack; the env guard covers dot access, bracket
access, and object destructuring
- migrates the residual files (auth-config create, trigger create,
toolkit search, runtime debug flags, master detection, import-time UI
setup) off try/catch and ad-hoc env reads
- every surviving violation sits at a declared runtime boundary (bin.ts
bootstrap, child-process companion runtime, import-time UI setup,
environment writes and whole-environment enumeration, spawn-time env
handshakes) with an inline `// eslint-disable-next-line <rule> --
<reason>` justification
- adds `eslint-boundaries.json` — the checked-in manifest of the 46
sanctioned disables across 22 files — and `validate:boundaries` (part of
`pnpm test`), which scans both `.ts` and `.tsx` sources and fails on
undeclared, missing, relocated, bare, or file-wide disables
- pins each registered boundary by rule, justification, and governed
next-line target, with regression coverage for TSX discovery, same-file
retargeting, and duplicate semantic sites
- documents the Effect Boundary Policy in the CLI `AGENTS.md` and the
`cli-command` skill reference, and drops the gitleaks test-file
allowlist
---
**Stack** (re-slice of https://github.com/ComposioHQ/composio/pull/3859;
each PR targets its parent and auto-retargets to `next` as parents
merge):
1. https://github.com/ComposioHQ/composio/pull/3877 — guidelines + inert
rule groups
2. https://github.com/ComposioHQ/composio/pull/3878 — `new Function()`
eval security fix
3. https://github.com/ComposioHQ/composio/pull/3879 — behavioral fix
pack
4. https://github.com/ComposioHQ/composio/pull/3880 — platform-imports
rule + migration
5. https://github.com/ComposioHQ/composio/pull/3881 — terminal-streams
rule + TerminalUI boundary
6. https://github.com/ComposioHQ/composio/pull/3882 — descriptor seam +
zod→Schema
7. https://github.com/ComposioHQ/composio/pull/3883 — test-tree lint +
deterministic suites
8. https://github.com/ComposioHQ/composio/pull/3884 — typed error
boundaries + v4 seams
9. https://github.com/ComposioHQ/composio/pull/3885 — try/catch+env ban
+ boundary ratchet ← **this PR**
On stacked bases CI runs lint/build and the CLI Docker e2e job; unit
tests and typecheck are verified locally per PR and re-verified by full
CI when each PR is retargeted to `next`.
This PR:
- converts every remaining thunk-form `Effect.tryPromise` in CLI source
to a purpose-named `Data.TaggedError` preserving its cause —
`UnknownException` no longer surfaces from `src/` — and switches
best-effort recoveries from `catchAll` to `catchTag`
- isolates the `Symbol.for('effect/SpanAnnotation')` internal read
behind a shape-validating adapter, with a canary test that fails a real
effect through the runtime so an `effect` upgrade that drops the
mechanism breaks CI instead of silently losing span timelines
- decodes trigger-log payloads once at the API boundary through a
tolerant schema documenting camelCase/snake_case/meta-nested alias
precedence
- deduplicates the per-entry tolerant decoders into
`utils/collect-decoded-entries.ts`, replaces locally re-declared record
schemas with `JsonRecordSchema`, deletes the unused `EnvLangDetector`
service, and removes the temporary sync bridge from the platform-imports
slice
- the largest PR of the stack by design: generic refactors land late so
the fix and rule slices before it stay small; one commit per sub-theme
keeps `git show` reviewable
---
**Stack** (re-slice of https://github.com/ComposioHQ/composio/pull/3859;
each PR targets its parent and auto-retargets to `next` as parents
merge):
1. https://github.com/ComposioHQ/composio/pull/3877 — guidelines + inert
rule groups
2. https://github.com/ComposioHQ/composio/pull/3878 — `new Function()`
eval security fix
3. https://github.com/ComposioHQ/composio/pull/3879 — behavioral fix
pack
4. https://github.com/ComposioHQ/composio/pull/3880 — platform-imports
rule + migration
5. https://github.com/ComposioHQ/composio/pull/3881 — terminal-streams
rule + TerminalUI boundary
6. https://github.com/ComposioHQ/composio/pull/3882 — descriptor seam +
zod→Schema
7. https://github.com/ComposioHQ/composio/pull/3883 — test-tree lint +
deterministic suites
8. https://github.com/ComposioHQ/composio/pull/3884 — typed error
boundaries + v4 seams ← **this PR**
9. https://github.com/ComposioHQ/composio/pull/3885 — try/catch+env ban
+ boundary ratchet
On stacked bases CI runs lint/build and the CLI Docker e2e job; unit
tests and typecheck are verified locally per PR and re-verified by full
CI when each PR is retargeted to `next`.
This PR:
- activates the platform-imports rule group: `node:fs`, `node:path`,
`node:os`, and `child_process` are now ESLint-banned in CLI source
- migrates ~36 files to `FileSystem`/`Path`/`Command` from
`@effect/platform`, introducing the `NodeOs` and `DetachedProcess`
service boundaries and Effect-native run-companion module resolution
- keeps the sanctioned permanent boundaries (`node-os.ts`,
`detached-process.ts`, `run-subagent-output-mcp.ts`,
`cli-user-config.ts`, the child-process companion runtime) on inline `--
reason` disables
- files whose compliant rewrite belongs to a later slice carry temporary
inline disables naming the owning PR; a small sync bridge in
`run-companion-modules.ts` keeps the not-yet-migrated Promise-based
callers working until the typed-error slice removes it
- adds A-theme coverage: `NodeOs` platform info through Effect, session
artifacts via `FileSystem` with symlink and HOME-less handling,
skill-root discovery, and safe-output-path traversal guards
---
**Stack** (re-slice of https://github.com/ComposioHQ/composio/pull/3859;
each PR targets its parent and auto-retargets to `next` as parents
merge):
1. https://github.com/ComposioHQ/composio/pull/3877 — guidelines + inert
rule groups
2. https://github.com/ComposioHQ/composio/pull/3878 — `new Function()`
eval security fix
3. https://github.com/ComposioHQ/composio/pull/3879 — behavioral fix
pack
4. https://github.com/ComposioHQ/composio/pull/3880 — platform-imports
rule + migration ← **this PR**
5. https://github.com/ComposioHQ/composio/pull/3881 — terminal-streams
rule + TerminalUI boundary
6. https://github.com/ComposioHQ/composio/pull/3882 — descriptor seam +
zod→Schema
7. https://github.com/ComposioHQ/composio/pull/3883 — test-tree lint +
deterministic suites
8. https://github.com/ComposioHQ/composio/pull/3884 — typed error
boundaries + v4 seams
9. https://github.com/ComposioHQ/composio/pull/3885 — try/catch+env ban
+ boundary ratchet
On stacked bases CI runs lint/build and the CLI Docker e2e job; unit
tests and typecheck are verified locally per PR and re-verified by full
CI when each PR is retargeted to `next`.
## Review follow-up
- `DetachedProcess` now waits for Node’s `spawn` or `error` event, so
ENOENT/EACCES become typed failures instead of false success; focused
tests cover failure and success.
- the platform-import rule now rejects bare `fs`, `fs/*`, `os`, and
`path` specifiers as well as their `node:` forms; the two exposed path
imports now use Effect `Path`.
- run-companion self-repair again honors unprefixed `GITHUB_*` values
first, with `COMPOSIO_GITHUB_*` fallback and regression coverage for
both contracts.
Verification: CLI tests (95 files, 834 passed, 1 skipped), workspace
TypeScript typecheck, scoped ESLint (0 errors), CLI build, Prettier, and
`git diff --check`.
This PR:
- replaces `decompress` (unmaintained; the zip-slip fix in the GHSA
advisory was never published to npm past 4.2.1) with `extract-zip`
across the CLI's four zip-extraction call sites: `install-skill.ts`,
`run-companion-modules.ts`, `upgrade-binary.ts`, and
`cli-local-tools/bundled-binaries.ts`
- `extract-zip` validates each entry resolves inside the target
directory before writing, closing the path-traversal issue `pnpm audit`
flags as critical
- replaces the one `.tgz`-extracting call site
(`scripts/_acp-adapters.ts`, used to vendor ACP adapter binaries at
build time) with `tar`, since `extract-zip` only handles zip archives
- removes `@types/decompress`; both `extract-zip` and `tar` ship their
own type definitions
- `pnpm audit --prod --audit-level=high` now passes (previously failing
on `next`, unrelated to #3766)
Verified `extract-zip` and `tar` extract nested directories correctly
with a local smoke test (real `.zip`/`.tgz` archives), in addition to
the existing `@composio/cli` (724 tests) and `@composio/cli-local-tools`
(13 tests) suites passing.
## Summary
- bump generated TS client to @composio/client 0.1.0-alpha.69 and Python
client to composio-client 1.36.0
- page through ToolRouter session tools in TS/Python using the generated
v3.1 cursor response
- accept generated connected account status REVOKED and fail connection
waits immediately for terminal states
## Validation
- pnpm --filter @composio/core typecheck
- pnpm --filter @composio/core test -- test/tools/tools.test.ts
test/models/toolRouter.test.ts
test/connectedAccounts/connectedAccounts.test.ts
test/connectedAccounts/connectionRequest.test.ts
- uv run --frozen ruff check python/composio/core/models/tools.py
python/tests/test_tool_execution.py
- uv run --frozen pytest
python/tests/test_tool_execution.py::TestToolExecution::test_get_raw_tool_router_meta_tools_fetches_all_pages
python/tests/test_tool_router.py
Note: pnpm install --frozen-lockfile hits the repo preinstall Bun guard
locally because this machine has Bun 1.2.10 and the branch expects
1.3.10; dependency sync was completed with --ignore-scripts for local
verification.
## Summary
- Broaden the Beeper iMessage macOS build patch so BetterSwiftAX
`kAX...` constants compile on GitHub `macos-15`/`macos-15-intel`.
- Pin the fixed `platform-imessage` submodule source and add Swift 6.2 /
Peekaboo dependency patching for the CLI binary workflow.
- Package and verify macOS local-tool sidecars plus `release-tag.txt` in
CLI release zips.
- Fix installed beta metadata/upgrade behavior so `--version`, update
checks, and beta-default experimental flags use the installed release
tag.
- Let `LOCAL_*` execution bypass remote auth/project/schema validation.
- Add runtime self-heal for missing installed `local-tools-binaries`: if
an old upgrader installs the fixed beta binary without sidecars, first
local-tool execution downloads the matching release zip, verifies
checksum when available, and restores the sidecars.
## Validation
- `pnpm --filter @composio/cli-local-tools build:beeper-imessage --
--target darwin-arm64`
- `pnpm --filter @composio/cli-local-tools build:beeper-imessage --
--target darwin-x64`
- `pnpm --filter @composio/cli-local-tools build:peekaboo -- --target
darwin-arm64`
- `pnpm --filter @composio/cli-local-tools build:peekaboo -- --target
darwin-x64`
- `pnpm --filter @composio/cli-local-tools typecheck:tsc`
- `pnpm --filter @composio/cli-local-tools test`
- `pnpm --filter @composio/cli typecheck:tsc`
- `pnpm --filter @composio/cli build:binary`
- Targeted CLI tests for execute/config/upgrade/version/update-check
paths.
- Packaged binary smoke test confirmed bundled Beeper sidecar works.
- Repair smoke test: copied only the new `composio` binary plus
`release-tag.txt` into a temp install with no `local-tools-binaries`;
`execute LOCAL_BEEPER_IMESSAGE_VERSION -d '{}'` restored sidecars from
`@composio/cli@0.2.29-beta.235` and succeeded.
## Release workflow
- Beta build run `25405049712` succeeded for commit
`9d0910c909b7b257d0f17b6d082980952d1e6c59` and published
`@composio/cli@0.2.29-beta.235`.
- This PR now includes one follow-up commit (`2c32cff4c`) to cover the
old-upgrader/missing-sidecars incremental upgrade path; normal branch CI
and beta build run `25406984535` are running again.
## Summary
- Add experimental CLI local tools behind `local_tools` (beta-on,
stable-off unless `composio config experimental local_tools on`).
- Add reusable `@composio/cli-local-tools` package: declarations,
metadata, readiness, command/MCP/native/FFI runtimes, bundled-binary
resolution, and Tool Router search/execute/schema integration.
- Add first-class local toolkits for:
- `BEEPER_IMESSAGE` backed by `imessage-cli` from the ComposioHQ
`platform-imessage` fork.
- `CHROME_DEVTOOLS` backed by the official `chrome-devtools-mcp@0.24.0`
npm/npx package.
- `PEEKABOO` backed by upstream Peekaboo CLI.
- Remove generated native executables from git: Beeper and Peekaboo
binaries are now ignored, pinned via git submodules, and generated
during CLI binary release jobs.
- Update CLI binary workflow so Linux artifacts skip native sidecars,
while macOS artifacts run on macOS runners and build only the matching
`darwin-x64` or `darwin-arm64` Beeper/Peekaboo sidecars before
packaging.
## Native binary policy
- No generated `imessage-cli` or `peekaboo` binary blobs are committed
in this PR history.
- Beeper source is pinned as
`ts/packages/cli-local-tools/vendor/platform-imessage` at
`364445a1b3089ad9fe293d5951efe160c5677c42` from
`https://github.com/ComposioHQ/platform-imessage`.
- Peekaboo source is pinned as
`ts/packages/cli-local-tools/vendor/peekaboo` at
`31e66e8d02656141d18f60bf3b46b24c2b9bc785` from
`https://github.com/steipete/Peekaboo`.
- Build commands:
- `pnpm --filter @composio/cli-local-tools build:local-tool-binaries --
--target darwin-arm64`
- `pnpm --filter @composio/cli-local-tools build:local-tool-binaries --
--target darwin-x64`
- Chrome DevTools is an npm/npx integration and is pinned as a dev
dependency (`chrome-devtools-mcp@0.24.0`) instead of using native
sidecars.
## Validation
- `pnpm --filter @composio/cli-local-tools build:local-tool-binaries --
--target darwin-arm64`
- `pnpm --filter @composio/cli-local-tools build:peekaboo -- --target
darwin-x64`
- `pnpm --filter @composio/cli-local-tools build:beeper-imessage --
--target darwin-x64`
- `pnpm --filter @composio/cli-local-tools typecheck:tsc`
- `pnpm --filter @composio/cli-local-tools test`
- `COMPOSIO_REAL_LOCAL_TOOLS_TESTS=1 pnpm --filter
@composio/cli-local-tools test -- src/toolkits/beeper-imessage.test.ts
src/toolkits/peekaboo.test.ts`
- `pnpm --filter @composio/cli typecheck:tsc`
- `pnpm --filter @composio/cli build`
- `COMPOSIO_CACHE_DIR=<tmp-config-with-local_tools-enabled> bun
ts/packages/cli/dist/bin.mjs local-tools doctor --json`
- `pnpm turbo build`
- Verified rewritten branch has no >1MB objects relative to
`origin/next` and no native executable paths in the PR diff.
## Notes / risks
- Beeper iMessage and Peekaboo are macOS-only and depend on local
permissions.
- Peekaboo requires macOS 15+; GUI tools require Screen Recording,
Accessibility, and sometimes Automation.
- Beeper send/reaction behavior can still depend on upstream Messages
automation reliability.
- Chrome DevTools can inspect/modify browser contents; avoid sensitive
browser sessions.
## Summary
- Add a generated `composio-cli` skill source that can render stable and
beta variants from a single channel-aware definition.
- Introduce build and validation scripts to generate the skill output
and verify channel-specific content, references, and reproducibility.
- Update the CLI packaging workflow to validate skills and package the
correct release-channel build for beta vs stable releases.
- Expand the skill content with clearer top-level CLI guidance,
troubleshooting, developer-project workflows, and beta-only power-user
examples.
- Tighten CLI install/upgrade behavior and add tests covering skill
installation behavior.
- Add example validation to the repo test flow and align example package
metadata with workspace expectations.
## Testing
- Not run locally.
- Added `ts/packages/cli/scripts/validate-skills.ts` checks for
stable/beta markers, channel-specific content, and required reference
files.
- Added `ts/packages/cli/test/src/effects/install-skill.test.ts`
coverage for skill installation behavior.
- Added `ts/scripts/validate-examples.ts` to validate example package
manifests during `pnpm test`.
- CI workflow now runs `pnpm run validate:skills` before packaging CLI
skill files.
This PR:
- fixes the stale beta version expectation in `upgrade-binary.test.ts`
(\`0.2.18\` → \`0.2.19\`) that broke the "selects the latest prerelease"
test
- replaces live \`composio generate ts\` call in the
\`typescript-mjs-import-nodenext\` e2e suite with checked-in fixture
files, removing the \`COMPOSIO_API_KEY\` dependency
- adds \`mock-toolkits-server.ts\` — a deterministic mock HTTP server
for \`/api/v3/toolkits\` and \`/api/v3/toolkits/:slug\` endpoints
- migrates \`toolkits/list\`, \`toolkits/info\`, and \`toolkits/search\`
CLI e2e suites from live API calls to the mock server, removing the
\`COMPOSIO_USER_API_KEY\` requirement
- adds \`--add-host host.docker.internal:host-gateway\` to Docker e2e
runner so CLI containers can reach host-side mock servers
- closes
[PLEN-2012](https://linear.app/composio/issue/PLEN-2012/cli-fix-cli-e2e-tests)
All three failures are pre-existing on \`next\` — this PR makes CI green
again.
## Testing
```bash
pnpm --dir ts/packages/cli exec vitest run test/src/services/upgrade-binary.test.ts
pnpm typecheck
pnpm --dir ts/e2e-tests/_utils typecheck
pnpm --filter @e2e-tests/cli-toolkits-info typecheck
pnpm --filter @e2e-tests/cli-toolkits-list typecheck
pnpm --filter @e2e-tests/cli-toolkits-search typecheck
```
> **Stack:** 1/2 — followed by #3099 (org switch limit display feature)
---------
Co-authored-by: jkomyno <12381818+jkomyno@users.noreply.github.com>
Co-authored-by: Rahul Tarak <cryogenicplanet@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- bundle the shipped `composio run` companion services with direct
`Bun.build(..., target: "bun")` output instead of reusing the shared
`dist` graph
- rebuild the Claude ACP support files as Bun-bundled runtime assets and
invalidate the cached adapter layout so stale raw files are not reused
- add runtime validation for shipped support files, wire the MCP helper
through the workspace `@composio/json-schema-to-zod` package, and cover
the static-import expectation in tests
## Why
Standalone binaries were still relying on external runtime dependencies
from companion support files. On a clean machine this surfaced as
failures like `Cannot find package 'decompress'` from the generated
companion modules. The fix is to make every shipped support file
self-contained for Bun and package exactly that tree into the binary
archives.
## Validation
- `pnpm run typecheck`
- `pnpm exec vitest run
test/src/services/run-subagent-output-mcp.test.ts
test/src/services/run-subagent-acp.test.ts`
- `pnpm run build:binary:all`
- `pnpm run build:binary:package`
- unpacked `dist/binaries/composio-darwin-aarch64.zip` and verified
`experimental_subAgent(..., { target: "codex", schema: ... })`
- unpacked `dist/binaries/composio-darwin-aarch64.zip` and verified
`experimental_subAgent(..., { target: "claude", schema: ... })`
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- replace runtime MCP SDK path resolution with static imports in the
structured-output helper
- ensure the helper works when shipped next to the standalone CLI binary
without repo-local node_modules
## Verification
- pnpm --filter @composio/cli run typecheck:src
- pnpm --filter @composio/cli test
test/src/services/run-subagent-acp.test.ts
- built and executed the bundled helper from a temp directory outside
the repo
## What changed
- make `build:binary:cross` emit the `run-subagent-*.mjs` companion
modules alongside the compiled CLI binary
- update the `Build CLI Binaries` workflow to include those companion
modules in the published release archives
- make `install.sh` copy companion modules when they are present, while
remaining backward compatible with older archives that only contain
`composio`
- fix the CLI installation workflow assertions to match the actual
installer behavior and paths
## Why
`composio run` launches a separate Bun runtime that imports the
`run-subagent-*` helpers from disk. The main binary alone is not
sufficient. The previous release workflow zipped only the `composio`
binary, so prerelease assets installed successfully but failed at
runtime with missing-module errors.
The installation test workflow also had stale expectations for
`~/.composio/bin/composio` and `COMPOSIO_INSTALL`, which caused false
negatives even when installation itself succeeded.
## Impact
- newly built CLI release assets will contain the files required for
`composio run`
- `install.sh` will install sidecars for new releases and ignore them
for older releases
- the installation workflow will validate the real install layout
instead of the stale `bin/` path
## Validation
- `pnpm --filter @composio/cli run build:binary:cross --target
bun-darwin-arm64` from the existing checkout emitted:
- `dist/binaries/composio-darwin-aarch64`
- `dist/binaries/companions/run-subagent-shared.mjs`
- `dist/binaries/companions/run-subagent-acp.mjs`
- `dist/binaries/companions/run-subagent-legacy.mjs`
- simulated the GitHub Actions archive step and verified the zip
contains `composio` plus all three companion modules
- earlier local binary/package validation on the main fix branch
confirmed the extracted binary runs `composio run
'console.log("hello")'` successfully once those files are packaged
## Summary
- Adds a new ACP execution path for `subAgent()` in the CLI `run`
command, with fallback to the legacy CLI-based implementation when ACP
is unavailable.
- Introduces shared subagent helpers plus separate ACP and legacy
service modules to keep the invocation logic isolated.
- Adds `--acp-only` to force ACP usage and fail instead of falling back.
- Updates binary build output so the CLI ships the companion modules
needed by the `run` command in both source and compiled forms.
- Bumps CLI dependencies to include ACP packages used by the new
execution path.
## Testing
- `pnpm test ts/packages/cli/test/src/commands/run.cmd.test.ts`
- `pnpm test ts/packages/cli/test/src/services/run-subagent-acp.test.ts`
- Not run: full repository build or end-to-end CLI validation.
- Only test binaries when target is `bun-linux-x64` since ARM64 binaries
can't execute on the x64 CI runner.
- Extract duplicated `teardown` function from 8 scripts into
`scripts/_shared.ts`.
- Fix `build-binary.ts` silent exit on failure (Effect.logInfo →
Effect.fail), matching the fix already applied to build-binary-cross.
- Add missing `pnpm install --frozen-lockfile` to the release CI job so
`generate-checksums.ts` resolves `catalog:` versions from the lockfile
instead of Bun auto-installing `latest` from npm.
- Replace `Effect.logInfo` with `Effect.fail` in `build-binary-cross.ts`
so a failed `bun build` propagates a non-zero exit code instead of
silently succeeding.
- Add cross-compilation scripts (build-binary-cross.ts, build-all-binaries.ts)
using Bun's --target flag, enabling all platforms to build from ubuntu-latest
- Add package-binaries.ts and generate-checksums.ts for release artifact preparation
- Restructure CI workflow into build + release jobs; release job aggregates
artifacts and generates checksums.txt
- Simplify install.sh: use git ls-remote refspec filter for version detection,
add SHA-256 checksum verification with graceful fallback, use mktemp/trap
for temp file cleanup, remove dead musl detection code
- Add checksum verification to composio upgrade command via fetchChecksums
and verifyChecksum helpers in upgrade-binary.ts
Add a recording infrastructure that produces SVG and asciicast demos
from a declarative YAML config. Supports dynamic height auto-sizing,
parallel execution, and progress reporting via Clack UI.