Building a Real Notes CLI App with Rust — From Scratch to Exporting PDF

🧠 Why I Built This Project
As a software engineer diving deeper into Rust, I wanted more than tutorials — I needed something real. I chose to build a command-line app for managing notes: something useful, practical, and just complex enough to explore Rust's true power.
🚀 What This CLI App Does
This isn't your basic "Hello, world!" project. Here's what my Notes CLI tool can do:
Add structured notes with a title, body, and tags
Track created and updated timestamps
Search by tag or keyword
Export all notes to PDF, CSV, or Markdown
Automatically open the PDF after exporting
Everything runs in the terminal, powered by Rust and a clean modular codebase.
🦀 Rust Concepts I Practiced
I didn't just build an app — I learned the language:
✅ struct and enum
Used for representing notes, user status, and CLI command types. Rust makes it easy (and fun) to model your data clearly.
✅ clap
My CLI parser of choice. clap made it elegant to define arguments like --add-note, --export-pdf, or --search-tag.
✅ serde + serde_json
These two made serializing notes into JSON a breeze — and loading them back just as easy.
✅ chrono
For managing timestamps: when a note was created, and when it was last updated.
✅ File I/O
Reading and writing .json, .csv, .md, and even generating .pdf — I used std::fs, OpenOptions, and Rust's amazing safety net to keep file operations solid.
🔥 Cool Features I’m Proud Of
--open-pdf — after export, the file opens automatically depending on your OS
Structured JSON notes with IDs, timestamps, and tags
--search-tag and --search let you filter notes in real time
Auto-generated PDFs with Arabic text support (using custom fonts)
💥 What Was Hard
PDF Generation with Arabic
Getting genpdf to work with Arabic fonts was tricky. The default fonts don’t support RTL languages, so I had to bundle in a proper font like Amiri and load it manually.
Ownership + Borrowing
I thought I understood ownership until I started passing structs around. It took some trial and error, and a lot of & vs &mutmoments, but I finally got it.
CLI Design
Making a CLI app feel "usable" and not like a bunch of flags glued together took some planning. Having --add-note, --search-tag, --export-pdf, and --delete-note as separate pathways made it easier to maintain and test.
📦 Libraries Used
clap – CLI argument parsing
serde + serde_json – for note storage
chrono – time tracking
csv – export to spreadsheets
genpdf – PDF generation with custom fonts
🧾 Final Thoughts
This project taught me more about Rust than any tutorial could. It made abstract concepts real. Now, when I see impl, Result, match, or a lifetimed reference, I know what it means — and I know I’ve built something real with it.
If you’re learning Rust and want to make something useful, build a CLI tool. You’ll get hands-on with the core of the language and end up with a project that’s truly yours.
🔗 Check it out: github.com/RawanAlrajeh/user-cli-rust
Built with ❤️ by Rawan Alrajeh
Subscribe to my newsletter
Read articles from Rawan Alrajeh directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Rawan Alrajeh
Rawan Alrajeh
Front-End Developer with a passion for building clean, responsive interfaces. I love challenging myself with new technologies and creating projects that blend creativity and structure. Always learning, always building.