Skip to content

feat: add apify agent setup command with auto-detection and non-interactive flag (#1451) - #1471

Open
kuntal1461 wants to merge 2 commits into
apify:masterfrom
kuntal1461:feat/global-non-interactive-flag
Open

kuntal1461 wants to merge 2 commits into
apify:masterfrom
kuntal1461:feat/global-non-interactive-flag

Conversation

@kuntal1461

@kuntal1461 kuntal1461 commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Related to #1451
Related to #1445

Summary

  • Adds apify agent setup — auto-detects installed AI coding agents by env var and home-path heuristics, then configures them to use Apify tools via MCP
  • Adds global --non-interactive flag (isNonInteractive()) so commands can detect CI/script context without checking TTY themselves
  • Covers Claude Code, Cursor, VS Code, VS Code Insiders, Kiro, Codex, and Antigravity (Gemini CLI)

What's included

New command: apify agent setup

  • Auto-detects clients via env vars (CLAUDECODE, CURSOR_AGENT, CODEX_SANDBOX, CODEX_THREAD_ID, OPENCLAW_SHELL, etc.) and home-path markers (~/.claude, ~/.cursor/mcp.json, ~/.kiro, ~/.gemini/antigravity, etc.)
  • Tier ladder: plugin > skills+mcp > mcp > manual with graceful fallback when a higher tier has no published artifact
  • Idempotency: reads agent-state.json before applying; skips already-configured clients and reports already_configured outcome
  • --client <name> to target a specific client, bypassing auto-detection
  • --yes to skip the confirmation prompt (CI / scripted use)
  • --json output: { clients: [{ client, tier, outcome }] } with reason stripped from machine-readable output
  • MCP URL tagged with ?client=apify-cli for attribution analytics
  • Atomic state file write (tmp -> rename) to prevent partial writes on crash

New supporting modules:

  • src/lib/agent/catalog.json + catalog.ts — client capability catalog with tier ordering helpers
  • src/lib/agent/detection.ts — env-var and filesystem-based client detection
  • src/lib/agent/state.ts — agent-state.json read/write with atomic write pattern
  • src/lib/consts.ts — AGENT_STATE_FILE_PATH constant

Global --non-interactive flag (part of #1451):

  • isNonInteractive() helper in src/lib/nonInteractiveMode.ts
  • stdinCheckWrapper automatically gates interactive prompts
  • All commands respect the flag without per-command TTY checks
  • APIFY_CLI_NON_INTERACTIVE=1 env var equivalent

Tests: 89 tests across 4 files

  • catalog.test.ts — schema validation, tier ordering, URL builder, prototype poisoning guard
  • detection.test.ts — all env signals, negative cases (unsupported clients), home-path markers, ordering (env before path), deduplication
  • state.test.ts — null on missing/malformed file, round-trip fidelity, atomic write (no .tmp left), security (no token in state file), case sensitivity
  • setup.test.ts — detection flow, --client flag, auth gating, confirmation prompt, happy path, MCP URL attribution, idempotency (5 scenarios), --json shape, security, error handling

Test plan

  • pnpm run build passes
  • pnpm run lint passes
  • pnpm run test:local — 725 tests pass (2 pre-existing Python pip failures unrelated to this change)
  • apify agent setup --client cursor --yes writes ~/.cursor/mcp.json with Apify MCP server entry
  • Re-running immediately returns already_configured without overwriting the config

🤖 Generated with Claude Code

@kuntal1461 kuntal1461 changed the title feat: add global --non-interactive flag and agent env var auto-detection (#1451) feat: add apify agent setup command with auto-detection and non-interactive flag (#1451) Oct 5, 2026
kuntal1461 and others added 2 commits October 5, 2026 18:08
Fixes apify#1451 (prompt hang in pseudo-TTY environments) and apify#1354 (phantom --confirm flags).

P0 — global --non-interactive flag:
- New `src/lib/nonInteractiveMode.ts`: single source of truth with
  `isNonInteractive()`, `setNonInteractiveFlag()`, and `resetNonInteractiveFlag()`
- Registered `--non-interactive` in `_buildParseArgsOption()` alongside `--help`
  and `--user-agent`; env var `APIFY_CLI_NON_INTERACTIVE=1` is equivalent
- Activated early in `runCLI()` before version-check middleware; reset+re-applied
  at the start of every `_run()` for test isolation
- All three divergent interactivity decision points now converge on `isNonInteractive()`:
  `_stdinCheckWrapper`, `create.ts`, and `detectIsInteractive()` in telemetry
- Skipped prompt with no programmatic answer exits non-zero with an actionable message
  naming the exact flag to pass (fixes phantom `--confirm/--no-confirm` bug apify#1354)
- Added GLOBAL OPTIONS section to main `--help` output
- Added actionable `errorMessageForStdin` to previously unguarded prompts in
  `useActorConfig.ts` and `auth/login.ts`

P1 — agent env var auto-detection and skill update:
- `AGENT_ENV_VARS` (9 known agent runtimes) moved to `nonInteractiveMode.ts` and
  exported; `isNonInteractive()` returns true when any agent env var is set
- `detectEnvironment.ts` refactored to import `AGENT_ENV_VARS` from the single
  source (no duplication, no circular import)
- `skills/apify/SKILL.md`: added required "always pass --non-interactive" line
- `test/setup.ts` + `vitest.config.ts`: global Vitest setup clears agent env vars
  before each test file so host environment (e.g. CLAUDECODE) does not leak into tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds apify agent setup -- auto-detects installed AI coding agents (Claude Code, Cursor, VS Code, Kiro, Codex, Antigravity) by env var and home-path heuristics, then configures them via MCP. Includes tier ladder, idempotency via state file, --client override, --json output, and 89 tests covering unit, integration, security, and edge cases.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants