DEV Community

Mashiur Rahman
Mashiur Rahman

Posted on

I Built a Plain-Text Personal Productivity CLI in Rust — and It Lives in Your Terminal Forever

Appending tasks, searching, marking done, and pulling stats — a simple workflow loop with mps.

If you've ever searched different from Notion, grown tired of syncing Todoist with your calendar, or just wanted to jot something down without opening a browser tab — this one's for you.

Meet mps (pronounced just like the letters). Actually mps in this context stands for MonoPsyches — "a single mind." The idea is simple: one place for everything your mind is carrying, like one consciousness holding everything together. Not five apps. With just you, a terminal, and a folder of text files.

It's a plain-text, single-binary CLI for journaling your day: tasks, notes, reminders, work logs, even running notes about people you collaborate with. Everything lives in simple .mps files you can read in any text editor, version-control with git, and keep across places.

cargo install mps-rs
Enter fullscreen mode Exit fullscreen mode

That's it. One command, No subscriptions.


The Story

I've been keeping a daily text file for years. Tasks for the day. Notes from meetings. Reminders to myself. A quick log of what I actually worked on. It started as a Ruby script, grew into a gem I called mps, and eventually I rewrote it in Rust because I wanted a single, fast binary I could drop on any machine and have working in seconds.

The Rust version (mps-rs) is fully backward-compatible with every file I ever wrote with the Ruby version. Not a single file needed to change.


What It Does

Your day, one command at a time

mps                                          # open today's file in $EDITOR
mps list                                     # see what's on your plate
mps list --since monday                      # catch up on the week
Enter fullscreen mode Exit fullscreen mode

Append without opening a file

mps append task "Review the PR" --tags work,backend
mps append note "The edge case only appears under load"
mps append reminder "Team standup" --at 3pm
mps append log "Deep-work session" --start-time 09:00 --end-time 11:30
Enter fullscreen mode Exit fullscreen mode

Or with the short aliases from your config (ttask, aappend):

mps a t "Fix the auth bug" --tags work
Enter fullscreen mode Exit fullscreen mode

Mark things done

mps done task-1
Enter fullscreen mode Exit fullscreen mode

Edit or delete a specific entry

mps edit note-2           # opens just that element's body in $EDITOR
mps delete task-3 --yes   # gone, no file dancing required
Enter fullscreen mode Exit fullscreen mode

Search across your entire archive

mps search "auth"
mps search "design" --since "last week" --type note
Enter fullscreen mode Exit fullscreen mode

Stats and tag charts

mps stats --since monday   # element counts + total log time
mps tags --all             # tag frequency bar chart
Enter fullscreen mode Exit fullscreen mode

Export to JSON or CSV

mps export --format csv --since "20260501" > may.csv
Enter fullscreen mode Exit fullscreen mode

The File Format

This is the whole thing. No binary blobs, no database:

@task[work, backend, status: open]{
  Review the PR
}

@note{
  The auth token expiry edge case only appears under concurrent load.
  Worth a follow-up spike.
}

@reminder[at: 3pm]{
  Team standup
}

@log[work, start: 09:00, end: 11:30]{
  Deep-work session — rewrote the parser
}

@character[name: Dr. Alice, mentor, trusted]{
  Explained the layered caching approach in detail today.
  Would consult again for architecture decisions.
}
Enter fullscreen mode Exit fullscreen mode

Files are named YYYYMMDD.<epoch>.mps and stored in ~/.mps/mps/. You can open any of them directly in your editor, grep through them, pipe them — they're just text.


Five Element Types

Type What it's for
task Something to do. Has open/done status.
note A free-form thought, observation, or decision record.
reminder A time-anchored alert (--at 5pm, --at 09:30).
log A timed work block with start/end times — great for tracking where your day actually went.
character A running monologue about a person — a collaborator, mentor, client. Searchable by name.

The character type is my personal favourite. Instead of scattered CRM notes, I keep one long evolving entry per person. mps list --name "Dr. Alice" shows me everything I've ever noted about our interactions.


Desktop Notifications (Linux)

If you're on Linux and have notify-send, mps can fire desktop alerts when a reminder is due:

mps notify --dry-run    # see what would fire, no side effects
mps daemon install      # set up a systemd user timer that checks every minute
Enter fullscreen mode Exit fullscreen mode

Every morning at 9am (configurable), you can get a briefing of all open tasks — including anything overdue from the past week.


Sync Across Devices

mps autogit   # git add + commit + pull + push
Enter fullscreen mode Exit fullscreen mode

Because the storage directory is a plain git repo, syncing is a one-liner. There's also a .mps.meta sidecar (git-tracked) for cross-device config like notification settings and tag lists, and a .mps.local file (gitignored) for per-machine state like notification history. They stay out of each other's way automatically.


Natural Date Language

Dates work the way you'd say them out loud:

mps list --since monday
mps open yesterday
mps search "deploy" --since "last week"
mps open "3 days ago"
mps open "last friday"
mps export --since "20260501"
Enter fullscreen mode Exit fullscreen mode

Configuration

Drop this in ~/.mps_config.yaml (auto-created on first run):

storage_dir: /home/you/.mps/mps
default_command: list

type_aliases:
  t: task
  n: note
  r: reminder
  l: log

command_aliases:
  a: append
  "+": append
  s: search

notify:
  enabled: true
  task_notify_at: "9am"
  window_minutes: 5
  overdue_days: 7
Enter fullscreen mode Exit fullscreen mode

Now mps + t "Ship the feature" just works.


The Technical Bits (for the curious)

  • Written in Rust, single binary, no runtime dependencies
  • clap for the CLI, chrono for dates, regex + serde + thiserror for the rest
  • 559 unit and integration tests
  • GitHub Actions CI: test on stable + beta Rust, clippy, rustfmt
  • Fully backward-compatible with the original Ruby gem's file format and YAML config (including Ruby symbol-key YAML)
  • Atomic file writes throughout — a crash during mps edit never corrupts your data

Get It

# Install from crates.io
cargo install mps-rs

# Or from source
git clone https://github.com/mash-97/mps-rs
cd mps-rs
cargo install --path .
Enter fullscreen mode Exit fullscreen mode

The binary is called mps.


Contributing

The project is early and there's plenty of room to make it better. If you find a bug, open an issue. If you have an idea, open an issue and let's talk. PRs are welcome — there's a CONTRIBUTING.md with setup instructions and a PR checklist.

Good first places to poke around: tests/fixtures/ for adding new test coverage, and src/commands/ if you want to follow how a command is wired end-to-end.


If you've ever wished your productivity system was just a folder of text files you could grep — this might be it. Give it a try and let me know what you think.

Top comments (0)