Need help with cargo-script?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

551 Stars 33 Forks Other 177 Commits 38 Opened issues


Cargo script subcommand

Services available


Need anything else?

Contributors list

# 163,670
153 commits
# 42,531
7 commits
# 91,260
2 commits
# 34,489
2 commits
# 86,606
2 commits


is a Cargo subcommand designed to let people quickly and easily run Rust "scripts" which can make use of Cargo's package ecosystem. It can also evaluate expressions and run filters.

Some of

's features include:
  • Reading Cargo manifests embedded in Rust scripts.
  • Caching compiled artefacts (including dependencies) to amortise build times.
  • Supporting executable Rust scripts via UNIX hashbangs and Windows file associations.
  • Evaluating expressions on the command-line.
  • Using expressions as stream filters (i.e. for use in command pipelines).
  • Running unit tests and benchmarks from scripts.
  • Custom templates for command-line expressions and filters.


does not work when Cargo is instructed to use a target architecture different to the default host architecture.

Table of contents:


The recommended method for installing

is by using Cargo's
cargo install cargo-script

If you have already installed

, you can update to the latest version by using:
cargo install --force cargo-script

Migrating From Previous Versions

supports migrating data from previous versions. This is not mandatory, but may be preferred. Using
cargo script --migrate-data dry-run
will perform a "dry run", informing you of any applicable migrations. Using the
option will actually perform the migration. The following migrations may be applicable:
  • 0.1 → 0.2: On non-Windows platforms, and when
    is defined, moves the location for cached data from

Cargo Features

The following features are defined:

  • suppress-cargo-output
    (default): if building the script takes less than 2 seconds and succeeds,
    will suppress Cargo's output. Note that this disabled coloured Cargo output on Windows.

Manually Compiling and Installing

requires Rust 1.11 or higher to build. Rust 1.4+ was supported prior to version 0.2.

Once built, you should place the resulting executable somewhere on your

. At that point, you should be able to invoke it by using
cargo script
. Note that you can run the executable directly, but the first argument will need to be

If you want to run

cargo script
from a hashbang on UNIX, or via file associations on Windows, you should also install the
program somewhere on

Self-Executing Scripts

On UNIX systems, you can use

#!/usr/bin/env run-cargo-script
as a hashbang line in a Rust script. If the script file is executable, this will allow you to execute a script file directly.

If you are using Windows, you can associate the

extension (which is simply a renamed
file) with
. This allows you to execute Rust scripts simply by naming them like any other executable or script.

This can be done using the

cargo-script file-association
command (note the hyphen in
). This command can also remove the file association. If you pass
to the
file-assocation install
command, it will also allow you to execute
scripts without having to specify the file extension, in the same way that
files can be used.

If you want to make a script usable across platforms, it is recommended that you use both a hashbang line and give the file a

file extension.


Generally, you will want to use

by invoking it as
cargo script
(note the lack of a hypen). Doing so is equivalent to invoking it as
cargo-script script
supports several other subcommands, which can be accessed by running
directly. You can also get an overview of the available options using the


The primary use for

is for running Rust source files as scripts. For example:
$ echo 'fn main() { println!("Hello, World!"); }' >
$ cargo script
Hello, World!
$ cargo script hello # you can leave off the file extension
Hello, World!

The output of Cargo will be hidden unless compilation fails, or takes longer than a few seconds.

will also look for embedded dependency and manifest information in the script. For example, all of the following are equivalent:
    (code block manifest with UNIX hashbang and
    #!/usr/bin/env run-cargo-script
    //! This is a regular crate doc comment, but it also contains a partial
    //! Cargo manifest.  Note the use of a *fenced* code block, and the
    //! `cargo` "language".
    //! ```cargo
    //! [dependencies]
    //! time = "0.1.25"
    //! ```
    extern crate time;
    fn main() {
        println!("{}", time::now().rfc822z());
    (dependency-only, short-hand manifest):
    // cargo-deps: time="0.1.25"
    // You can also leave off the version number, in which case, it's assumed
    // to be "*".  Also, the `cargo-deps` comment *must* be a single-line
    // comment, and it *must* be the first thing in the file, after the
    // hashbang.
    extern crate time;
    fn main() {
        println!("{}", time::now().rfc822z());

    Note: you can write multiple dependencies by separating them with commas. E.g.

    time="0.1.25", libc="0.2.5"

On running either of these,

will generate a Cargo package, build it, and run the result. The output may look something like:
$ cargo script now
    Updating registry ``
   Compiling winapi-build v0.1.1
   Compiling winapi v0.2.8
   Compiling libc v0.2.30
   Compiling kernel32-sys v0.2.2
   Compiling time v0.1.38
   Compiling now v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/file-now-37cb982cd51cc8b1)
    Finished release [optimized] target(s) in 49.7 secs
Sun, 17 Sep 2017 20:38:58 +1000

Subsequent runs, provided the script has not changed, will likely just run the cached executable directly:

$ cargo script now
Sun, 17 Sep 2017 20:39:40 +1000

Useful command-line arguments:

  • --bench
    : Compile and run benchmarks. Requires a nightly toolchain.
  • --debug
    : Build a debug executable, not an optimised one.
  • --features 
    : Cargo features to pass when building and running.
  • --force
    : Force the script to be rebuilt. Useful if you want to force a recompile with a different toolchain.
  • --gen-pkg-only
    : Generate the Cargo package, but don't compile or run it. Effectively "unpacks" the script into a Cargo package.
  • --test
    : Compile and run tests.


can also run pieces of Rust code directly from the command line. This is done by providing the
option; this causes
to interpret the
 argument as source code instead of as a file path.  For example, code can be executed from the command line in a number of ways:

  • cargo script --dep time --expr "extern crate time; time::now().rfc822z().to_string()"
  • cargo script --dep time=0.1.38 --expr "extern crate time; ..."
    - uses a specific version of
  • cargo script -d time -e "extern crate time; ..."
    - short form of above
  • cargo script -D time -e "..."
    - guess and inject
    extern crate time
    ; this only works when the package and crate names of a dependency match.
  • cargo script -d time -x time -e "..."
    - injects
    extern crate time
    ; works when the names do not match.

The code given is embedded into a block expression, evaluated, and printed out using the

formatter (i.e.

Useful command-line arguments:

  • -d
    : add a dependency to the generated
  • -x
    : inject
    extern crate
    into generated script.
  • -D
    : do both of the above.
  • -t
    : Specify a custom template for this expression (see section on templates).

Stream Filters

You can use

to write a quick stream filter, by specifying a closure to be called for each line read from stdin, like so:
$ cat | cargo script --loop \
    "let mut n=0; move |l| {n+=1; println!(\"{:>6}: {}\",n,l.trim_right())}"
   Compiling loop v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/loop-58079283761aab8433b1)
     1: // cargo-deps: time="0.1.25"
     2: extern crate time;
     3: fn main() {
     4:     println!("{}", time::now().rfc822z());
     5: }

You can achieve a similar effect to the above by using the

flag, which causes the line number to be passed as a second argument to your closure:
$ cat | cargo script --count --loop \
    "|l,n| println!(\"{:>6}: {}\", n, l.trim_right())"
   Compiling loop v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/loop-58079283761aab8433b1)
     1: // cargo-deps: time="0.1.25"
     2: extern crate time;
     3: fn main() {
     4:     println!("{}", time::now().rfc822z());
     5: }

Note that, like with expressions, you can specify a custom template for stream filters.

Environment Variables

The following environment variables are provided to scripts by

    : the base path used by
    to resolve relative dependency paths. Note that this is not necessarily the same as either the working directory, or the directory in which the script is being compiled.
    : the generated package name of the script.
    : the file name of the script (sans file extension) being run. For scripts, this is derived from the script's filename. May also be
    for those invocations.
    : absolute path to the script being run, assuming one exists. Set to the empty string for expressions.


You can use templates to avoid having to re-specify common code and dependencies. You can view a list of your templates by running

cargo-script templates list
(note the hyphen), or show the folder in which they should be stored by running
cargo-script templates show
. You can dump the contents of a template using
cargo-script templates dump NAME

Templates are Rust source files with two placeholders:

for the auto-generated prelude (which should be placed at the top of the template), and
for the contents of the script itself.

For example, a minimal expression template that adds a dependency and imports some additional symbols might be:

// cargo-deps: itertools="0.6.2"
extern crate itertools;
use std::io::prelude::*;
use std::mem;
use itertools::Itertools;

fn main() { let result = { #{script} }; println!("{:?}", result); }

If stored in the templates folder as
, you can use it by passing the name
via the
option, like so:
$ cargo script -t grabbag -e "mem::size_of::>()"

In addition, there are three built-in templates:

, and
. These are used for the
, and
--loop --count
invocation forms. They can be overridden by placing templates with the same name in the template folder. If you have not overridden them, you can dump the contents of these built-in templates using the
templates dump
command noted above.

Known Issues

Issue #50

There is a problem on Windows where

can hang when asking Cargo for the path to a package's compiled executable.
currently works around this by using an older heuristic to guess this path on affected versions. This can, however, lead to
being unable to correctly locate a compiled executable.

If this is a problem,

can be instructed to use the accurate-but-buggy approach by setting the
environment variable to any non-empty string.


Licensed under either of

at your option.


Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.