Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(system): add login shell bootstrap support#10377

Merged
jdx merged 5 commits into
mainfrom
codex/system-login-shell
Jun 13, 2026
Merged

feat(system): add login shell bootstrap support#10377
jdx merged 5 commits into
mainfrom
codex/system-login-shell

Conversation

@jdx

@jdx jdx commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • add [system].login_shell as a declarative current-user login shell setting
  • apply drift with chsh -s from mise system install and mise bootstrap
  • report login shell state in mise system status, mise doctor, schema, and docs

Tests

  • cargo fmt --all -- --check
  • cargo check --all-targets
  • mise run render
  • mise run test:e2e e2e/cli/test_system_login_shell
  • mise run test:unit

This PR was generated by an AI coding assistant.


Note

High Risk
Changes the user's login shell and may modify /etc/shells via sudo—account-level, irreversible-feeling effects that only run on explicit install/bootstrap but warrant careful review.

Overview
Adds [system].login_shell so mise.toml can declare the current user's desired login shell (absolute path) and converge it with mise system install or mise bootstrap, alongside existing system packages, files, edits, and defaults.

On Unix when chsh is available, install appends the shell to /etc/shells if needed (reusing the system-packages sudo path when the file isn't writable), then runs chsh -s with optional confirmation, dry-run, and --yes. Under sudo it targets SUDO_USER; invalid or relative paths are warned and skipped. Most-local config wins for the single desired value.

mise system status (table + JSON) and --missing now include login-shell drift; scoped installs (--manager or explicit packages) still apply packages only. mise doctor reports system_login_shell in text and JSON. Schema, CLI help, man page, and a new System Login Shell doc page are updated; an e2e test covers status, override, dry-run, and apply with stubbed chsh and /etc/shells.

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

Summary by CodeRabbit

  • New Features

    • Experimental system.login_shell setting added; install/bootstrap can apply it (with dry-run/confirmation) and ensure the shell is allowed on Unix.
  • Behavior & UX

    • status/--missing, doctor, and exit codes now report and validate login-shell state; messages note current-user application and advise restarting sessions.
  • Documentation

    • CLI help, man page, and docs updated with semantics, examples, and macOS/Unix details.
  • Tests

    • New end-to-end and unit tests cover parsing, dry-run, and install flows.

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9e031d0c-8844-482a-8317-7acbfbbfbf97

📥 Commits

Reviewing files that changed from the base of the PR and between 11a13a2 and b4404eb.

📒 Files selected for processing (3)
  • e2e/cli/test_system_login_shell
  • src/system/login_shell.rs
  • src/system/mod.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/system/mod.rs
  • e2e/cli/test_system_login_shell
  • src/system/login_shell.rs

📝 Walkthrough

Walkthrough

Adds a declarative [system].login_shell feature: schema and config parsing, core login-shell status/apply logic (ensure shell listed, chsh invocation), integration into install/status/bootstrap/doctor/usage, documentation updates, and an end-to-end test validating dry-run, validation, precedence, and apply behavior.

Changes

Login Shell System Feature

Layer / File(s) Summary
Login shell core types and module
src/system/login_shell.rs, src/system/mod.rs, schema/mise.json
Defines LoginShellRequest, LoginShellState, and LoginShellStatus types; detects chsh availability on Unix; checks current user shell and compares to requested value; ensures shell listed in shells file and applies via chsh with correct args; includes unit tests.
System config login_shell integration
src/system/mod.rs, src/config/config_file/mise_toml.rs, schema/mise.json
Adds optional login_shell field to SystemTomlConfig; implements login_shell_from_config using most-local-wins strategy with validation for non-empty absolute paths; includes TOML parsing tests and schema addition.
System install command login shell support
src/cli/system/install.rs, src/cli/system/mod.rs
Derives login shell from config alongside defaults; updates package-install gate to recognize login-shell-only runs; adds apply_login_shell helper performing availability check, status comparison, optional user confirmation, and chsh execution.
System status command login shell reporting
src/cli/system/status.rs
Loads login shell requirements, checks availability, reports set/differs/missing-from-shells state in both JSON and table output with fields for user/current/shell_listed/state; updates --missing semantics.
Bootstrap and doctor command integration
src/cli/bootstrap.rs, src/cli/doctor/mod.rs
Bootstrap adds post-defaults login shell step via apply_login_shell; doctor adds SystemLoginShellDiagnosis and check/analysis functions reporting availability, out-of-sync, and failure states in JSON and text output.
Documentation and help text updates
docs/cli/*.md, docs/system-*, docs/tips-and-tricks.md, man/man1/mise.1, mise.usage.kdl, xtasks/fig/src/mise.ts
Markdown docs and manpage introduce login_shell feature and semantics (Unix-only, absolute paths, chsh -s, /etc/shells handling); KDL usage and completions updated; examples added.
End-to-end test coverage
e2e/cli/test_system_login_shell
Bash E2E test validating status reporting, idempotency, local config precedence, validation of non-absolute paths, dry-run output, and real apply with shells-file and fake chsh verification.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • jdx/mise#10346: Overlaps changes to SystemInstall flow and related wiring touched by this PR.
  • jdx/mise#10363: Related macOS/system convergence changes that this PR builds on.
  • jdx/mise#10365: Related bootstrap and system-install pipeline changes touching the same integration points.

Poem

🐰 I hop the shells and tidy rows,

"Be listed first, then change your toes."
Dry-run hums a gentle cue,
chsh whispers when the time is true.
A rabbit nods — your login's new.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat(system): add login shell bootstrap support' clearly and accurately summarizes the main feature addition: implementing login shell configuration and bootstrap support within the system module.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Comment thread src/system/login_shell.rs
@greptile-apps

greptile-apps Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces [system].login_shell as a declarative, experimental setting that converges a user's Unix login shell via chsh -s, applied by mise system install and mise bootstrap with dry-run, confirmation, and sudo support for /etc/shells mutations.

  • Adds src/system/login_shell.rs with status/apply primitives, correct SUDO_USER targeting, /etc/shells membership checks, and an append-then-chsh apply flow.
  • Wires the feature into mise system status (table + JSON + --missing exit code), mise system install, mise bootstrap, and mise doctor (text + JSON); all paths are consistently gated on experimental.
  • Ships a thorough e2e test covering the no-op, local-overrides-global, invalid-skipped, dry-run, and real-apply scenarios.

Confidence Score: 5/5

Safe to merge; the change is correctly gated on experimental, the sudo/SUDO_USER path is handled, and the e2e test covers the critical apply flows.

The core logic in login_shell.rs and the install/status wiring is solid. The two doctor output issues are cosmetic inconsistencies that do not affect correctness or safety.

src/cli/doctor/mod.rs — the SystemLoginShellDiagnosis::Checked variant loses shell_listed and user from LoginShellStatus, producing less informative doctor output than system status --json.

Important Files Changed

Filename Overview
src/system/login_shell.rs New module implementing declarative login-shell management; correctly handles sudo/SUDO_USER targeting, /etc/shells membership checks, dry-run, and append-then-chsh apply flow. Unit tests cover state logic and chsh args.
src/cli/system/install.rs Adds apply_login_shell helper (shared with bootstrap) alongside the existing apply_defaults; scoping logic correctly gates login_shell behind the packages-only check.
src/cli/system/status.rs Adds login_shell rows to both table and JSON output, correctly sets any_missing for Differs and MissingFromShells states, and updates the nothing-configured guard.
src/cli/doctor/mod.rs Adds check_system_login_shell shared helper wired into both text and JSON doctor paths; doctor JSON drops user/shell_listed fields, and text output does not distinguish MissingFromShells from Differs.
src/system/mod.rs Adds login_shell_from_config with correct most-local-wins iteration; validates non-empty and absolute path, warns and skips invalid entries.
src/cli/bootstrap.rs Cleanly threads login_shell through bootstrap in the correct order (after defaults, before tool installs).
e2e/cli/test_system_login_shell Good e2e coverage: no-op when matching, local-overrides-global, invalid-skips-to-global, dry-run, and real apply.
src/config/config_file/mise_toml.rs Adds login_shell field to SystemTomlConfig with a unit test verifying parse round-trip.

Reviews (3): Last reviewed commit: "fix(system): tighten login shell converg..." | Re-trigger Greptile

Comment thread src/system/login_shell.rs Outdated
Comment thread src/system/login_shell.rs

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/cli/test_system_login_shell`:
- Around line 3-9: Ensure the test setup creates the bin directory and resets
the log before installing the fake chsh: create "$HOME/bin" with mkdir -p
"$HOME/bin", export CHSH_LOG="$PWD/chsh.log" (move the export above the
here-doc), remove any stale log (rm -f "$CHSH_LOG" or >"$CHSH_LOG") before the
test runs, then write the chsh stub to "$HOME/bin/chsh" (the here-doc should
append to "$CHSH_LOG" as before) and chmod +x "$HOME/bin/chsh"; this guarantees
CHSH_LOG and the target directory exist and the log is deterministic across
runs.

In `@mise.usage.kdl`:
- Line 291: The text currently groups "[system].login_shell" with macOS, which
is incorrect; update both occurrences so platform scope is explicit: leave
macOS-specific mentions tied to "[system.defaults]" or "(macOS)" only, and
clarify that "[system].login_shell" is a Unix-wide feature (e.g., "on Unix
systems, [system].login_shell — settable via chsh -s"); for example replace
ambiguous fragments like "(macOS) and [system].login_shell" with two clear
phrases such as "(macOS) and, separately, on Unix systems [system].login_shell
(set via chsh -s)". Ensure both places in the file use this clarified wording.
- Around line 2992-2993: The text mistakenly uses "version-differs" for the
login_shell status; update the wording around the existing phrase that lists
"missing/version-differs categories for configured login shell" to instead use a
non-versioned term such as "differs" or "out-of-sync" (e.g., replace
"version-differs" with "differs" so the login_shell is described as either
"missing" or "differs/out-of-sync"); target the occurrence referencing
login_shell in the sentence so no other versioned entries are changed.

In `@schema/mise.json`:
- Around line 2964-2967: The schema allows any string for the login_shell
property but the description requires an absolute path; tighten the
"login_shell" JSON Schema by adding a constraint such as "pattern": "^/.*" (or
an appropriate absolute-path regex) and, if desired, "minLength": 1 to reject
empty strings so that only absolute-paths (starting with "/") are accepted;
update the "login_shell" schema entry to include this pattern property while
leaving the existing "type" and "description" intact.

In `@xtasks/fig/src/mise.ts`:
- Around line 3345-3346: The help text for the "system status --missing" command
omits edits even though the implementation checks
system::edits::edits_from_config() and sets any_missing when a FileState !=
Applied; update the command help/description string to mention "[system.edits]"
alongside "packages, files, defaults, or login shell" and regenerate/modify the
corresponding generated entry in mise.ts so the displayed help includes
"[system.edits]" as well (ensure the same wording appears in the CLI source
description and the generated xtasks entry).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e4bb3fde-e3b3-4fdb-81a0-ed4a7094a36b

📥 Commits

Reviewing files that changed from the base of the PR and between 3f2ae78 and 5304ad0.

📒 Files selected for processing (20)
  • docs/cli/bootstrap.md
  • docs/cli/system.md
  • docs/cli/system/install.md
  • docs/cli/system/status.md
  • docs/system-login-shell.md
  • docs/system-packages/index.md
  • docs/tips-and-tricks.md
  • e2e/cli/test_system_login_shell
  • man/man1/mise.1
  • mise.usage.kdl
  • schema/mise.json
  • src/cli/bootstrap.rs
  • src/cli/doctor/mod.rs
  • src/cli/system/install.rs
  • src/cli/system/mod.rs
  • src/cli/system/status.rs
  • src/config/config_file/mise_toml.rs
  • src/system/login_shell.rs
  • src/system/mod.rs
  • xtasks/fig/src/mise.ts

Comment thread e2e/cli/test_system_login_shell
Comment thread mise.usage.kdl Outdated
Comment thread mise.usage.kdl Outdated
Comment thread schema/mise.json
Comment thread xtasks/fig/src/mise.ts Outdated

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/system/login_shell.rs`:
- Around line 67-70: The apply() function calls
ensure_shell_listed(&request.shell, dry_run) before resolving the user, which
can mutate /etc/shells even if user resolution fails; change the call order so
you first resolve the user and compute chsh args (call target_user() and
chsh_args(request, &user)), and only after those succeed call
ensure_shell_listed(&request.shell, dry_run) (so ensure_shell_listed runs after
target_user() and chsh_args()). Update apply() to return errors from
target_user()/chsh_args() without having already modified shells.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c6984b1c-6f8d-494b-9599-04ccd54e50ae

📥 Commits

Reviewing files that changed from the base of the PR and between 5304ad0 and ae3b65d.

📒 Files selected for processing (10)
  • docs/cli/system/install.md
  • docs/system-login-shell.md
  • docs/system-packages/index.md
  • e2e/cli/test_system_login_shell
  • man/man1/mise.1
  • mise.usage.kdl
  • src/cli/system/install.rs
  • src/cli/system/status.rs
  • src/system/login_shell.rs
  • src/system/sudo.rs
✅ Files skipped from review due to trivial changes (5)
  • src/system/sudo.rs
  • docs/cli/system/install.md
  • docs/system-packages/index.md
  • man/man1/mise.1
  • mise.usage.kdl
🚧 Files skipped from review as they are similar to previous changes (4)
  • docs/system-login-shell.md
  • e2e/cli/test_system_login_shell
  • src/cli/system/status.rs
  • src/cli/system/install.rs

Comment thread src/system/login_shell.rs

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 11a13a2. Configure here.

Comment thread src/system/login_shell.rs
Comment thread src/system/mod.rs

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/system/login_shell.rs (1)

71-85: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Skip chsh when the requested shell is already current.

status() now distinguishes MissingFromShells, but apply() still always executes chsh after repairing /etc/shells. When the passwd entry already matches request.shell, that turns a shells-allowlist fix into an unnecessary chsh call and makes the install/bootstrap path prompt for work that is already applied. Please short-circuit this branch after ensure_shell_listed() and add a regression test for the current == requested && !shell_listed case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/system/login_shell.rs` around lines 71 - 85, In apply(), after calling
ensure_shell_listed(&request.shell, dry_run) and before
building/printing/executing the chsh command, check the current shell for the
target user (reusing target_user() result or calling the same lookup used by
status()) and if the current shell equals request.shell return Ok(()) (or log
that no chsh is needed) to short-circuit the unnecessary chsh; update or reuse
functions chsh_args(), target_user(), and ensure_shell_listed() as needed to get
the current value without duplicating logic, and add a regression test
exercising the case where current == requested && !shell_listed to ensure
apply() repairs /etc/shells but does not call chsh.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/system/login_shell.rs`:
- Around line 71-85: In apply(), after calling
ensure_shell_listed(&request.shell, dry_run) and before
building/printing/executing the chsh command, check the current shell for the
target user (reusing target_user() result or calling the same lookup used by
status()) and if the current shell equals request.shell return Ok(()) (or log
that no chsh is needed) to short-circuit the unnecessary chsh; update or reuse
functions chsh_args(), target_user(), and ensure_shell_listed() as needed to get
the current value without duplicating logic, and add a regression test
exercising the case where current == requested && !shell_listed to ensure
apply() repairs /etc/shells but does not call chsh.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dec4fd46-0652-491b-a05e-d68c08bb30f1

📥 Commits

Reviewing files that changed from the base of the PR and between ae3b65d and 11a13a2.

📒 Files selected for processing (14)
  • docs/cli/bootstrap.md
  • docs/cli/system.md
  • docs/cli/system/install.md
  • docs/cli/system/status.md
  • e2e/cli/test_system_login_shell
  • man/man1/mise.1
  • mise.usage.kdl
  • schema/mise.json
  • src/cli/bootstrap.rs
  • src/cli/system/install.rs
  • src/cli/system/mod.rs
  • src/cli/system/status.rs
  • src/system/login_shell.rs
  • xtasks/fig/src/mise.ts
✅ Files skipped from review due to trivial changes (7)
  • src/cli/system/mod.rs
  • docs/cli/system/install.md
  • docs/cli/bootstrap.md
  • xtasks/fig/src/mise.ts
  • docs/cli/system/status.md
  • man/man1/mise.1
  • mise.usage.kdl
🚧 Files skipped from review as they are similar to previous changes (5)
  • docs/cli/system.md
  • src/cli/bootstrap.rs
  • schema/mise.json
  • src/cli/system/status.rs
  • e2e/cli/test_system_login_shell

@github-actions

github-actions Bot commented Jun 13, 2026

Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.5 x -- echo 17.8 ± 0.7 16.4 22.1 1.00
mise x -- echo 18.5 ± 2.0 16.9 57.7 1.04 ± 0.12

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.5 env 17.8 ± 0.7 16.2 21.0 1.00
mise env 18.3 ± 0.7 16.8 21.8 1.03 ± 0.06

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.5 hook-env 18.3 ± 0.7 16.9 22.3 1.00
mise hook-env 18.9 ± 0.7 17.5 22.0 1.03 ± 0.06

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.5 ls 15.0 ± 0.7 13.7 18.6 1.00
mise ls 15.7 ± 0.7 14.2 18.8 1.04 ± 0.07

xtasks/test/perf

Command mise-2026.6.5 mise Variance
install (cached) 131ms 132ms +0%
ls (cached) 58ms 59ms -1%
bin-paths (cached) 63ms 63ms +0%
task-ls (cached) 122ms 123ms +0%

@jdx jdx merged commit 294e9b2 into main Jun 13, 2026
35 checks passed
@jdx jdx deleted the codex/system-login-shell branch June 13, 2026 05:45
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.

1 participant