Commit Graph

5111 Commits

Author SHA1 Message Date
Anshu Garg cb5dc62478 docs(auth): generate the connected-accounts index (section on v3.1 and v3)
Ran generate:api-index instead of hand-editing. The one shared overview feeds
both version pages, so the OAuth connection security section now renders on the
v3.1 and v3 connected-accounts reference (chosen over a hand-edit the generator
would undo). Generator output is byte-identical to the prior hand-mirror on v3.1;
no other tags changed.
2026-07-30 18:57:13 +05:30
Anshu Garg 82558047d8 docs(auth): v3.1-only section, correct status_reason value, honest changelog
- complete_auth is a v3.1-only endpoint (no v3 route), so drop the OAuth
  connection security section from the v3 connected-accounts index; keep it on v3.1.
- status_reason on mismatch is the enum VALUE 'Callback identity verification
  failed', not the key IDENTITY_VERIFICATION_FAILED. Fix both files.
- Changelog no longer claims Composio universally 'stops' the attack. It ships
  two controls: same-browser binding (automatic on managed) and opt-in callback
  identity verification.
2026-07-30 18:41:44 +05:30
Anshu Garg 33cfc964f5 docs(auth): humanize changelog (skill) + correct the complete_auth state machine
Changelog: run through good-docs-writing — remove every em-dash, drop the salesy
'most reliable way', plainer confident voice.

connected-accounts overview + both index files: correct the completion outcomes.
Per completeFromSession, only an identity mismatch fails the connection (FAILED +
status_reason IDENTITY_VERIFICATION_FAILED); any other error leaves it pending so
the flow can be restarted; the session_uri is consumed either way. The old text
read as if the connection always moved to FAILED.
2026-07-30 18:33:44 +05:30
Anshu Garg 6d8a25af1d docs(auth): move OAuth connection security into the connected-accounts reference
Drop the standalone /docs/oauth-connection-security page and its nav entry. The
content now lives as a section in the connected-accounts API overview
(api-overviews/connected-accounts.mdx), next to the complete_auth endpoint it
documents, in that overview's house style.

- Add the section (same-browser binding + callback identity verification) to the
  overview and mirror it into both generated index.mdx files (v3.1 + v3). The
  index generator's deps don't resolve in this worktree, so the mirror is manual;
  it matches what generate:api-index would emit from the updated overview.
- Repoint the changelog and the agent concept map at
  /reference/api-reference/connected-accounts#...
- Fix a stale concept-map claim: identity verification is opt-in per project and
  covers every connection once set, not custom-auth-config-only.
