## Summary
[PRDE-1153](https://linear.app/composio/issue/PRDE-1153) adds a small
acquisition hint when the bare CLI is running inside Claude Code or
Codex and the Composio plugin is not installed in that host:
```text
Tip: running under Claude Code without the Composio plugin — 'composio setup' installs it.
```
The hint is written only to stderr, including in non-TTY shells, because
agent tool calls commonly capture stderr. It never changes stdout or
command results.
## When the hint appears
All of the following must be true:
- The CLI detects Claude Code via `CLAUDECODE`, or Codex via
`CODEX_THREAD_ID` / `CODEX_SANDBOX`.
- The host's plugin state confidently shows that `composio@composio` is
absent.
- A hint has not been shown for that host within the last 24 hours.
- The current command is not `composio setup`, including when root flags
precede the command.
- The invocation is not a child of `composio run`.
Unreadable or unrecognized plugin state suppresses the hint rather than
risking a false positive.
## Host state and throttling
- Claude Code presence is read from
`~/.claude/plugins/installed_plugins.json`.
- Codex presence is read from `~/.codex/config.toml`.
- `CLAUDE_CONFIG_DIR` and `CODEX_HOME` overrides are honored; blank
overrides fall back to the standard paths.
- Per-host throttle stamps live under `<COMPOSIO_CACHE_DIR or
~/.composio>/plugin-hints/`.
The throttle is best-effort rather than a correctness boundary. Two
processes racing exactly as a stale stamp is replaced may both print the
same tip; the only consequence is a duplicate advisory line.
## Implementation notes
- Detection and presence checks use local environment variables and
small local files only—there is no network request or background worker.
- Shared agent-host names, labels, and the plugin ID are centralized in
`agent-host.ts` and reused by the existing setup flow.
- This PR covers plugin acquisition only. Plugin freshness and CLI
update messaging remain separate concerns.
## Verification
- `plugin-hint.test.ts`: 15 passing tests covering host detection,
plugin presence, suppression rules, per-host throttling, custom/blank
host paths, root flags, concurrency, and non-TTY stderr.
- CLI source typecheck: passed.
- CLI test typecheck: passed.
- Changed-file oxlint and `git diff --check`: passed.
**Stacked on #3927** (A1 — direct-to-PostHog + install→Apollo identity).
Targets that branch; will auto-retarget to `next` when #3927 merges.
Review only this diff.
## What
Makes every CLI event self-describe its funnel stage, so the adoption
funnel can be queried without string-matching event names — which is how
it silently broke in the first place.
- **`journey_stage`** on every event: `install | setup | login | connect
| execute | other`. Declared as an exported typed const plus a single
exhaustive map, `as const satisfies Record<CliAnalyticsEventName,
CliJourneyStage>` — so **the compiler refuses to build if a future event
has no stage**. No per-event literals; stamped in one shared builder.
- **`cli_channel`** alongside `cli_version`, reusing the existing
`inferSkillReleaseChannel()` / `CLI_RELEASE_CHANNELS`. Makes "did this
fix reach stable users?" answerable — the question that went unanswered
in the 0.2.30 assetless-release incident.
- **Installer origin fix:** `install.sh` ran `"$exe" install` *without*
`COMPOSIO_CLI_INVOCATION_ORIGIN=installer` (the `setup` call on line 410
had it), so a genuine install was indistinguishable from a user running
`composio install` by hand. Now tagged, with a regression test that
reads `install.sh` and asserts it.
## Stage mapping (reviewed against 30d volume)
`install` = `CLI_INSTALL_*` · `setup` = `CLI_SETUP_*` + `CLI_PLUGIN_*` ·
`login` = `CLI_LOGIN_*` · `connect` = `CLI_LINK_*` · `execute` =
`CLI_EXECUTE_*` + `CLI_TOOL_INVOCATION_*` · `other` = `CLI_COMMAND_*`,
`CLI_SEARCH_*`, `CLI_PROXY_*`, `CLI_RUN_*`, `CLI_LOGOUT_*`
Judgment calls, made with data rather than by default:
- **`proxy` → `other`.** 2,060 of 2,140 proxy users (96%) already
execute; only 80 are proxy-only. Reclassifying would move the activated
cohort ~1%, so `execute` stays precisely "tool execution".
- **`run` → `other`.** `run` children emit their own execute events
carrying `parent_run_id`; staging the parent as `execute` would
double-count.
- **`search` → `other`.** Not a required funnel stage. Candidate for a
"discovery" step later if the flow page wants one.
## Note for whoever builds the flow page
`CLI_TOOL_INVOCATION_*` and `CLI_EXECUTE_FAILED` can both fire for a
single failure, so the `execute` stage **double-counts at the event
level**. Count **distinct users per stage**, not events.
## Known coverage limit
npm and Homebrew installs don't run `install.sh`, so they emit no
`CLI_INSTALL_*`. The `install` stage means "installed via install.sh",
not all installs.
## Verification
`pnpm typecheck` clean · `validate:boundaries` OK (46 disables, **zero
added**) · CLI suite **107 files / 971 passed** (+15 tests) ·
`dispatch.ts` identity/transport untouched.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## What
Sends CLI telemetry **directly to PostHog** (project 196278) instead of
through Apollo/Segment, and stitches the anonymous install identity to
the Apollo user at login. This unlocks the previously-dark top of the
CLI adoption funnel (install → setup → login → connect → execute).
### Why
Two live funnel breaks in PostHog today:
1. **Install/setup/plugin events were dark.** Pre-login, `dispatch.ts`
had no API base URL (→ endpoint null → dropped), and Apollo's ingest
401s anonymous requests. So `CLI_INSTALL_*`/`CLI_SETUP_*` never arrived.
2. **Identity split.** CLI/server events landed on *email*-keyed PostHog
persons (via Segment); dashboard onboarding on *UUID*-keyed persons —
the two never joined.
The CLI already knows the canonical Apollo UUID (`org_member.id` from
session info), so it can self-stitch with no platform/dashboard change.
## How
- **Direct transport.** New PostHog capture path (`captureToPostHog`)
reusing the existing detached best-effort worker. No dependency on the
API base URL, so **pre-login events send**.
- **Identity.** Pre-login `distinct_id = install_id`; at login
`linkApolloIdentityForAnalytics(org_member.id)` persists the UUID to
`~/.composio/analytics.json` and fires one `$create_alias` (`install_id
→ org_member.id`); post-login events key on the persisted
`apollo_user_id`. Because onboarding is already UUID-keyed, the CLI
funnel now joins web onboarding.
- **Public key, baked at build.** The write-only `phc_` project key is
injected via `bun build --define` from the `COMPOSIO_POSTHOG_KEY` env
(CI Actions **variable**), never committed to source. `--define` (not a
second `--env`) is deliberate — Bun honors only the last `--env`, which
would clobber the existing `DEBUG_OVERRIDE_*` bake. For this OSS repo
this keeps the key out of git history and means **forks / local builds
compile a no-op binary** (only official releases carry the key).
- **Direct-only:** the Apollo `/cli/analytics` send is dropped for CLI
events; the CLI attaches its own `org_id` (project_id is per-session; a
follow-up).
## Guards
No-op (no send, no worker spawn, no identity-file write) when telemetry
is disabled
(`COMPOSIO_CLI_TELEMETRY_DISABLED`/`TELEMETRY_DISABLED`/`COMPOSIO_DISABLE_TELEMETRY`/`CI`/`NODE_ENV=test`)
or when no project key is configured. Alias fires once per install
(idempotent). No user API key or tool-arg values in event properties.
## Verification
- `pnpm typecheck`, `validate:boundaries`, full CLI vitest (**954 passed
/ 1 skipped**) — green.
- Independent code review pass; findings addressed (spawn-gated-on-key,
disabled=no-file, idempotent alias).
- **Live cold-install trace:** built the real compiled binary with the
key baked, ran it from a throwaway `$HOME` → fresh `install_id` → 2
pre-login events delivered to `us.i.posthog.com` with **HTTP 200** →
confirmed queryable in PostHog 196278 within ~10s, keyed by
`install_id`.
## Notes
- CLI is Changesets-ignored; human note added to `CHANGELOG.md`
directly.
- Requires the `COMPOSIO_POSTHOG_KEY` Actions variable to be set for
official release builds (done).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
Automated docs update triggered by SDK source changes on `next`.
- Claude reviewed the SDK diff and updated guides, FAQs, or examples
that reference changed APIs or features.
- The docs `@composio/*` dependencies were realigned to their latest
published releases so Twoslash snippets and example apps validate
against versions users can actually install.
## Review checklist
- [ ] Changes accurately reflect the new SDK behavior
- [ ] No unrelated docs were modified
- [ ] Code examples are correct and complete
- [ ] If a documented feature is not published yet, the Twoslash build
will fail — wait for the release instead of working around it
Generated by Claude Code via GitHub Actions.
Co-authored-by: jkomyno <12381818+jkomyno@users.noreply.github.com>
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`
## What
Restores the two docs-prose skills that were dropped from the skill
tree:
- `good-docs-writing` — the house documentation style guide (Voice,
Structure, Terminology, Punctuation, Code examples, Formatting), for
drafting or revising docs prose.
- `good-docs-audit` — the review process that audits a doc/README/prose
block against that guide and reports `file:line` findings with concrete
rewrites. Report-only by default.
## Why
Both existed at `d17a268d` under `.claude/skills/` and were deleted in
#3666 (`chore(agents): normalize repo guidance skills`), which renamed
the rest of the tree into the current taxonomy but did not carry these
two over. Nothing replaced them: there is no docs-voice guidance in the
repo today, and `docs-decisions` covers docs-site mechanics (Fumadocs,
changelogs, ADRs), not prose style.
## Shape of the restore
Rule content is restored unchanged from `d17a268d`. Only the file layout
differs, because the old flat single-file form no longer passes
`validate:agent-skills` (SKILL.md is now capped at 80 lines and a linked
`references/` directory is required):
```
.agents/skills/good-docs-writing/SKILL.md # routing + the rules that matter most
.agents/skills/good-docs-writing/references/style-guide.md
.agents/skills/good-docs-audit/SKILL.md # routing + non-negotiables
.agents/skills/good-docs-audit/references/audit-process.md
```
They live under `.agents/skills` (canonical); `.claude/skills` is a
symlink, so there is no second copy.
Wiring, all three places the taxonomy is asserted:
- `ts/scripts/validate-agent-skills.mjs` — added to the `expectedSkills`
gate
- `ts/scripts/test-skill-routing.mjs` — one routing probe each (the
validator fails on any skill without a probe)
- `AGENTS.md` — added to the Skill Routing list
## Test results
- `node ts/scripts/test-skill-routing.mjs` — passes, 18 probes over 18
skills. Both new probes resolve to a unique top match.
- `node ts/scripts/validate-agent-skills.mjs` — zero findings against
tracked files.
- `pnpm lint-staged` — no staged file matches a configured task
(patterns cover `ts/packages/**` and `python/**`).
- Markdown formatted with the repo Prettier config.
Two notes on how those were run. `pnpm validate:*` could not be used
locally: pnpm's pre-run dependency check tries to purge and reinstall
the workspace and aborts without a TTY, so the scripts were invoked
directly with `node` (same entrypoints the pnpm scripts use).
Separately, `validate-agent-skills` reports stale-guidance hits under
`docs/.eve/dev-runtime/snapshots/**` on my machine; those are untracked,
gitignored local eve snapshots, unrelated to this change, and won't
exist in CI. The commit used `--no-verify` because the pre-commit hook
is just the `pnpm lint-staged` wrapper that hits the same pnpm abort;
lint-staged was run manually instead.
No changeset: guidance and tooling only, no published package touched.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to next, this PR will
be updated.
# Releases
## @composio/core@0.14.1
### Patch Changes
- 577a3d4: Replace the backtracking leading/trailing-slash-trim regexes
in the Cloudflare Workers/Edge platform path helpers with index-walk
loops, closing a polynomial-time regular expression denial-of-service
(CodeQL js/polynomial-redos) on long runs of slash characters. Output is
unchanged for every input.
- 503b50a: Refresh runtime dependencies across the TypeScript SDK
packages.
- 2f63fe5: Guard Tool Router session URL uploads against SSRF,
revalidate redirect targets, and enforce a streamed 100 MiB response
limit across TypeScript URL upload paths.
## @composio/experimental@0.2.1
### Patch Changes
- 503b50a: Refresh runtime dependencies across the TypeScript SDK
packages.
## @composio/mastra@0.10.3
### Patch Changes
- 503b50a: Refresh runtime dependencies across the TypeScript SDK
packages.
## @composio/slim@0.14.1
### Patch Changes
- 503b50a: Refresh runtime dependencies across the TypeScript SDK
packages.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This PR:
- prepares Python SDK core and provider packages for `0.18.1`, including
runtime and lockfile metadata
- adds the canonical combined changelog for Python `0.18.1` and the
TypeScript releases tracked by
https://github.com/ComposioHQ/composio/pull/3906
- documents `@composio/core` `0.14.1` so the generated release PR passes
the release-workflow guard
- refreshes `mise.lock` so the TypeScript audit workflow reaches the
dependency audit
- keeps the pending TypeScript Changesets untouched; the generated
release PR remains responsible for npm versioning and publication
- validates Python with Ruff/mypy, 944 tests, all 13 package builds, and
`twine check`
- validates TypeScript/docs with the full 26-task `pnpm test`,
high-severity production audit, 100 docs static tests, link checks, docs
typecheck, and production build
## Summary
Auto-generated Python SDK reference docs from `python/composio/`.
Regenerates pages at `docs/content/reference/sdk-reference/python/` to
reflect changes in the Python package's public API (new methods, updated
signatures, changed types).
Co-authored-by: jkomyno <12381818+jkomyno@users.noreply.github.com>
## Summary
- add an experimental guide for registering customer-hosted MCP servers
- document supported authentication, the registration and sync flow,
toolkit behavior, and customer-facing workarounds for known gaps
- add the guide to the Extending sessions navigation and cross-link it
from the sessions-over-MCP guide
## Why
Custom MCP toolkits now have a working platform lifecycle, but customers
need one place that clearly distinguishes remote MCP servers from
in-process custom tools. The guide also makes the current pilot
limitations explicit so customers know which API version, sync flow,
account selection, and hosting model to use.
## Validation
- `cd docs && bun run lint:links`
- `cd docs && bun run types:check`
- `git diff --check`
Docs-only change, so no changeset is required.
When the bare CLI runs inside a plugin-capable agent host (Claude Code,
Codex) and the Composio plugin is not installed there, print one
throttled stderr tip pointing at 'composio setup'. Deliberately visible
in non-TTY shells: the primary audience is the agent driving the CLI.
Host detection reads CLAUDECODE / CODEX_THREAD_ID / CODEX_SANDBOX under
their raw names (bypassing the COMPOSIO_-prefixing ConfigProvider).
Plugin presence comes from cheap host state reads: Claude Code's
installed_plugins.json and Codex's config.toml plugin section. Throttle
state lives in its own ~/.composio/plugin-hint.json to avoid colliding
with the update-check state file #3961 is rewriting.
Suppressed when: no host marker, plugin installed (or state unreadable),
shown within 24h, or COMPOSIO_CLI_INVOCATION_ORIGIN=run.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This PR:
- fixes a regression introduced by
https://github.com/ComposioHQ/composio/pull/3956: fumadocs-openapi 11's
`groupBy: 'tag'` silently skips operations whose tag is not declared in
the document's top-level `tags` array, which 404'd all 16 Projects and
Organization Management operation pages (e.g.
`/reference/api-reference/projects/postProjectUsageSummary`) on both
v3.1 and v3, and dropped them from the sitemap and search index
- adds `declareOperationTags()` (`docs/lib/openapi-tags.ts`), applied at
spec load time in `lib/openapi.ts` (covers build-time-fetched specs) and
at sync time in `scripts/fetch-openapi.mjs`, which now also warns when
the upstream payload omits tags; the checked-in specs are normalized
accordingly (purely additive)
- adds CI guards in `tests/static/api-reference-routes.test.ts`: spec
invariants (every visible operation has a tag and `operationId`),
bidirectional spec-vs-generated-routes set equality through the
production loader path, a negative test pinning fumadocs' silent-drop
behavior (fails when upstream fixes it, signaling the workaround can be
retired), and validation that every `ApiEndpointsTable` quick-link href
resolves to a generated page
- extends `Docs - Check Links` with a nightly (02:30 UTC) + manual
external-URL sweep via a new `lint:links:external` script; the validator
only fails on evidence a link is dead (404/410 or repeated network
errors, with UA/timeout/GET-fallback/retry and per-URL caching) and
scheduled failures file a deduplicated tracking issue; PR runs keep the
fast internal-only check
- fixes six dead external links the first sweep found (moved Claude
Agent SDK docs, stale dashboard settings URL ×2, a `master`-branch path
now pinned to tag `0.5.0+post.1`, and two removed `ComposioHQ` example
repos whose mentions were dropped — their code is embedded in the pages
via `RepoBrowser`)
## Context
fumadocs-openapi 10 generated a page for any tag string found on an
operation; v11 requires the tag to be declared top-level and skips
silently otherwise (`preset-auto.js`: `builder.fromTagName(tag)` →
`continue`, no warning). The backend spec generator omits `Projects`,
`Organization Management`, and `Invite Codes` from `tags`, so their
operation pages vanished while the checked-in MDX tag landing pages kept
rendering with dead quick links. With the normalizer, the generated URL
set is byte-identical to the pre-#3956 set (234 routes, verified via
`getReferenceSource().getPages()` diff); no revert needed.
Existing checks missed this because `lint:links` only extracts markdown
links and `Card` hrefs (the dead links live in `ApiEndpointsTable`'s
array prop) and validates against the same loader that shrank, and the
integration suite samples fixed routes under tags that survived. The new
completeness guard derives expectations from the specs themselves, so
routine data syncs don't churn it.
## What
Closes the PRDE-1138 gap: an unattended agent hitting plain `composio
login` in a pipe dead-ended at browser OAuth. Now the default headless
path either completes unattended or tells the agent exactly what to run
— without ever auto-creating an account for a human.
- **Offer**: non-interactive login instructions gain a second hint —
"For unattended agents: run `composio login --agent`" — alongside the
existing URL + `composio login --poll` flow.
- **Perform (reuse only)**: when `~/.composio/agent.json` already holds
a READY agent identity, plain headless `composio login` completes
unattended by reusing it. New `getStoredReadyAgent` in
`services/agents.ts` is the reuse-only counterpart of
`getOrSignupReadyAgent` — it never falls back to signup.
- **Guardrail** (the design constraint from the ticket): account
creation stays exclusively behind the explicit `composio login --agent`
/ `composio signup` commands. A human piping `composio login` with no
stored agent identity gets the same URL instructions as before and no
account. Asserted at both unit and E2E level (`/api/signup` is never
called on the default path).
- `install.sh --agent` login now sets
`COMPOSIO_CLI_INVOCATION_ORIGIN=installer` for analytics attribution.
- Root `.dockerignore`: host `node_modules` (pnpm store symlinks that
break outside the host) no longer enter the e2e image build context;
without this, e2e images cannot build from a checkout that has run `pnpm
install`.
## Verification
- `pnpm typecheck` green; `@composio/cli` suite green — 1001 passed, 1
skipped; `validate:boundaries` clean.
- New Docker E2E suite `ts/e2e-tests/cli/agent-signin` (10/10) against a
mock `agents.composio.dev` (`COMPOSIO_AGENTS_BASE_URL`): unattended
nothing→authenticated (`login --agent` then `whoami` in one container),
headless-human guardrail (instructions printed, zero signup calls),
stored-identity reuse (login completes + whoami reports `account_type:
agent`). No real accounts are created.
## Notes
- No VHS recordings: the visible change is piped-mode text output, which
VHS interactive recordings don't demonstrate.
- No changeset by design (`@composio/cli` is Changesets-ignored);
human-facing note added to `ts/packages/cli/CHANGELOG.md` under 0.3.0.
getStoredReadyAgent collapsed every whoami failure into Option.none via
Effect.option and fell back to the on-disk identity, so a revoked agent
key (HTTP 401/403) still completed headless login. Auth rejections now
return no agent; only transport-shaped failures keep the offline
fallback.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A root .dockerignore excluding **/node_modules broke Dockerfile.node's
runtime fixtures: suites without a setup phase (claude-agent-sdk) resolve
deps through node_modules copied in via COPY ts/e2e-tests/. BuildKit's
per-Dockerfile ignore keeps the exclusion for Dockerfile.cli, which
installs inside the image and must not see host pnpm symlinks.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
## What
Removes npm and Homebrew as Composio CLI install channels. `curl -fsSL
.../install.sh | bash` is now the only supported channel (plus manual
zip / from-source).
Channel decommission decision: KJ, 2026-07-27. Tickets: PRDE-1155 (npm),
PRDE-1156 (brew).
## Changes
- **INSTALL.md** — removed the npm/pnpm/yarn install section; Windows
guidance is now explicitly WSL
- **install.sh** — Windows error path no longer advises `npm install -g
@composio/cli` (dead channel); points to WSL
- **.github/workflows/build-cli-binaries.yml** — generated per-release
INSTALL.md no longer includes an npm section; comment no longer lists
Homebrew as a release consumer
- **.github/workflows/cli.install-health-check.yml** — dropped the stale
comment describing an npm dist-tag publish flow that no longer exists
- **.github/workflows/cli.test-installation.yml** — deleted the
`test-npm-fallback` job (a no-op that only checked `npm --version`) and
its `toolchain-versions` feeder job; pruned summary references
- **.github/workflows/cli.bump-homebrew-tap.yml** +
**.github/scripts/bump-homebrew-formula.py** — deleted. This automation
never fired reliably: releases are published with `GITHUB_TOKEN`, which
suppresses `release`-triggered workflows, and `HOMEBREW_TAP_TOKEN` is
dead (root cause recorded on PRDE-1156). Removal loses nothing.
- **ts/packages/cli/package.json** — dropped the unused `publishConfig`
block (package stays `private: true`)
- **.agents/skills/cli-release/** + **ts/packages/cli/AGENTS.md** —
removed Homebrew steps from release docs
- **toolchain-versions.json** — dropped `node_install_compat`, whose
only consumer was the deleted npm-fallback job
## Deliberately untouched
- SDK npm packages (`@composio/core` etc.) — only the CLI channel dies
- Historical CHANGELOG entries mentioning npm
- `brew install mise` / `brew install steipete/tap/peekaboo` —
third-party tools, unrelated to the CLI channel
## Cross-repo
Companion PR on the Homebrew tap repo replaces the formula with a
deprecation stub that migrates existing brew users (0.2.28) to the curl
installer.
## Verification
- `bash -n install.sh`
- `test/install-sh-release-resolution.test.sh` passes locally
- YAML/JSON parse checks on all edited workflow/manifest files
- grep sweeps: zero remaining user-facing npm/brew CLI-install
references
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This PR:
- follows up https://github.com/ComposioHQ/composio/pull/3943, replacing
its hardcoded message with a fix for the cause it worked around
- stops `install.sh` redirecting `composio install`'s stderr to a temp
file — that redirect is what silenced the command, since the CLI gates
every log, note and outro on stderr being a terminal, so the captured
file was always empty and the replay printed nothing
- probes `"$exe" --version` before delegating, so a binary that cannot
run still falls back to inline setup without spilling loader errors —
the reason the redirect existed in the first place
- makes `composio install` fall back to plain `ui.error` lines when
there is nothing to decorate, so container and CI installs that pipe the
session to a build log still get the report; interactive output is
unchanged. `canDecorate` is constant for a run, so each channel binds to
its decorated or plain form once rather than re-testing per message
- drops the unconditional "Composio was added to your PATH" line, which
printed on three paths where nothing was written: shell-not-detected and
unsafe-install-dir (both exit 0 after reporting manual setup), and the
inline fallback's unsupported-shell and unwritable-rc branches
- adds regression tests using the production `makeTerminalUI`
implementation with captured streams, so the real decoration gate is
exercised — the shared test double reports `canDecorate: false` but
prints everything anyway, which is why this went unnoticed through two
prior attempts
## Context
Measured against the released binary, `composio install` writes 0 bytes
when its stderr is not a terminal, and exits 0 without touching any rc
file when `$SHELL` is unset. Both were invisible to the installer:
| case | exit | stderr bytes | PATH block written |
| --- | --- | --- | --- |
| `2>file`, as `install.sh` did | 0 | 0 | yes |
| `$SHELL` unset | 0 | 0 | no |
| stderr on a terminal | 0 | full report | yes |
With the redirect gone, the delegated path prints what the user was
missing — `Updated ~/.zshrc` and `Restart your shell to apply changes` /
`source ~/.zshrc` — and the manual-setup text on the paths where PATH
genuinely was not touched. The closing block no longer needs a PATH
claim of its own, and the fallback keeps printing its own
`refresh_command`.
067c67b695 already tried to surface this
output by capturing it to a temp file and replaying it on success. That
replay has been a no-op for the same reason, so this guidance has never
reached a user since the delegation was introduced.
## How Has This Been Tested?
- new tests fail with `expected '' to contain 'PATH: will add'` (empty
output — the production bug) without the `install.cmd.ts` change, and
pass with it
- full CLI suite: 957 passed, 1 skipped; `pnpm typecheck` 14/14;
`validate:boundaries`, eslint and prettier clean, no new eslint disables
- released binary in a sandboxed `$HOME`: stderr to a file yields 0
bytes; stderr on a pty yields the full report
- CLI from source with stderr captured: 155 bytes of plain guidance
where it previously wrote nothing; decorated output on a terminal
unchanged
- `install.sh` driven through a harness built from the real script under
a pty: a working binary's stderr reaches the terminal, a broken binary's
loader noise stays suppressed and the fallback writes the PATH block and
prints `source ~/.zshrc`. The same harness against `next` shows the
swallow.
No changeset: `@composio/cli` is Changesets-ignored and `install.sh` is
not a published package. The CLI note went into `CHANGELOG.md` directly.
`install.sh` is served from `next`, so the installer half of this
reaches new installs on merge and works with already-released binaries.
The `install.cmd.ts` half only affects captured-stderr installs and
rides the next CLI release.
This PR:
- restores TypeDoc generation after
https://github.com/ComposioHQ/composio/pull/3966 by resolving
`@composio/core`'s TypeScript dev dependency from `catalog:ts6`
- keeps core typechecking on the root TypeScript 7 compiler while
TypeDoc receives the TS6 compiler API
- documents the additional compiler-API consumer in the shared
TypeScript catalog
- commits the regenerated `session-files.mdx` output that could not be
produced while the workflow was broken
- verifies `generate:docs`, `typecheck`, and `build` for
`@composio/core`
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.