13 releases (7 breaking)
| 0.8.1 | Feb 28, 2026 |
|---|---|
| 0.8.0 | Oct 26, 2025 |
| 0.7.0 | Aug 14, 2025 |
| 0.6.0 | Jan 20, 2025 |
| 0.2.1 | Jul 30, 2023 |
#52 in Command-line interface
65,277 downloads per month
Used in 44 crates
(40 directly)
32KB
500 lines
clap-stdin 
This library offers two wrapper types for clap Args that help
for cases where values may be passed in via stdin. When an Arg value is to be read
from stdin, the user will pass the commonly used stdin alias: -
MaybeStdin: Used when a value can be passed in via args ORstdinFileOrStdin: Used when a value can be read in from a file ORstdinFileOrStdout: Used to proxy as a writer for either a file ORstdout
MaybeStdin
Example usage with clap's derive feature for a positional argument:
use clap::Parser;
use clap_stdin::MaybeStdin;
#[derive(Debug, Parser)]
struct Args {
value: MaybeStdin<String>,
}
let args = Args::parse();
println!("value={}", args.value);
Calling this CLI:
# using stdin for positional arg value
$ echo "testing" | cargo run -- -
value=testing
Compatible Types
MaybeStdin can wrap any type that matches the trait bounds for Arg: FromStr and Clone
use std::path::PathBuf;
use clap::Parser;
use clap_stdin::MaybeStdin;
#[derive(Debug, Parser)]
struct Args {
path: MaybeStdin<PathBuf>,
}
$ pwd | ./example -
FileOrStdin
Example usage with clap's derive feature for a positional argument:
use clap::Parser;
use clap_stdin::FileOrStdin;
#[derive(Debug, Parser)]
struct Args {
input: FileOrStdin,
}
# fn main() -> anyhow::Result<()> {
let args = Args::parse();
println!("input={}", args.input.contents()?);
# Ok(())
# }
Calling this CLI:
# using stdin for positional arg value
$ echo "testing" | cargo run -- -
input=testing
# using filename for positional arg value
$ echo "testing" > input.txt
$ cargo run -- input.txt
input=testing
Compatible Types
FileOrStdin can wrap any type that matches the trait bounds for Arg: FromStr and Clone
use clap::Parser;
use clap_stdin::FileOrStdin;
#[derive(Debug, Parser)]
struct Args {
path: FileOrStdin<u32>,
}
# Value from stdin
$ wc ~/myfile.txt -l | ./example -
# Value from file
$ cat myfile.txt
42
$ .example myfile.txt
FileOrStdout
Example usage with clap's derive feature for a positional argument:
use std::io::Write;
use clap::Parser;
use clap_stdin::FileOrStdout;
#[derive(Debug, Parser)]
struct Args {
output: FileOrStdout,
}
# fn main() -> anyhow::Result<()> {
let args = Args::parse();
let mut writer = args.output.into_writer()?;
writeln!(&mut writer, "testing");
# Ok(())
# }
Calling this CLI:
# using stdout for positional arg value
$ cargo run -- -
testing
# using filename for positional arg value
$ cargo run -- output.txt
$ cat output.txt
testing
Reading from Stdin without special characters
When using MaybeStdin or FileOrStdin, you can allow your users to omit the "-" character to read from stdin by providing a default_value to clap.
NOTE: This only works with positional args, since clap requires optional args (E.g. using #[arg(long, short)]) to have a value to parse.
use clap::Parser;
use clap_stdin::FileOrStdin;
#[derive(Debug, Parser)]
struct Args {
#[arg(default_value = "-")]
input: FileOrStdin,
}
# fn main() -> anyhow::Result<()> {
let args = Args::parse();
println!("input={}", args.input.contents()?);
# Ok(())
# }
Calling this CLI:
# using stdin for positional arg value
$ echo "testing" | cargo run
input=testing
# using filename for positional arg value
$ echo "testing" > input.txt
$ cargo run -- input.txt
input=testing
Async Support
FileOrStdin and FileOrStdout can also be used with tokio::io::AsyncRead and tokio::io::AsyncWrite respectively, using the tokio feature. See FileOrStdin::contents_async, FileOrStdin::into_async_reader, and FileOrStdout::into_async_writer for examples.
Using MaybeStdin or FileOrStdin multiple times
Both MaybeStdin and FileOrStdin will check at runtime if stdin is being read from multiple times. You can use this
as a feature if you have mutually exclusive args that should both be able to read from stdin, but know
that the user will receive an error if 2+ MaybeStdin args receive the "-" value.
For example, this compiles:
use clap_stdin::{FileOrStdin, MaybeStdin};
#[derive(Debug, clap::Parser)]
struct Args {
first: FileOrStdin,
second: MaybeStdin<u32>,
}
and it will work fine if the stdin alias - is only passed for one of the arguments:
$ echo "2" | ./example FIRST -
But if stdin is attempted to be used for both arguments, there will be no value for the second arg
$ echo "2" | ./example - -
error: invalid value '-' for '<SECOND>': stdin argument used more than once
License
clap-stdin is both MIT and Apache License, Version 2.0 licensed, as found
in the LICENSE-MIT and LICENSE-APACHE files.
Dependencies
~0.1–3.5MB
~62K SLoC