Rust project ideas: 12 builds that make ownership click
Good Rust projects are small programs where memory, errors and parallel work matter: a command-line search tool, a diff, a file-format reader, a key-value store with a log, a terminal interface or a proxy. Start with a tool that reads text or bytes and returns clear errors, because that is where the compiler teaches ownership best. Then add a library such as clap, ratatui or Tokio. Each of the twelve below lists crates, concepts, a first version, a stretch goal and a time estimate.
What makes a good Rust project idea?
A good Rust project gives the compiler something to teach you. Programs that move data between owners, return errors you must handle and share state between threads force you to learn ownership, borrowing and lifetimes in context. A project where you copy strings everywhere to avoid the borrow checker teaches the wrong habit.
Before the projects, read the official material. The Rust Programming Language is the standard introduction, and Rustlings is a set of small exercises that get you used to reading and writing Rust code. The projects below assume you have finished the first dozen chapters or equivalent.
| Project kind | Concepts | Typical crates |
|---|---|---|
| Command-line tool | Result, error types, iterators, &str versus String | clap, anyhow or thiserror |
| File-format reader | Byte slices, lifetimes, parsing with nom-style code or by hand | None, or memmap2 |
| Terminal interface | State machines, event loops, trait objects | ratatui, crossterm |
| Async network service | async/await, tasks, channels, cancellation | tokio, hyper |
| Macro or library | Traits, generics, macro hygiene, public API design | syn, quote |
| Embedded or WebAssembly | no_std, targets, foreign interfaces | embedded-hal, wasm-bindgen |
How should you set up a Rust project so the compiler helps?
Rust ships its checks with the toolchain. Run the same four commands before every commit and you will catch most mistakes early.
cargo new project-namecreates the package and a first commit's worth of structure.cargo fmt --checkfails if the formatting differs from the standard style.cargo clippy -- -D warningsruns the linter and turns its warnings into errors.cargo testruns unit tests in your source files and integration tests intests/.
Project: <name from the list> Language: Rust, stable toolchain, edition 2021 or later. Crates allowed: <list>. Nothing else without asking. Build only the FIRST VERSION below. Do not start the stretch goal. First version: <paste it> Rules: - Library code in src/lib.rs, a thin main.rs that only parses arguments and prints. - Return Result from anything that can fail. No unwrap() outside tests. - Prefer borrowing (&str, &[u8]) in function arguments. If you clone to satisfy the borrow checker, add a comment saying why. - Write a failing test before each function with logic. - cargo fmt --check, cargo clippy -- -D warnings and cargo test must all pass. End with: how to run it, three inputs that should fail, and anything you were unsure about.
The last rule in that prompt is the one that matters if an AI tool writes the code: Rust code that compiles is not necessarily code that does what you meant. For the general method, read how to write an app build prompt, and for starting points in every language, coding project ideas.
Which Rust projects suit someone who has just finished the book?
These four are command-line tools. They have one input, one output and plenty of ways to fail, which is the ideal shape for learning Result and borrowed data.
01 Line-search tool with ignore rules
A small grep that searches a folder recursively, prints matching lines with file names and numbers, and skips the files your ignore file lists.
- Stack
- Rust standard library, `clap` for arguments,
regex. - Teaches
- Iterators, error handling, reading files line by line, borrowing from a buffer.
- Time
- 8 to 14 hours.
First version: search one file for a plain string. Stretch goal: recurse through a directory, support regular expressions, skip patterns listed in a .searchignore file, and compare your speed against the system grep on a large source tree. Note where you are slower, then find out why, which is usually unnecessary allocation per line.
02 Dotfile linker
A tool that reads a manifest of config files in your repo and links each into your home directory, with a dry-run mode and a safe undo.
- Stack
clap,serdewith TOML,std::fs,thiserror.- Teaches
- Designing an error enum, file-system edge cases,
PathversusPathBuf, idempotence. - Time
- 10 to 16 hours.
First version: read a TOML manifest, print what it would link, create the symlinks. Stretch goal: back up any existing file before replacing it, an unlink command that restores the backups, and tests that run in a temporary directory. Running it twice must change nothing the second time. Never write outside the directories the manifest names.
03 Torrent file inspector
A command-line tool that decodes a .torrent file and prints the tracker, the file names, sizes and piece count.
- Stack
- Standard library only for the decoder,
sha1crate for the info hash. - Teaches
- Writing a recursive parser over
&[u8], enums for values, lifetimes on borrowed data. - Time
- 8 to 12 hours.
The BitTorrent specification, BEP 3, defines the metainfo format and its encoding. First version: decode integers, byte strings, lists and dictionaries into an enum and print the structure. Stretch goal: compute the info hash, handle multi-file torrents and reject malformed input with a position in the error message. Use files you are allowed to have; the tool reads metadata and downloads nothing.
04 Line diff
A tool that compares two text files and prints the lines added and removed, like a minimal diff.
- Stack
- Standard library,
clap. - Teaches
- Dynamic programming, 2D tables as
Vec<Vec<_>>, slices, writing tests from known cases. - Time
- 10 to 16 hours.
First version: compute the longest common subsequence of lines and print additions with + and removals with -. Stretch goal: group changes into hunks with three lines of context, use Myers' algorithm for memory savings on large files, and add property tests: applying your diff to the first file must give the second. Test on files with no trailing newline.
Which Rust projects add terminals, files and the web?
The intermediate set introduces one new ecosystem each: a terminal interface, filesystem events, WebAssembly and persistent storage. Keep the logic in a library crate and the interface thin so you can test it.
01 Disk-usage browser in the terminal
A full-screen terminal app that scans a folder and lets you move through directories sorted by size.
- Stack
- `ratatui` for the interface,
crossterm,std::fs. - Teaches
- A model-update-view loop, tree data structures in Rust, scanning in a background thread.
- Time
- 20 to 30 hours.
Ratatui is a Rust library for building fast, lightweight, rich terminal user interfaces. First version: scan one folder, show its entries with sizes, move the cursor, enter and leave a directory. Stretch goal: scan in a background thread and update the list as results arrive, show a bar proportional to size and mark entries you cannot read instead of crashing. Test the scanner on a folder you build in a temporary directory.
02 File watcher that reruns your tests
A tool that watches a project folder and runs a command whenever a source file changes, ignoring noise.
- Stack
- `notify` (a cross-platform filesystem notification library),
clap,std::process. - Teaches
- Channels, debouncing, child processes, killing and restarting work.
- Time
- 10 to 18 hours.
First version: run a command on the first change after a quiet period of 200 milliseconds. Stretch goal: cancel a running command when a new change arrives, ignore the target directory and anything in .gitignore, and print a one-line summary of exit code and duration. Editors save in different ways, so test with at least two.
03 Image filter compiled to WebAssembly
A Rust function that applies blur, sharpen or edge detection to image pixels, called from a small web page.
- Stack
- `wasm-bindgen`, a small HTML page, plain JavaScript for the glue.
- Teaches
- Compiling to a different target, passing buffers across a language boundary, benchmarking against JavaScript.
- Time
- 12 to 20 hours.
The wasm-bindgen guide describes the library as the way to facilitate high-level interactions between Wasm modules and JavaScript. First version: an invert-colors function over a byte buffer, called from a page that draws to a canvas. Stretch goal: a convolution blur, a timing comparison with the same filter written in JavaScript on a large picture, and a note on where the boundary cost starts to dominate.
04 Key-value store with a write-ahead log
A persistent store where every write is appended to a log file and an in-memory index points at the latest value for each key.
- Stack
- Standard library,
serdeor hand-written encoding,crc32fastfor checksums. - Teaches
- File I/O, durability, binary encoding, recovering from a half-written record.
- Time
- 20 to 35 hours.
First version: set, get and remove commands, each appended to a log, with the index rebuilt by replaying the log on start. Stretch goal: a checksum per record so a torn write at the end is detected and skipped, and compaction that rewrites the log with only live keys. The test that matters kills the process mid-write and checks that the store reopens.
Which Rust projects are worth building for a portfolio?
These four look like systems work because they are. Each uses a part of the Rust ecosystem that employers and open source maintainers recognise. For how to present a finished project to a reader, see portfolio project ideas.
01 Read-only SQLite file reader
A tool that opens a .db file without SQLite's own library and lists its tables and rows.
- Stack
- Standard library, byte-slice parsing, a test database you create with the
sqlite3tool. - Teaches
- A real binary format, B-trees, variable-length integers, page-based storage.
- Time
- 30 to 50 hours.
SQLite documents its database file format in detail. First version: read the 100-byte header, report the page size and count the tables from the schema page. Stretch goal: walk table B-tree pages, decode records and print every row of a table, then check your output against the sqlite3 command on five databases. Reading is enough; writing is a much larger project.
02 Rate-limiting reverse proxy
A proxy that forwards requests to a backend you run and rejects clients that send too many.
- Teaches
async/await, shared state behindArc<Mutex<_>>, cancellation, backpressure.- Time
- 25 to 40 hours.
First version: forward every request to one backend and copy the response back. Stretch goal: a token bucket per client address, a 429 status with a Retry-After header when it runs out, a health check that stops sending to a dead backend, and a load test showing the limiter holds under a hundred concurrent clients. Test against a backend you run yourself.
03 Builder derive macro
A #[derive(Builder)] macro that generates a builder type with setters and a build() method from any struct.
- Stack
syn,quote,proc-macro2, a separate proc-macro crate.- Teaches
- How the compiler hands your code to a macro as tokens, generating code, good compile-error messages.
- Time
- 15 to 25 hours.
The Rust Reference describes procedural macros, including derive macros, as functions that take token streams and return them. First version: generate setters for every field and a build() that returns Result. Stretch goal: support optional fields with defaults, rename attributes, and a compile error that points at the offending field when someone uses the macro on an enum.
04 Embedded sensor logger
Firmware for a small development board that reads a temperature sensor and reports it over a serial connection.
- Stack
no_stdRust,embedded-haltraits, a supported board and its support crate.- Teaches
- Running with no operating system, peripherals as owned values, interrupts, flashing hardware.
- Time
- 15 to 30 hours plus the board.
The Embedded Rust Book walks through setting up the toolchain and a first program for a supported board. First version: blink an LED, then print a fixed message over serial. Stretch goal: read a temperature sensor once a second, store an average in a ring buffer and expose it with a simple text command. Buy a board the book supports so your first hour goes to Rust, not drivers.
What should you do when the borrow checker blocks you?
| Symptom | Usual cause | Fix to try first |
|---|---|---|
| Cannot borrow as mutable while borrowed | Holding a reference across a mutation | Shorten the borrow, or collect into a new vector first |
| Lifetime may not live long enough | Returning a reference to a local value | Return an owned value, or take the data as an argument |
| Value used after move | Passing ownership into a function | Pass a reference, or clone once on purpose |
| Future cannot be sent between threads | Holding a non-thread-safe value across .await | Drop the value before the await, or use a thread-safe type |
Read the compiler message to the end. Rust errors usually include the suggestion. If an AI tool offers .clone() or Rc<RefCell<_>> on every error, ask it to restructure the data instead; that keeps the lesson.
Where can you find real problems to solve in Rust?
The twelve above are exercises. For something other people want, browse the board of ideas. Command-line and file-handling needs cluster under developer tools, for example a tool that diffs environment variables between two deploys or ranks which unfinished repositories are closest to done. Every idea has a generated build prompt to adapt, and you can post an idea of your own if you would rather someone else built it.
Frequently asked questions
What are good Rust projects for beginners?
Command-line tools that read input and return clear errors: a line-search tool, a dotfile linker, a file-format inspector or a diff. They teach ownership, borrowing and Result without async code or unsafe code. Finish the first chapters of the Rust book and Rustlings exercises before you start.
What can I build with Rust?
Command-line tools, network services, terminal interfaces, WebAssembly modules, embedded firmware, databases and game engines. The language suits programs that need speed and memory safety without a garbage collector. For a first project, a command-line tool is the best fit.
Is Rust good for a portfolio project?
Yes, if the project is finished and explained. A file-format reader checked against a reference tool, a store that survives being killed mid-write or a proxy with a load test shows skills a reader can verify. Include tests, a README and what you measured.
Should I use async Rust for my first project?
No. Start with synchronous command-line tools and learn ownership first. Move to async when the project has real waiting, such as many network connections. Tokio is the usual runtime, and the reverse proxy in this list is a good first async project.
How long does a Rust project take?
Beginner projects take 8 to 16 hours for a first version. Intermediate ones take 10 to 35 hours, and advanced ones 15 to 50. Expect slower progress early because the compiler rejects code that other languages accept. That friction is where the learning happens.
Where do I find Rust project ideas other people need?
Browse the board at Post your build ideas, where people post ideas they will never build. Each has a generated build prompt, so you can add Rust and your chosen crates to it. Developer tools and productivity ideas are often a good fit for command-line programs.
Created with AI assistance and edited for this site. Examples are illustrative and do not represent customer research. About the publisher.