Generate human readable random names.
🚨 Upgrading?
Check the notes on switching from 2.x to 3.x and from 1.x to 2.x.
Petnames are useful when you need to name a large number of resources – like servers, services, perhaps bicycles for hire – and you want those names to be easy to recall and communicate unambiguously. For example, over a telephone compare saying "please restart remarkably-striking-cricket" with "please restart s01O97i4": the former is easier to say and less likely to be misunderstood. Avoiding sequential names adds confidence too: petnames have a greater lexical distance between them, so errors in transcription can be more readily detected.
This crate is both a command-line tool and a Rust library. Dustin Kirkland's petname project is the inspiration for this project. The word lists and the basic command-line UX here are taken from there. Check it out! Dustin maintains packages for Python, and Golang too.
Notable features:
english! (aliased as petnames!) and turkish! (with feature
lang-turkish) macros to statically embed word lists at compile-time.no_std support (see later section).If you have [installed Cargo][install-cargo], you can install rust-petname with
cargo install petname. This puts a petname binary in ~/.cargo/bin, which
the Cargo installation process will probably have added to your PATH.
🍺 Homebrew – You can instead install it from the
allenap/utilstap. The formula is namedrust-petnameand provides the samepetnamecommand:
shellsession $ brew install allenap/utils/rust-petname
The petname binary from rust-petname is mostly drop-in compatible with the
original petname. It has more options and it's stricter when validating
arguments, but for most uses it should behave the same[^differences].
[^differences]:
When using the --dir option, Dustin Kirkland's petname looks for a
file named names.txt whereas this looks for nouns.txt first before
checking for names.txt.
$ petname -h
Generate human readable random names
Usage: petname [OPTIONS] [COMMAND]
Commands:
completions Print a shell completion script to standard output
help Print this message or the help of the given subcommand(s)
Options:
-w, --words <WORDS> Number of words in name [default: 2]
-s, --separator <SEP> Separator between words [default: -]
--language <LANG> Language to generate names in [default: english] [aliases: --lang] [possible values: english, turkish]
--lists <LIST> Use the built-in word lists with small, medium, or large words [default: medium] [possible values: small, medium, large]
-c, --complexity <NUM> Alias for compatibility with upstream; prefer --lists instead
-d, --dir <DIR> Use custom word lists by specifying a directory containing `adjectives.txt`, `adverbs.txt`, and `nouns.txt`
--count <COUNT> Generate multiple names; or use --stream to generate continuously [default: 1]
--stream Stream names continuously
-l, --letters <LETTERS> Maximum number of letters in each word; 0 for unlimited [default: 0]
-a, --alliterate Generate names where each word begins with the same letter
-A, --alliterate-with <LETTER> Generate names where each word begins with the given letter
-u, --ubuntu Alias for compatibility with upstream; prefer --alliterate instead
--seed <SEED> Seed the RNG with this value (unsigned 64-bit integer in base-10)
-h, --help Print help (see more with '--help')
-V, --version Print version
Based on Dustin Kirkland's petname project <https://github.com/dustinkirkland/petname>.
$ petname
unified-platypus
$ petname -s _ -w 3
lovely_notable_rooster
Beyond the default English word lists, rust-petname can generate names in other
languages with their own grammar-aware generators. These are gated behind
per-language features (so the default build stays small) and selected with
--language.
Turkish is available via the lang-turkish feature. It is grammatically simple
for this purpose – no gender, no adjective agreement, adjective-before-noun
order – and it models Turkish's distinctive emphatic reduplication
(pekiştirme), so a two-word name may intensify the adjective morphologically:
$ petname --language turkish --words 2
kıpkırmızı-kedi
$ petname --language turkish --words 3
çok-güzel-yıldız
More languages (Luxembourgish, French, German, …) are planned. Each is a distinct generator, so languages with grammatical gender, agreement, or word-order rules can be modelled properly rather than approximated.
petname completions <SHELL> prints a completion script to standard output, for
bash, zsh, fish, elvish, or powershell. Redirect it to the location
your shell loads completions from, for example:
$ petname completions zsh > ~/.zfunc/_petname
$ petname completions bash > /etc/bash_completion.d/petname
$ petname completions fish > ~/.config/fish/completions/petname.fish
This is an ordinary subcommand, so petname on its own still generates names as
usual. If you installed via Homebrew, the completions are set up for you.
This implementation is considerably faster than the upstream petname:
$ time /usr/bin/petname
fit-lark
real 0m0.038s
user 0m0.032s
sys 0m0.008s
$ time target/release/petname
contiguous-seriema
real 0m0.004s
user 0m0.001s
sys 0m0.002s
These timings are irrelevant if you only need to name a single thing, but if you need to generate 100s or 1000s of names then rust-petname is handy:
$ time { for i in $(seq 1000); do /usr/bin/petname; done; } > /dev/null
real 0m32.058s
user 0m29.360s
sys 0m5.163s
$ time { for i in $(seq 1000); do target/release/petname; done; } > /dev/null
real 0m2.293s
user 0m1.044s
sys 0m1.003s
To be fair, /usr/bin/petname is a shell script. The Go command-line version
(available from the golang-petname package on Ubuntu) is comparable to the Rust
version for speed, but has very limited options compared to its shell-script
ancestor and to rust-petname.
Lastly, rust-petname has a --count option that speeds up generation of names
considerably:
$ time target/release/petname --count=10000000 > /dev/null
real 0m0.785s
user 0m0.767s
sys 0m0.016s
That's ~408,000 (four hundred and eight thousand) times faster, for about 12.7 million petnames a second on this hardware. This is useful if you want to apply an external filter to the names being generated:
$ petname --words=3 --stream | grep 'love.*\bsalmon$'
You can use rust-petname in your own Rust projects with cargo add petname.
no_std supportThere are features that can be selected, and many than can be deselected (since they're enabled by default):
default-rng enables std and std_rng in rand. A couple of convenience
functions depend on this for a default RNG.default-words enables the default word lists. Deselecting this will reduce
the size of compiled artifacts.clap enables the clap command-line argument parser, which is needed to
build the petname binary.clap is not necessary for the library at all, and you
can deselect it, but it is presently a default feature since otherwise it's
inconvenient to build the binary. This will probably change in the future.macros enables the english! macro (and its petnames! alias). It's
required for the default-words feature, but otherwise it can be deselected.lang-turkish (not a default) compiles the Turkish generator and enables
--language turkish. Like the English lists, the built-in Turkish word lists
are embedded only when default-words is also enabled. See
Languages.All of the default features are required to build the command-line utility.
The library can be built without any default features, and it will work in a
no_std environment, like Wasm. You'll need to figure out a
source of randomness, but SmallRng::seed_from_u64 may
be a good starting point.
3.0.1 is purely additive – nothing is required to upgrade, and the default build
is unchanged. It adds non-English generators (see Languages). The
new --language flag (alias --lang) selects the language; the lang-turkish
feature compiles a Turkish generator and makes --language turkish available.
The word-list macro is now english!, with petnames! kept as a
backwards-compatible alias, and a turkish! macro is available when the
lang-turkish feature is enabled.
Version 3.0 brings a few breaking changes to the API, but the command-line is largely unchanged.
--seed, the generated names will differ from
2.x, since rand 0.10 produces different output for the same seed.rand dependency has been bumped from 0.9 to 0.10. If you depend on
rand types (e.g. RngCore, SmallRng) directly in your own code, you will
need to upgrade your rand dependency to match.Generator trait has changed significantly:generate and generate_one methods are gone.Generator<'a> is now just
Generator.generate_into.iter method has been renamed to namer. It now returns a [Namer]
directly instead of Box<dyn Iterator<Item = String>>, so there is no heap
allocation for the iterator itself.Namer] is a new public type (an iterator over generated petnames). It is
generic over the generator type, so Namer<Petnames> and
Namer<Alliterations> are both valid.petnames!
proc macro rather than via build.rs. This is mostly an internal change, but
it does mean that the petname-macros crate is a new compile-time dependency
when the default-words or macros features are enabled.macros feature flag exposes the petnames! proc macro as public API.
It is enabled by default. You can use it to embed custom word lists at compile
time:
rust
let p = petname::petnames!("path/to/my/words");Version 2.0 brought several breaking changes to both the API and the command-line too. Below are the most important:
--complexity <COMPLEXITY> option has been replaced by --lists <LISTS>.--complexity [0,1,2] will still work, but its
availability is not shown in the -h|--help text.--complexity 1). Previously it
was "small" (--complexity 0).--dir <DIR>, nouns are now found in a file
named appropriately DIR/nouns.txt. Previously this was names.txt but this
was confusing; the term "names" is overloaded enough already.nouns.txt is not found, an attempt will be made to
load nouns from names.txt.--count 0 is no longer a synonym for --stream. Use --stream
instead. It's not an error to pass --count 0, but it will result in zero
names being generated.--non-repeating flag is no longer recognised ([#101]).std_rng is now default-rng,default_dictionary is now default-words.names field on the Petnames struct has been renamed to nouns.Petnames::new() is now Petnames::default().Petnames::new(…) now accepts word lists as strings.Names is no longer public. This served as the iterator struct returned by
Petnames::iter(…), but this now hides the implementation details by
returning impl Iterator<Item = String> instead. This also means that
Names::cardinality(&self) is no longer available; use
Petnames::cardinality(&self, words: u8) instead.Petnames::iter_non_repeating has been removed ([#101]).Petnames::generate, Petnames::generate_one, and Petnames::iter have been
extracted into a Generator trait. This must be in scope in order to call
th$ claude mcp add rust-petname \
-- python -m otcore.mcp_server <graph>