Skip to content

Stabilize cargo script#16569

Open
epage wants to merge 3 commits intorust-lang:masterfrom
epage:script-stable
Open

Stabilize cargo script#16569
epage wants to merge 3 commits intorust-lang:masterfrom
epage:script-stable

Conversation

@epage
Copy link
Contributor

@epage epage commented Jan 30, 2026

Fixes #12207

RFC: https://rust-lang.github.io/rfcs/3502-cargo-script.html
Tracking issue: #12207
Frontmatter stabilization: rust-lang/rust#148051

This stabilizes an MVP of Cargo script

  • Cargo scripts are Rust source files without an extension or with a .rs extension
  • They may have a frontmatter block with manifest content
  • Changes from Cargo.toml
    • package.name is optional, defaults to the file stem
    • package.edition defaults to current edition, not 2015 edition, with a warning
    • package.build, package.links, package.default-run, package.workspace, package.auto-* are disallowed
    • workspace, build-dependencies, and any build-target tables are disallowed
    • Workspace auto-discovery does not run
  • package.name defaulting logic
    • strips leading numbers
      • If nothing left after this, calls it package
    • replaces non-UnicodeXID characters with - or _
    • commonly reserved names are allowed:
      • windows names, like con
      • sysroot names, like test
      • keywords, like self
    • disallowed names on a short-term basis:
      • build-dir directories like deps
  • cargo foo precedence:
    1. built-in command
    2. script if there is a .rs extension or a path component is present (e.g. ./foo )
    3. aliases
    4. plugins
  • Command support:
    • cargo install errors on publishing a script
    • cargo package errors on publishing a script
    • cargo publish errors on publishing a script
  • Script metadata
    • arg0 is set on a best-effort basis to the script's path
    • CARGO_MANIFEST_PATH was previously stabilized in addition to the existing CARGO_MANIFEST_DIR
  • cargo foo.rs loads config relative to foo
  • Pseudo-config defaults
    [build]
    build-dir = "{cargo-cache-home}/build/{workspace-path-hash}"
    target-dir = "{build-dir}/target"
    [resolver]
    lockfile-path = "{build-dir}/{workspace-path-hash}/Cargo.lock"

Whats missing:

  • rustfmt styling frontmatter according to the Style Guide
  • rust-analyzer handling manifest in frontmatter
  • playground support

Known issues:

Risks

  • If people share their build-dir across projects, then multiple scripts will point to the same Cargo.lock, fighting over what is locked in it (fix(script): Make the lockfile script-specific independent of build-dir #16619)
  • Not allowing local config for scripts could become a problem as we get into workspace support as people would expect their repo's config to be respected when it won't be (fix(script): Load config relative to the script #16620)
  • Changing package name rules impacts programmatic output
  • Precedence rules for cargo foo
    • In particularly, requiring an extension or path element should be safe, especially for most uses of shebang but you can intentionally contrive a shebang and PATH that makes this not work

Future possibilities

@epage epage added the T-cargo Team: Cargo label Jan 30, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 30, 2026

r? @weihanglo

rustbot has assigned @weihanglo.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-build-execution Area: anything dealing with executing the compiler A-cli Area: Command-line interface, option parsing, etc. A-cli-help Area: built-in command-line help A-documenting-cargo-itself Area: Cargo's documentation A-manifest Area: Cargo.toml issues A-unstable Area: nightly unstable support Command-run S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 30, 2026
@epage epage marked this pull request as draft January 30, 2026 14:32
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 30, 2026
Comment on lines 99 to 100
match manifest_path.is_file() {
true => {}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cleaned up in the next commit

Comment on lines +797 to 798
// TODO: remove once frontmatter hits nightly
if unit.pkg.manifest().is_embedded() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Blocked on rust-lang/rust#148051 hitting nightly

Comment on lines +847 to 848
// TODO: remove once frontmatter hits nightly
if unit.pkg.manifest().is_embedded() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Blocked on rust-lang/rust#148051 hitting nightly

@epage epage marked this pull request as ready for review January 30, 2026 15:39
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 30, 2026
@epage
Copy link
Contributor Author

epage commented Jan 30, 2026

@rfcbot fcp merge T-cargo

For me, my biggest concerns are the first two Risks listed.

@rust-rfcbot
Copy link
Collaborator

rust-rfcbot commented Jan 30, 2026

Team member @epage has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period An FCP proposal has started, but not yet signed off. disposition-merge FCP with intent to merge labels Jan 30, 2026
Copy link
Member

@weihanglo weihanglo left a comment

Choose a reason for hiding this comment

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

Should we inform rustfmt team that we're going to stabilize this and leave frontmatter style issue unresolved? I remembered that let-else has caused confusions and frustrations when we stabilized it in the language syntax side but rustfmt didn't format it: rust-lang/rustfmt#4914.

At least the rustfmt team should be aware of the potential incoming volume of issues regarding this.

View changes since this review

in the [TOML] format. It contains metadata that is needed to compile the package. Checkout
the `cargo locate-project` section for more detail on how cargo finds the manifest file.

The content of the manifest can also be embedded inside of the frontmatter inside of a Rust source file:
Copy link
Member

Choose a reason for hiding this comment

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

Not a blocker but not satisfied with the current stable doc. I would love to see a dedicated section for Cargo scripts with some examples, and all other mentions of "script" to link back to that section. Currently it is a bit not obvious when it is mentioned.

The original unstable docs has some good stuff in it but maybe it depends on many stuff we want to commit as "stable"

(Or it was migrated to elsewhere? The diff is too large that I could have missed it)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was unsure how to handle it. A guide? If so, where does it fit in. A reference? Does it get its own page or a section on manifests?

Copy link
Member

Choose a reason for hiding this comment

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

Or a reference-like doc in src/doc/man/cargo.md, and we have another standalone guide? In manifest is not too bad but script is more than manifest.

@weihanglo
Copy link
Member

rustfmt styling frontmatter according to the Style Guide

rust-analyzer handling manifest in frontmatter

playground support

All these teams actually

@weihanglo
Copy link
Member

Pseudo-config defaults

This is worth calling out in user doc that whether the target directory of script is considered implementation details.

@epage
Copy link
Contributor Author

epage commented Jan 31, 2026

Should we inform rustfmt team that we're going to stabilize this and leave frontmatter style issue unresolved? I remembered that let-else has caused confusions and frustrations when we stabilized it in the language syntax side but rustfmt didn't format it: rust-lang/rustfmt#4914.

At least the rustfmt team should be aware of the potential incoming volume of issues regarding this.

View changes since this review

This was handled as part of the Frontmatter stabilization.

in the [TOML] format. It contains metadata that is needed to compile the package. Checkout
the `cargo locate-project` section for more detail on how cargo finds the manifest file.

The content of the manifest can also be embedded inside of the frontmatter inside of a Rust source file:
Copy link
Member

Choose a reason for hiding this comment

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

Or a reference-like doc in src/doc/man/cargo.md, and we have another standalone guide? In manifest is not too bad but script is more than manifest.

github-merge-queue bot pushed a commit that referenced this pull request Feb 3, 2026
### What does this PR try to resolve?

This is to make space for discussing scripts, see #16569

### How to test and review this PR?
@ehuss ehuss moved this to FCP merge in Cargo status tracker Feb 3, 2026
@nicoburns
Copy link
Contributor

nicoburns commented Feb 6, 2026

If we stabilise cargo foo shorthand, would that prevent further additions to that namespace in future?

This is subjective, but it feels to me like an "impl trait in argument position" situation where a more controversial extension of a feature is slipping into the stabilisation of an overwhelmingly popular feature.

I wonder whether it might be best to omit this from the initial stabilisation. cargo run foo.rs isn't that bad in the short term (but if there are no backwards compat hazards then I guess it's fine).

@epage
Copy link
Contributor Author

epage commented Feb 6, 2026

cargo <path> requires either

  • <path> to have a .rs extension
  • <path> to have path separators

cargo run path

  • would be a breaking change as positional arguments get forwarded
  • would require a non-standard env extension, like -S

Copy link
Contributor

@ehuss ehuss left a comment

Choose a reason for hiding this comment

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

IIUC, it's not possible to have a script as a member of workspace. Is that correct? Is there a strategy for allowing that in the future?

For now, what is the intended way for users to clean the build directories? Is it cargo clean --manifest-path=script.rs?

View changes since this review

- The file name is `Cargo.toml`

Differences between `cargo run --manifest-path <path>` and `cargo <path>`
- `cargo <path>` runs with the config for `<path>` and not the current dir, more like `cargo install --path <path>`
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a little confused on this. This says that cargo <path> loads the config from the given path. But the PR description says it loads from CARGO_HOME. Which is it?

@rust-rfcbot rust-rfcbot added final-comment-period FCP — a period for last comments before action is taken and removed proposed-final-comment-period An FCP proposal has started, but not yet signed off. labels Feb 10, 2026
@rust-rfcbot
Copy link
Collaborator

🔔 This is now entering its final comment period, as per the review above. 🔔

@rustbot

This comment has been minimized.

@epage
Copy link
Contributor Author

epage commented Feb 10, 2026

IIUC, it's not possible to have a script as a member of workspace. Is that correct? Is there a strategy for allowing that in the future?

Workspace support is deferred out. My plan had been for us to check files among workspace membes but that was before I knew about #8511 as my last knowledge on this was that cargo errored for anything that matched the glob that wasn't a valid.

I don't see this affecting us now but it does mean that more work will be needed to figure out workspace support

For now, what is the intended way for users to clean the build directories? Is it cargo clean --manifest-path=script.rs?

Yes. There is an issue for us to GC unused build-dirs (as in the entire directory) but figured that was not blocking. I'll call this out in the stabilization report.

@ehuss
Copy link
Contributor

ehuss commented Feb 10, 2026

For workspaces, a concern I had was about auto-discovery. If in the future we decide to support workspaces and cargo did auto-discovery if a script is inside a workspace, then that would be a change that could be difficult to transition. It would be incompatible with older versions, and would cause Cargo.lock churn when switching cargo versions.

If it is intended to only be opt-in (like via a frontmatter field), then that should be fine. I'm not sure if there are downsides with that. Opt-in via workspace.members might be a problem due to #16611, since it would have the same problem as auto-discovery.

I just wanted to make sure we don't accidentally lock ourselves into a particular solution we didn't plan for.

@epage
Copy link
Contributor Author

epage commented Feb 10, 2026

If it is intended to only be opt-in (like via a frontmatter field), then that should be fine. I'm not sure if there are downsides with that. Opt-in via workspace.members might be a problem due to #16611, since it would have the same problem as auto-discovery.

My assumption has been that we will not auto-discover the workspace for a script but instead users will need to opt-in to a workspace through package.workspace = "..." or package.workspace = true (#16563).

@ehuss
Copy link
Contributor

ehuss commented Feb 11, 2026

What is (or will be) the intended behavior of workspace.members pointing to a script?
I'm trying to think of the consequences (particularly in light of #16611) of how we can transition to workspace support.

@rustbot

This comment has been minimized.

@epage
Copy link
Contributor Author

epage commented Feb 12, 2026

What is (or will be) the intended behavior of workspace.members pointing to a script? I'm trying to think of the consequences (particularly in light of #16611) of how we can transition to workspace support.

I posted #16633 to make the existing behavior explicit.

My comment at #16569 (comment) about #8511 equally applies to #16611

I don't see this affecting us now but it does mean that more work will be needed to figure out workspace support

We'll need some way to mention them as workspace members. Off the top of my head, some ideas I came up with are

  • Finally doing workspace editions
  • Seeing what behavior we are comfortable changing without editions
  • Having some other field that either toggles behavior or mentions them

I had gone into all of this with pre- #8511 knowledge and #8511 and #16611 dramatically change what we can do.

@epage epage force-pushed the script-stable branch 2 times, most recently from 8c6298b to e1bbe62 Compare February 12, 2026 19:41
@rustbot
Copy link
Collaborator

rustbot commented Feb 13, 2026

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

github-merge-queue bot pushed a commit that referenced this pull request Feb 13, 2026
### What does this PR try to resolve?

Inspired by the conversation at
#16569 (comment)

### How to test and review this PR?
@rustbot
Copy link
Collaborator

rustbot commented Feb 13, 2026

☔ The latest upstream changes (possibly ba739a5) made this pull request unmergeable. Please resolve the merge conflicts.

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

Labels

A-build-execution Area: anything dealing with executing the compiler A-cli Area: Command-line interface, option parsing, etc. A-cli-help Area: built-in command-line help A-documenting-cargo-itself Area: Cargo's documentation A-manifest Area: Cargo.toml issues A-unstable Area: nightly unstable support Command-run disposition-merge FCP with intent to merge final-comment-period FCP — a period for last comments before action is taken S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-cargo Team: Cargo

Projects

Status: FCP merge

Development

Successfully merging this pull request may close these issues.

Tracking Issue for cargo-script RFC 3424

6 participants