Skip to content

fix(cli): run JSON crews headless when there is no terminal - #8239

Merged
joaomdmoura merged 1 commit into
mainfrom
fix/json-crew-run-headless-without-terminal
Oct 18, 2026
Merged

joaomdmoura merged 1 commit into
mainfrom
fix/json-crew-run-headless-without-terminal

Conversation

@joaomdmoura

@joaomdmoura joaomdmoura commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

crewai run on a JSON crew, the default crewai create crew project, always opened the interactive run screen unless CREWAI_DMN was set. Without a terminal (a coding agent's shell, CI, piped input) the screen stayed open after the crew finished, so the command never exited. JSON crews now follow the rule declarative flows already use: the screen opens only in an interactive terminal, and otherwise the crew runs on plain output and the command exits.

  • Scope: _run_json_crew gates the screen on is_interactive() (stdin is a terminal and CREWAI_DMN is unset) instead of on CREWAI_DMN alone.
  • Unchanged: an interactive terminal still gets the screen, and CREWAI_DMN still forces the plain run.
  • Tests: with no terminal the crew runs plain, prints its result, and the screen never starts (this fails on main). A terminal still opens the screen; the existing screen tests now simulate one. End to end, crewai run < /dev/null on a scaffolded JSON crew exits 0 in 28 s, and hangs until killed on main.
  • Found by the AGENTS.md eval: coding agents running a JSON crew with either AGENTS.md had to kill crewai run, or read results with crewai log-tasks-outputs.
  • Out: Python conversational flows (_run_conversational_flow_tui) still open the chat screen without a terminal check. Needs a ticket.

🤖 Generated with Claude Code


Note

Low Risk
CLI run-mode gating only; no changes to crew execution, auth, or data handling beyond when the TUI starts.

Overview
Fixes crewai run on JSON crews so the command exits in non-interactive environments (coding agents, CI, piped stdin) instead of leaving the run TUI open after kickoff finishes.

_run_json_crew now skips the TUI when is_interactive() is false (no TTY or CREWAI_DMN set) and uses the plain _run_json_crew_without_tui path; interactive terminals still get the run screen, with inputs resolved as fully interactive on that path. The is_dmn_mode_enabled import from this module is removed in favor of the shared is_interactive() helper.

Tests mock stdin.isatty for existing TUI cases and add coverage for headless vs TUI selection.

Reviewed by Cursor Bugbot for commit caa4173. Bugbot is set up for automated code reviews on this repo. Configure here.

`crewai run` on a JSON crew opened the Textual run screen unless CREWAI_DMN
was set. Without an interactive terminal (a coding agent's shell, CI, piped
input) the screen stayed open after the crew finished, so the command never
exited. It now opens only when is_interactive() is true, the convention
declarative flows already follow; otherwise the crew runs on plain output and
the command exits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@joaomdmoura joaomdmoura added the llm-generated This was created primarily by an agent, agents, or LLM. label Oct 17, 2026
@strix-security

strix-security Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Strix Security Review

No security issues found.

Review summary

Reviewed the full diff for PR #8239. The change makes crewai run on a JSON crew gate its interactive TUI on is_interactive() (stdin is a terminal and CREWAI_DMN is unset) instead of CREWAI_DMN alone, so the command exits cleanly when no terminal is present (CI, coding agents, piped input). This is a control-flow/exit-behavior fix with no security-relevant surface: no new input handling, no dangerous sinks, no removed security controls, and no auth/crypto/secrets changes. The interactive=True change is safe because it is only reachable after the early return has confirmed interactivity. The remaining changed lines are tests only. No security vulnerabilities were found in the changed code.

Updated for caa4173.


Reviewed by Strix
Re-run review · Configure security review settings

@coderabbitai

coderabbitai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 24d87f09-b695-49ce-a942-05bd457f6531
📥 Commits

Reviewing files that changed from the base of the PR and between 40bb2d3 and caa4173.

📒 Files selected for processing: 2
  • lib/cli/src/crewai_cli/run_crew.py
  • lib/cli/tests/test_run_crew.py

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

JSON crew execution now uses plain terminal output when stdin is not interactive. When stdin is interactive, execution uses the TUI. Tests cover both paths.

Changes: JSON crew execution

Layer / File(s) Summary
Terminal-dependent execution paths
lib/cli/src/crewai_cli/run_crew.py, lib/cli/tests/test_run_crew.py
The CLI selects plain execution for non-interactive input and the TUI for interactive input. Tests verify the loader, kickoff, output, and returned result for both paths.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as JSON crew CLI
  participant Terminal as is_interactive()
  participant PlainLoader as Plain crew loader
  participant TUI as TUI loader
  CLI->>Terminal: Check terminal availability
  alt Non-interactive
    CLI->>PlainLoader: Load JSON crew
    PlainLoader-->>CLI: Return crew
    CLI->>PlainLoader: Call kickoff with resolved defaults
    PlainLoader-->>CLI: Return result
    CLI->>CLI: Print plain result
  else Interactive
    CLI->>TUI: Load and open TUI
    TUI-->>CLI: Return TUI result
  end
Loading

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to caa41

JSON crews now run with plain output when stdin is not a terminal, so the command can exit instead of hanging. Interactive terminals still open the run screen. No merge-blocking risk was identified.

Pre-merge checks: Passed 3 · Failed 2

Failed Failed checks: 2 warnings

Check name Status Explanation Resolution
Description check Warning The description explains the problem, solution, scope, behavior, and verification. However, it omits the required Related issue section and does not complete the verification checklist. Add a valid linked issue under Related issue, complete the Verification checklist, and include an Additional context section with relevant notes or None.
Docstring Coverage Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 3 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: JSON crews run headlessly when no terminal is available.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@joaomdmoura
joaomdmoura enabled auto-merge (squash) October 18, 2026 06:04

@iris-clawd iris-clawd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The early branch makes the unsafe headless route unable to reach Textual while preserving the interactive and DMN cases.

Not holding this for it, but worth a ticket so it is not forgotten: This changes the observable default behavior of a public CLI command: non-TTY JSON runs now select plain execution instead of the TUI. The two paths are not presentation-only: the TUI path applies _prepare_json_crew_for_tui, changing verbosity and LLM streaming, while the headless path does not.

@joaomdmoura
joaomdmoura merged commit 9112709 into main Oct 18, 2026
64 checks passed
@joaomdmoura
joaomdmoura deleted the fix/json-crew-run-headless-without-terminal branch October 18, 2026 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gate-approved llm-generated This was created primarily by an agent, agents, or LLM. size/S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants