feat(task): add interactive field for exclusive terminal access#8491
feat(task): add interactive field for exclusive terminal access#8491
interactive field for exclusive terminal access#8491Conversation
Tasks marked `interactive = true` acquire an exclusive write lock, ensuring they get sole access to stdin/stdout/stderr. Non-interactive tasks use a shared read lock and can still run in parallel with each other. This is a more targeted alternative to `raw = true` which forces `jobs=1` globally. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a new Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces an interactive field for tasks, providing a mechanism for exclusive terminal access. This is achieved using a global RwLock in task_executor.rs, where interactive tasks acquire a write lock and non-interactive tasks acquire a read lock. This is a well-designed alternative to using raw = true which would limit concurrency globally. The changes are consistently applied across schema definitions, CLI outputs, and task handling logic. The logic for treating interactive tasks as raw for I/O purposes in task_output_handler.rs is also correct. The implementation is clean and effective. The e2e tests have been updated accordingly. Overall, this is a great addition.
- Move lock acquisition from exec_program to exec_task_run_entries and exec_file callers, so the lock is held across the full task execution (not released between multi-step run entries) - Skip misleading "--raw will prevent redactions" hint for interactive tasks since the user set interactive=true, not raw=true Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR adds an Key changes:
Issues found:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Sched as Task Scheduler
participant ExecTask as exec_task / exec_file
participant Lock as TASK_RUNTIME_LOCK
participant Cmd as CmdLineRunner (block_in_place)
Note over Sched: Interactive task + 2 non-interactive tasks dispatched
Sched->>ExecTask: interactive-task (interactive=true)
ExecTask->>Lock: write().await (exclusive)
Lock-->>ExecTask: WriteGuard held
par non-interactive tasks try to start
Sched->>Lock: read().await (bg-task-1)
Note over Lock: Blocked — writer held
Sched->>Lock: read().await (bg-task-2)
Note over Lock: Blocked — writer held
end
ExecTask->>Cmd: block_in_place(cmd.execute())
Cmd-->>ExecTask: process exits
ExecTask->>Lock: drop WriteGuard
par bg tasks now unblocked
Lock-->>Sched: ReadGuard (bg-task-1)
Lock-->>Sched: ReadGuard (bg-task-2)
Note over Sched: bg-task-1 and bg-task-2 run in parallel
end
|
…o text output - Wrap cmd.execute() with tokio::task::block_in_place since it blocks the thread while holding a tokio RwLock guard - Add "interactive" to human-readable `mise task info` properties - Add comment explaining intentional double-lock with RAW_LOCK Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ck acquisition Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…usivity Acquire the lock once before the run-entry loop so consecutive script entries maintain terminal exclusivity for interactive tasks. The lock is temporarily dropped around inject_and_wait calls to avoid deadlocking with sub-tasks that also need to acquire the lock. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move lock acquisition from the caller into exec_file, after parse_usage_spec_and_init_env and check_confirmation complete. This avoids blocking all tasks during the confirmation dialog. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ile tasks For interactive file-based tasks, acquire the lock before the confirmation prompt so it gets exclusive terminal access and doesn't race with concurrent task output. Non-interactive tasks still acquire the lock after confirmation to avoid blocking the task graph. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Interactive tasks bypass redactions since they use raw I/O. Instead of silently suppressing the warning, emit a specific hint so users are aware secrets may appear in terminal output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… tasks Consistent with the exec_file path, acquire the runtime lock before check_confirmation for interactive run-entry tasks so the confirmation prompt gets exclusive terminal access. The lock is dropped after confirmation and re-acquired inside exec_task_run_entries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Instead of dropping the confirmation guard and re-acquiring a new one (leaving a gap where other tasks could print), pass the existing guard into exec_task_run_entries so exclusivity is maintained seamlessly from confirmation through script execution. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…clippy warning Show raw_redactions hint when task has explicit raw config, even if also interactive. Only show interactive_redactions when raw is solely due to interactive mode. Suppress too_many_arguments clippy lint on exec_task_run_entries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.3 x -- echo |
23.8 ± 0.7 | 22.7 | 26.0 | 1.02 ± 0.04 |
mise x -- echo |
23.4 ± 0.5 | 22.7 | 28.6 | 1.00 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.3 env |
23.0 ± 0.7 | 22.2 | 29.1 | 1.02 ± 0.04 |
mise env |
22.6 ± 0.6 | 22.0 | 32.9 | 1.00 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.3 hook-env |
23.6 ± 0.3 | 23.0 | 27.8 | 1.01 ± 0.02 |
mise hook-env |
23.4 ± 0.3 | 22.7 | 24.8 | 1.00 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.3 ls |
23.1 ± 0.5 | 22.4 | 27.3 | 1.01 ± 0.03 |
mise ls |
22.9 ± 0.4 | 22.1 | 24.5 | 1.00 |
xtasks/test/perf
| Command | mise-2026.3.3 | mise | Variance |
|---|---|---|---|
| install (cached) | 152ms | 151ms | +0% |
| ls (cached) | 84ms | 82ms | +2% |
| bin-paths (cached) | 85ms | 84ms | +1% |
| task-ls (cached) | 836ms | 811ms | +3% |
### 🚀 Features - **(github)** keep exe extensions on Windows by @iki in [#8424](#8424) - **(task)** add `interactive` field for exclusive terminal access by @jdx in [#8491](#8491) - add header comment to generated lockfiles by @ivy in [#8481](#8481) - runtime musl/glibc detection for correct libc variant selection by @jdx in [#8490](#8490) ### 🐛 Bug Fixes - **(github)** use registry platform options during install by @jdx in [#8492](#8492) - **(http)** store tool opts as native TOML to fix platform switching by @jdx in [#8448](#8448) - **(installer)** error if MISE_INSTALL_PATH is a directory by @jdx in [#8468](#8468) - **(prepare)** resolve sources/outputs relative to `dir` when set by @jdx in [#8472](#8472) - **(ruby)** fetch precompiled binary by release tag instead of listing all releases by @jdx in [#8488](#8488) - **(schema)** support structured objects in task depends by @risu729 in [#8463](#8463) - **(task)** replace println!/eprintln! with calm_io in task output macros by @vmaleze in [#8485](#8485) - handle scoped npm package names without backend prefix by @jdx in [#8477](#8477) ### 📦️ Dependency Updates - update ghcr.io/jdx/mise:copr docker digest to c485c4c by @renovate[bot] in [#8484](#8484) - update ghcr.io/jdx/mise:alpine docker digest to 8118bc7 by @renovate[bot] in [#8483](#8483) ### 📦 Registry - disable sd version test by @jdx in [#8489](#8489) ### New Contributors - @ivy made their first contribution in [#8481](#8481) - @iki made their first contribution in [#8424](#8424) ## 📦 Aqua Registry Updates #### New Packages (5) - [`datadog-labs/pup`](https://github.com/datadog-labs/pup) - [`k1LoW/mo`](https://github.com/k1LoW/mo) - [`rtk-ai/rtk`](https://github.com/rtk-ai/rtk) - [`suzuki-shunsuke/docfresh`](https://github.com/suzuki-shunsuke/docfresh) - [`yashikota/exiftool-go`](https://github.com/yashikota/exiftool-go) #### Updated Packages (6) - [`cloudflare/cloudflared`](https://github.com/cloudflare/cloudflared) - [`mozilla/sccache`](https://github.com/mozilla/sccache) - [`owenlamont/ryl`](https://github.com/owenlamont/ryl) - [`spinel-coop/rv`](https://github.com/spinel-coop/rv) - [`technicalpickles/envsense`](https://github.com/technicalpickles/envsense) - [`weaviate/weaviate`](https://github.com/weaviate/weaviate)
Summary
interactive = truetask field that acquires an exclusive write lock on a globalRwLock, giving the task sole access to stdin/stdout/stderrraw = truewhich forcesjobs=1globally —interactiveonly blocks concurrent tasks while the interactive task is runningcmd.rschanges, no TTY save/restore, no setpgidChanges
src/task/mod.rs— addinteractive: boolfield, file-task parsing, defaultsrc/task/task_executor.rs— globalTASK_RUNTIME_LOCK: RwLock<()>, acquire write (interactive) or read (non-interactive) beforecmd.execute()src/task/task_output_handler.rs— treatinteractiveasrawfor I/Osrc/cli/tasks/info.rs,src/cli/tasks/ls.rs,src/cli/mcp.rs— addinteractiveto JSON outputschema/mise-task.json,schema/mise.json— addinteractiveboolean propertye2e/tasks/test_task_info,e2e/tasks/test_task_ls— update expectationsTest plan
mise run lint-fixpassescargo test— all 520 unit tests passmise run test:e2e test_task_info test_task_lspassesinteractive-task ::: bg-task-1 ::: bg-task-2— interactive task waits for exclusive access while bg tasks run in parallel🤖 Generated with Claude Code
Note
Medium Risk
Touches core task execution/concurrency and terminal I/O behavior via a new global lock, which could introduce deadlocks or unexpected scheduling/throughput changes if edge cases aren’t covered.
Overview
Adds a new boolean task field
interactive(defaultfalse) that marks a task as requiring exclusive terminal access, and wires it through task parsing and defaults.Task execution now uses a global runtime
RwLockto coordinate concurrency: interactive tasks take an exclusive lock (including during confirmation prompts), while non-interactive tasks take a shared lock; the lock is held across consecutive run-script entries but dropped while waiting on injected sub-tasks to avoid deadlocks, and command execution is wrapped inblock_in_placeto avoid starving the tokio runtime.CLI/MCP JSON outputs and
tasks infoproperty display now includeinteractive, JSON schemas (mise.json,mise-task.json) are updated accordingly, interactive tasks are treated as raw I/O in the output handler (with a new hint warning about redactions), and e2e expectations are updated.Written by Cursor Bugbot for commit 4126daa. This will update automatically on new commits. Configure here.