2026-07-30 18:26:13 +05:30
Alberto Schiabel 7c5e22c3ce fix(cli): unblock release checksum generation (#3990)
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`
@composio/cli@0.2.33-beta.322 @composio/cli@0.2.33
2026-07-30 18:15:21 +05:30
Anshu Garg d9b7ec54b7 docs(auth): OAuth connection security page (good-docs-writing voice)
Skill-guided rewrite of the OAuth connection security page: direct second-person
voice, no em-dashes, concept-first sentences, no salesy comparatives.

Also corrects four accuracy issues found while verifying against the Apollo code
(these exist in the sibling PR too):
- the ten-minute figure is the session_uri TTL, not a connection-expiry;
- verification covers API + Connect Link redirects, not marketplace-install
  acknowledgements (which return before the verifier fork);
- save-time validation is https + SSRF (private/reserved), not a reachability test;
- the rejection message has no trailing period.
2026-07-30 18:13:50 +05:30
Rahul Tarak d7b6e7eb30 chore(agents): restore good-docs-writing and good-docs-audit skills (#3991)
## 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>
2026-07-30 05:31:33 -07:00
sdkrelease[bot] fdbd44f9eb Release: update version (#3906)
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>
@composio/mastra@0.10.3 @composio/core@0.14.1 @composio/experimental@0.2.1 @composio/slim@0.14.1 py@0.18.1
2026-07-30 16:25:33 +05:30
Alberto Schiabel 0ae443bece chore(sdk): prepare Python 0.18.1 and TypeScript 0.14.1 releases (#3988)
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
2026-07-30 16:03:55 +05:30
sdkrelease[bot] 264d7dc9ee docs: update Python SDK reference from source (#3965)
## 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>
2026-07-30 15:23:50 +05:30
Kshitij Jhunjhunwala 1a943dd384 Merge next into plugin hint 2026-07-29 19:26:00 -07:00
Kshitij Jhunjhunwala 52071ed5a0 fix(cli): resolve selected-org analytics identity 2026-07-29 19:23:46 -07:00
Kshitij Jhunjhunwala e0d184ede2 Merge PR 3927 fixes into telemetry taxonomy 2026-07-29 19:07:29 -07:00
Kshitij Jhunjhunwala d00a3b5576 fix(cli): keep analytics identity in sync with auth 2026-07-29 19:04:35 -07:00
Soumya Medapati 6b81b404f5 docs: make toolkit-version requirement explicit in direct-execution samples
97-agent docs eval: 72/97 agents hit ToolVersionRequiredError copying
version-less tools.execute() samples. Adds an explicit requirement
callout, uses 'latest' with a lookup pointer instead of a hardcoded
GitHub-only pin, adds versions to all file-handling samples, fixes the
LLM guardrails block's version-less signature, and states the Python
3.10+ requirement in the quickstart.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 18:51:43 -07:00
Kshitij Jhunjhunwala 4bdbaecc10 fix(cli): simplify analytics identity dispatch 2026-07-29 18:07:02 -07:00
Kshitij Jhunjhunwala af772565f7 fix(cli): simplify and harden plugin hints 2026-07-29 18:05:31 -07:00
Kshitij Jhunjhunwala 53a4e7ca46 fix(cli): preserve configured analytics channel 2026-07-29 16:36:37 -07:00
Kshitij Jhunjhunwala 0f37be91e5 fix(cli): key identity stitch throttle by credential 2026-07-29 16:36:33 -07:00
shams haroon 2cfdd90680 docs: document Custom MCP (#3975)
## 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.
2026-07-29 16:07:45 -07:00
Kshitij Jhunjhunwala 87236ff642 fix(cli): configure telemetry before invocation 2026-07-29 16:07:34 -07:00
Kshitij Jhunjhunwala ce2c3a4024 fix(cli): wait for analytics state locks 2026-07-29 16:07:26 -07:00
Kshitij Jhunjhunwala 24626db522 chore: refresh mise lock metadata 2026-07-29 15:47:21 -07:00
Kshitij Jhunjhunwala 5ab7dbbcc3 fix(cli): throttle plugin hints per host 2026-07-29 15:43:24 -07:00
Kshitij Jhunjhunwala 6d90bb3a1c fix(cli): report installed release channel 2026-07-29 15:43:07 -07:00
Kshitij Jhunjhunwala 2be90d765f fix(cli): serialize analytics identity state 2026-07-29 15:42:14 -07:00
Kshitij Jhunjhunwala 90087b0b94 chore: refresh mise lock metadata 2026-07-29 15:13:21 -07:00
Kshitij Jhunjhunwala 4bfae41c7a Merge remote-tracking branch 'origin/claude/cli-adoption-funnel-d95660' into codex/pr3928
# Conflicts:
#	ts/packages/cli/CHANGELOG.md
2026-07-29 15:12:32 -07:00
Kshitij Jhunjhunwala 9bfe6e3610 feat(cli): agent-aware plugin acquisition hint (PRDE-1153)
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>
2026-07-29 12:19:52 -07:00
Alberto Schiabel 3335bb3013 fix(docs): restore API reference pages dropped by undeclared tags (#3973)
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.
2026-07-29 03:05:43 +05:30
Kshitij Jhunjhunwala bf87709d92 Merge remote-tracking branch 'origin/next' into claude/cli-adoption-funnel-d95660
# Conflicts:
#	ts/packages/cli/CHANGELOG.md
#	ts/packages/cli/test/src/commands/login.cmd.test.ts
2026-07-28 13:52:31 -07:00
Kshitij Jhunjhunwala fc9745040a feat(cli): make headless composio login agent-friendly (PRDE-1138) (#3945)
## 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.
2026-07-28 13:48:28 -07:00
Kshitij Jhunjhunwala 0c6b09df19 fix(cli): never reuse a stored agent identity the agents API rejected
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>
2026-07-28 13:33:28 -07:00
Kshitij Jhunjhunwala 14011b9057 fix(e2e): scope node_modules dockerignore to the CLI image only
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>
2026-07-28 13:21:49 -07:00
Kshitij Jhunjhunwala 0b182a3c0f Merge remote-tracking branch 'origin/claude/cli-adoption-funnel-d95660' into claude/posthog-a2-taxonomy
# Conflicts:
#	install.sh
#	ts/packages/cli/src/analytics/events.ts
2026-07-28 12:08:10 -07:00
Kshitij Jhunjhunwala 9aa3e4b1c6 Merge branch 'next' into claude/cli-adoption-funnel-d95660 2026-07-28 12:01:10 -07:00
Kshitij Jhunjhunwala fab1790b50 chore(cli): decommission npm + Homebrew install channels (PRDE-1155, PRDE-1156) (#3960)
## 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)
2026-07-28 11:55:05 -07:00
Abhishek Patil 11686484d1 [codex] restore Security and Data docs (#3720) 2026-07-28 22:10:28 +05:30
jkomyno 6725d1c078 Merge branch 'next' into kj/decommission-npm-brew 2026-07-28 22:05:06 +05:30
Alberto Schiabel 27706a5081 fix(install): stop swallowing the CLI's PATH guidance (#3951)
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.
2026-07-28 21:40:48 +05:30
jkomyno c5c3203db6 fix(install): prioritize Windows platform guidance 2026-07-28 21:25:11 +05:30
jkomyno fa0b8f7c1c fix(cli): align generated Windows install guidance 2026-07-28 21:17:39 +05:30
jkomyno 6dc77c987d fix(cli): preserve release bundle in manual installs 2026-07-28 21:17:34 +05:30
Alberto Schiabel 2b9571b17f fix(core): resolve typedoc against the TS6 compiler API (#3972)
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`
2026-07-28 21:03:06 +05:30
Kshitij Jhunjhunwala fc1460995b feat(cli): make headless composio login agent-friendly (PRDE-1138)
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.
2026-07-28 20:13:57 +05:30
Checo a3f6b9c8f2 fix(py/triggers): swallow malformed chunked frame instead of tearing down subscription (#3892)
## Problem

TriggerSubscription._handle_chunked_events is bound directly as a Pysher
channel callback. Pysher channel dispatch has no local exception
boundary, so malformed chunk frames reached websocket-client error
handling and marked the realtime connection failed. The normal payload
parser already skips malformed frames, but the chunked path did not.

## Fix

- Validate that each decoded frame is an object with string id/chunk,
integer non-boolean index, and boolean final fields.
- Contain decoder, validation, and reassembly failures at the callback
boundary and log only a bounded frame preview.
- Clear partial state only when the frame carries a validated string id,
allowing that id to be reused safely.
- Preserve the valid chunk reassembly path and fix the Chunked docstring
typo.

## Regression coverage

Tests cover invalid JSON, non-object frames, missing fields, unhashable
ids, wrong field types, unexpected decoder failures, and successful
same-id reassembly immediately after a bad frame clears partial state.

## Verification

- nox -s tst -- tests/test_triggers.py: 83 passed
- make chk: Ruff and mypy passed

---------

Signed-off-by: Checo <sergio@checo.cc>
Co-authored-by: Checo <sergio@checo.cc>
Co-authored-by: jkomyno <alberto@composio.dev>
2026-07-28 20:08:54 +05:30
Alberto Schiabel 2deb239e94 fix(cli): separate prompt, output, and decoration capabilities (#3964)
## Summary

`TerminalUI` classified the terminal with a single aggregate:

```ts
isInteractive = stdinIsTTY && stdoutIsTTY && stderrIsTTY;
```

and reused it for three unrelated decisions: whether Clack may prompt,
whether `ui.output()` emits machine data, and caller behavior in login,
setup, and the update notice. That let output routing change program
behavior:

- Redirecting stdout made `login` look non-interactive even though stdin
and stderr were still usable, so `composio login | tee log` silently
switched to the headless instructions path.
- Redirecting only stdin made `ui.output()` write machine data onto a
human-visible stdout terminal, because the output gate keyed off the
prompting aggregate instead of stdout.
- Capturing stderr changed stdout data emission, even though it is
purely a reporting-mode concern.

This PR separates the three capability axes so each stream owns exactly
one decision:

| Axis | Rule |
| --- | --- |
| Prompting | `canPrompt = stdinIsTTY && stderrIsTTY` — stdout is
irrelevant |
| Machine output | `ui.output(data)` writes only when stdout is **not**
a TTY, or with explicit `{ force: true }` (unchanged) |
| Decoration | `canDecorate = stderrIsTTY` (unchanged) |

The aggregate `isInteractive` capability is removed rather than renamed,
so no caller can reintroduce the conflation.

## Changes

- `services/terminal-ui.ts`: `TerminalCapabilities` now exposes
`canPrompt` instead of `isInteractive`; `output()` gates on
`stdoutIsTTY` alone. The live implementation is now built by an exported
`makeTerminalUI(streams)` factory so tests can exercise real behavior
against injected streams; `TerminalUILive` passes
`process.{stdin,stdout,stderr}` as before.
- `commands/login.cmd.ts`: waiting for browser login is a prompting
decision (`canPrompt`); intro/notes are stderr chrome (`canDecorate`).
Piping stdout no longer reroutes authentication.
- `commands/setup.cmd.ts`: the `--yes` guards for local changes now key
off `canPrompt`.
- `services/update-check.ts`: the update notice is advisory output for a
human watching stderr, not part of any command's result, so it now keys
off `canDecorate` — piping stdout no longer suppresses it, and it still
never touches stdout, so piped data stays clean.
- Telemetry continues to receive the raw per-stream TTY bits
(unchanged).
- `ts/packages/cli/AGENTS.md`: output conventions now document the three
independent stream contracts.

## Tests

- Full 8-combination TTY matrix at the classifier level.
- Behavioral tests with fake sink streams and mocked Clack prompts,
proving behavior rather than returned booleans:
- stdin redirected, stdout+stderr TTY: prompts fall back to defaults
without invoking Clack, `ui.output()` does **not** leak JSON to the
visible terminal, `force` still writes, decoration renders;
- stdout piped, stdin+stderr TTY: the Clack prompt actually runs,
machine data emits, decoration renders;
- stderr captured, stdin+stdout TTY: no prompts, no decoration, stdout
suppressed unless forced;
  - everything redirected: machine data still emits.
- Login regression: with stdout piped but stdin/stderr TTYs, `composio
login --no-browser` enters the interactive wait (poll spinner) path and
does not print the headless/agent instructions.
- Update-notice regressions: still shown when stdout is piped or stdin
is redirected; suppressed only when stderr is captured.

## Notes

This is the shared prerequisite for
https://github.com/ComposioHQ/composio/pull/3951 (captured-stderr plain
renderer) and https://github.com/ComposioHQ/composio/pull/3945
(agent-friendly headless login). It intentionally implements neither
feature; both PRs should rebase onto this once merged. No changeset:
`@composio/cli` is Changesets-ignored.

## Verification

- `pnpm typecheck` (repo root)
- `pnpm --filter @composio/cli test` (validate:skills,
validate:boundaries, full vitest suite)
- `eslint` and `prettier --check` on all touched files

VHS recordings skipped: internal capability wiring, no visible
command-surface change.
2026-07-28 19:57:07 +05:30
Alberto Schiabel 64acec65b6 ci(ts): fix next push trigger and cache reuse (#3971)
This PR:

- fixes the `ts.build.yml` push trigger, which still pointed at
`master`: the repo's default branch is `next`, so the workflow has not
run on push since 2025-10-24 and never populated the turbo/pnpm caches
that PR runs restore from (GitHub cache isolation lets PRs read
base-branch caches, but not other PRs')
- fixes the same stale `master` push trigger in `py.check.yaml` (all
other workflows already list `next`)
- adds a `cache-save` input (default `'true'`, preserving current
behavior for every other consumer) to the `setup-node-pnpm-bun`
composite action, swapping `actions/cache` for `actions/cache/restore`
(same repo, same v6.1.0 SHA pin) when disabled
- wires `cache-save` in `ts.build.yml` so only push runs on `next`
persist caches: PR-scoped saves are invisible to other branches, so they
only cost post-job time and evict default-branch entries from the 10 GB
repo cache quota

## Context

Measured on run
[30364148082](https://github.com/ComposioHQ/composio/actions/runs/30364148082)
(PR run, ~90s wall time):

| Step | Time |
|---|---|
| Checkout | 5s |
| Setup Node.js, pnpm, Bun | 34s (mise 1s, setup-node 5s, setup-bun 2s,
pnpm 2s, **pnpm store restore 18s** for 658 MB, turbo restore 1s) |
| `pnpm install --frozen-lockfile` | 14s |
| `pnpm lint` | 1s |
| `pnpm run build:packages` | 24s, **0/19 turbo cache hits** |
| Post-job cache saves | ~11s (turbo save + a 658 MB pnpm store save
that failed with "Unable to reserve cache", racing the parallel ts.*
jobs on the same PR) |

The build restored a turbo cache only via the fallback restore-key
`Linux-turbo-build-` from an unrelated branch, hence 0 hits. Once push
runs fire on `next` again, every merge saves a fresh
`Linux-turbo-build-<sha>` cache that PR runs match through the
restore-key prefix, so unchanged packages become turbo hits (up to ~20s
off the build step) and the ~11s post-job save disappears from PR runs.
The per-commit key suffix is kept intentionally: the turbo cache
accumulates, so each default-branch save needs a fresh key and readers
match via the prefix (documented inline in the action).
2026-07-28 19:53:19 +05:30
Alberto Schiabel a78a3fcb97 Merge branch 'next' into claude/cli-adoption-funnel-d95660 2026-07-28 19:38:42 +05:30
Alberto Schiabel f233e46937 chore(repo): migrate eslint to oxlint and typecheck to TypeScript 7 (#3966)
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
2026-07-28 19:16:57 +05:30