Skip to content

Implement cargo new --script - #17627

Draft
tomassedovic wants to merge 6 commits into
rust-lang:masterfrom
tomassedovic:cargo-new-script
Draft

tomassedovic wants to merge 6 commits into
rust-lang:masterfrom
tomassedovic:cargo-new-script

Conversation

@tomassedovic

@tomassedovic tomassedovic commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR try to resolve?

This adds a new --script flag to the unstable script feature (the flag is behind the same feature flag).

With it, cargo new --script script.rs will create a script.rs file with the following contents:

#!/usr/bin/env -S cargo +nightly -Zscript
---
package.edition = "2024"
[dependencies]
---
fn main() {
    println!("Hello, world!");
}

This makes it a little easier to create cargo scripts. By specifying the edition, the script will run with no warning and provide basic front matter scaffolding.

Notes to reviewers

Partially implements: #16849

This is related to the cargo script stabilisation effort (project goal: rust-lang/goals#119), but not a blocker.

It aims to improve the end-user experience for creating new scripts -- especially depending on how exactly will the edition discussion be resolved (rust-lang/rust#152254).

I fixed the obvious CI failures, but haven't added new tests nor fixed the UI ones yet.

At this point, it's a proof-of-concept for a feature that's not been accepted yet (cargo#16849). I'd love to hear from the maintainers whether it's worth doing this now/ever (I use use cargo script and wished this existed).

If so, I'm happy to work out the final shape and push it forward.


🤖 LLM involvement: no LLM/AI was (knowingly) used anywhere in the process of working on this feature.

This will create a new "cargo script" file. It's a single file ending with `.rs`
which can be run with `cargo <file>`.

The contents of the file are a hello world example as well as a front matter
manifest that includes the current edition and an empty `dependencies` section.
It doesn't make sense for `cargo init`.
Previously, we generated:

```
[package]
edition = "2024"
```

which is needlessly verbose compared to the new:

```
package.edition = "2024"
```
@rustbot rustbot added A-cli Area: Command-line interface, option parsing, etc. Command-new S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 23, 2026
@rustbot

rustbot commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

r? @Muscraft

rustbot has assigned @Muscraft.
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

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @Muscraft, @epage, @weihanglo
  • @Muscraft, @epage, @weihanglo expanded to Muscraft, epage, weihanglo
  • Random selection from Muscraft, epage, weihanglo

)
.arg_new_opts()
// NOTE: add the flag here instead of `arg_new_opts`, because it makes no sense for `cargo init`
// TODO: show the flag in `cargo help new`

@tomassedovic tomassedovic Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I haven't figured out how to make this show in help yet. Waiting to see if this work is even desirable (now) before figuring that out.

I'll be grateful for pointers of course.

View changes since the review

Comment thread src/ops/cargo_new.rs
(_, false) => NewProjectKind::Bin,
let kind = match (bin, lib, script) {
(true, true, _) | (_, true, true) | (true, _, true) => {
anyhow::bail!("must specify exactly one of: lib, bin or script outputs")

@tomassedovic tomassedovic Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This function is called from both cargo new and cargo init, but --script makes no sense in cargo init (I think).

So this error message will be appropriate in cargo new, but less so in cargo init.

Do we want to print a different error in either case?

View changes since the review

Comment thread src/ops/cargo_new.rs
let cfg = gctx.get::<CargoNewConfig>(["cargo-new"])?;

// TODO: cleaner way to detect it's a script? E.g. by passing the `kind` to `MkOptions`?
let is_script = name.ends_with(".rs") && opts.source_files.is_empty();

@tomassedovic tomassedovic Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do we want to support creating files that don't end with .rs (or any extension)?

The likely use case would be "regular" unix scripts relying on the executable permission and shebang.

View changes since the review

Comment thread src/ops/cargo_new.rs
None => Edition::LATEST_STABLE.to_string(),
};
manifest["package"]["edition"] = toml_edit::value(edition);
manifest["package"]["edition"] = toml_edit::value(&edition);

@tomassedovic tomassedovic Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Note, this is to prevent an error saying edition was moved here.

View changes since the review

Comment thread src/ops/cargo_new.rs
if is_script {
let default_script_content = format!(
"\
#!/usr/bin/env -S cargo +nightly -Zscript

@tomassedovic tomassedovic Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This shebang targets rustup-installed cargo. It wouldn't work with cargo installed as an OS package or user-compiled cargo.

I'm assuming that while the feature is unstable, most nightly users use rustup so this is the right default before stabilisation.

What do you think?

View changes since the review

Comment thread src/ops/cargo_new.rs
"\
#!/usr/bin/env -S cargo +nightly -Zscript
---
package.edition = \"{}\"

@tomassedovic tomassedovic Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I opted for the shorter syntax (instead of specifying the [package] table.

Happy to change that if desirable.

View changes since the review

Comment thread src/ops/cargo_new.rs
#!/usr/bin/env -S cargo +nightly -Zscript
---
package.edition = \"{}\"
[dependencies]

@tomassedovic tomassedovic Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This also differs from what the issue proposes, but I think it's more convenient for the end-user.

It (a) shows that dependencies can be specified and (b) makes it easier to do so at the cost of an extra line.

View changes since the review

@tomassedovic

Copy link
Copy Markdown
Contributor Author

I don't want to override a reviewer just yet, but @epage should be at least aware, given his involvement in cargo script.

@tomassedovic
tomassedovic marked this pull request as draft October 23, 2026 14:04
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 23, 2026
@epage

epage commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

At this point, it's a proof-of-concept for a feature that's not been accepted yet (cargo#16849). I'd love to hear from the maintainers whether it's worth doing this now/ever (I use use cargo script and wished this existed).

Note that that is a conversation for the Issue.

@tomassedovic

Copy link
Copy Markdown
Contributor Author

Thank you, I posted the comments there.

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

A-cli Area: Command-line interface, option parsing, etc. Command-new

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants