<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mashiur Rahman</title>
    <description>The latest articles on DEV Community by Mashiur Rahman (@mash97).</description>
    <link>https://dev.to/mash97</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F609603%2Fe455c3b5-c941-4c03-9191-313e89bc477b.jpeg</url>
      <title>DEV Community: Mashiur Rahman</title>
      <link>https://dev.to/mash97</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mash97"/>
    <language>en</language>
    <item>
      <title>I Built a Plain-Text Personal Productivity CLI in Rust — and It Lives in Your Terminal Forever</title>
      <dc:creator>Mashiur Rahman</dc:creator>
      <pubDate>Sun, 24 May 2026 19:55:30 +0000</pubDate>
      <link>https://dev.to/mash97/i-built-a-plain-text-personal-productivity-cli-in-rust-and-it-lives-in-your-terminal-forever-23bb</link>
      <guid>https://dev.to/mash97/i-built-a-plain-text-personal-productivity-cli-in-rust-and-it-lives-in-your-terminal-forever-23bb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3f20k6ufsqee5xju9mhc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3f20k6ufsqee5xju9mhc.gif" alt="Appending tasks, searching, marking done, and pulling stats — a simple workflow loop with mps." width="720" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Meet &lt;strong&gt;mps&lt;/strong&gt; (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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;.mps&lt;/code&gt; files you can read in any text editor, version-control with git, and keep across places.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;mps-rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. One command, No subscriptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Story
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;mps&lt;/code&gt;, 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.&lt;/p&gt;

&lt;p&gt;The Rust version (&lt;code&gt;mps-rs&lt;/code&gt;) is fully backward-compatible with every file I ever wrote with the Ruby version. Not a single file needed to change.&lt;/p&gt;




&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Your day, one command at a time
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps                                          &lt;span class="c"&gt;# open today's file in $EDITOR&lt;/span&gt;
mps list                                     &lt;span class="c"&gt;# see what's on your plate&lt;/span&gt;
mps list &lt;span class="nt"&gt;--since&lt;/span&gt; monday                      &lt;span class="c"&gt;# catch up on the week&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Append without opening a file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps append task &lt;span class="s2"&gt;"Review the PR"&lt;/span&gt; &lt;span class="nt"&gt;--tags&lt;/span&gt; work,backend
mps append note &lt;span class="s2"&gt;"The edge case only appears under load"&lt;/span&gt;
mps append reminder &lt;span class="s2"&gt;"Team standup"&lt;/span&gt; &lt;span class="nt"&gt;--at&lt;/span&gt; 3pm
mps append log &lt;span class="s2"&gt;"Deep-work session"&lt;/span&gt; &lt;span class="nt"&gt;--start-time&lt;/span&gt; 09:00 &lt;span class="nt"&gt;--end-time&lt;/span&gt; 11:30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with the short aliases from your config (&lt;code&gt;t&lt;/code&gt; → &lt;code&gt;task&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt; → &lt;code&gt;append&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps a t &lt;span class="s2"&gt;"Fix the auth bug"&lt;/span&gt; &lt;span class="nt"&gt;--tags&lt;/span&gt; work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mark things done
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps &lt;span class="k"&gt;done &lt;/span&gt;task-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Edit or delete a specific entry
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps edit note-2           &lt;span class="c"&gt;# opens just that element's body in $EDITOR&lt;/span&gt;
mps delete task-3 &lt;span class="nt"&gt;--yes&lt;/span&gt;   &lt;span class="c"&gt;# gone, no file dancing required&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Search across your entire archive
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps search &lt;span class="s2"&gt;"auth"&lt;/span&gt;
mps search &lt;span class="s2"&gt;"design"&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt; &lt;span class="s2"&gt;"last week"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; note
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stats and tag charts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps stats &lt;span class="nt"&gt;--since&lt;/span&gt; monday   &lt;span class="c"&gt;# element counts + total log time&lt;/span&gt;
mps tags &lt;span class="nt"&gt;--all&lt;/span&gt;             &lt;span class="c"&gt;# tag frequency bar chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Export to JSON or CSV
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; csv &lt;span class="nt"&gt;--since&lt;/span&gt; &lt;span class="s2"&gt;"20260501"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; may.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The File Format
&lt;/h2&gt;

&lt;p&gt;This is the whole thing. No binary blobs, no database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@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.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Files are named &lt;code&gt;YYYYMMDD.&amp;lt;epoch&amp;gt;.mps&lt;/code&gt; and stored in &lt;code&gt;~/.mps/mps/&lt;/code&gt;. You can open any of them directly in your editor, grep through them, pipe them — they're just text.&lt;/p&gt;




&lt;h2&gt;
  
  
  Five Element Types
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;What it's for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;task&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Something to do. Has &lt;code&gt;open&lt;/code&gt;/&lt;code&gt;done&lt;/code&gt; status.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;note&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A free-form thought, observation, or decision record.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reminder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A time-anchored alert (&lt;code&gt;--at 5pm&lt;/code&gt;, &lt;code&gt;--at 09:30&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;log&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A timed work block with start/end times — great for tracking where your day actually went.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;character&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A running monologue about a person — a collaborator, mentor, client. Searchable by name.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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




&lt;h2&gt;
  
  
  Desktop Notifications (Linux)
&lt;/h2&gt;

&lt;p&gt;If you're on Linux and have &lt;code&gt;notify-send&lt;/code&gt;, mps can fire desktop alerts when a reminder is due:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps notify &lt;span class="nt"&gt;--dry-run&lt;/span&gt;    &lt;span class="c"&gt;# see what would fire, no side effects&lt;/span&gt;
mps daemon &lt;span class="nb"&gt;install&lt;/span&gt;      &lt;span class="c"&gt;# set up a systemd user timer that checks every minute&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every morning at &lt;code&gt;9am&lt;/code&gt; (configurable), you can get a briefing of all open tasks — including anything overdue from the past week.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sync Across Devices
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps autogit   &lt;span class="c"&gt;# git add + commit + pull + push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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




&lt;h2&gt;
  
  
  Natural Date Language
&lt;/h2&gt;

&lt;p&gt;Dates work the way you'd say them out loud:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mps list &lt;span class="nt"&gt;--since&lt;/span&gt; monday
mps open yesterday
mps search &lt;span class="s2"&gt;"deploy"&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt; &lt;span class="s2"&gt;"last week"&lt;/span&gt;
mps open &lt;span class="s2"&gt;"3 days ago"&lt;/span&gt;
mps open &lt;span class="s2"&gt;"last friday"&lt;/span&gt;
mps &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt; &lt;span class="s2"&gt;"20260501"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Drop this in &lt;code&gt;~/.mps_config.yaml&lt;/code&gt; (auto-created on first run):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;storage_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/home/you/.mps/mps&lt;/span&gt;
&lt;span class="na"&gt;default_command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;list&lt;/span&gt;

&lt;span class="na"&gt;type_aliases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;t&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;task&lt;/span&gt;
  &lt;span class="na"&gt;n&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;note&lt;/span&gt;
  &lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;reminder&lt;/span&gt;
  &lt;span class="na"&gt;l&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;log&lt;/span&gt;

&lt;span class="na"&gt;command_aliases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;append&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;append&lt;/span&gt;
  &lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;search&lt;/span&gt;

&lt;span class="na"&gt;notify&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;task_notify_at&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9am"&lt;/span&gt;
  &lt;span class="na"&gt;window_minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
  &lt;span class="na"&gt;overdue_days&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;mps + t "Ship the feature"&lt;/code&gt; just works.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Technical Bits (for the curious)
&lt;/h2&gt;

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




&lt;h2&gt;
  
  
  Get It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install from crates.io&lt;/span&gt;
cargo &lt;span class="nb"&gt;install &lt;/span&gt;mps-rs

&lt;span class="c"&gt;# Or from source&lt;/span&gt;
git clone https://github.com/mash-97/mps-rs
&lt;span class="nb"&gt;cd &lt;/span&gt;mps-rs
cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The binary is called &lt;code&gt;mps&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/mash-97/mps-rs" rel="noopener noreferrer"&gt;https://github.com/mash-97/mps-rs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Crates.io: &lt;a href="https://crates.io/crates/mps-rs" rel="noopener noreferrer"&gt;https://crates.io/crates/mps-rs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; with setup instructions and a PR checklist.&lt;/p&gt;

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




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

</description>
      <category>rust</category>
      <category>productivity</category>
      <category>cli</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Ran Out of Ideas</title>
      <dc:creator>Mashiur Rahman</dc:creator>
      <pubDate>Tue, 06 Apr 2021 18:01:19 +0000</pubDate>
      <link>https://dev.to/mash97/ran-out-of-ideas-543o</link>
      <guid>https://dev.to/mash97/ran-out-of-ideas-543o</guid>
      <description>&lt;p&gt;As a newbie dev, I'm looking for partners to work together. You know I feel like unmotivated right now for some unknown reasons. So I thought of changing the pace by meeting with some new people who feel the same. By working on some not-real-world-project or silly ideas together, we can learn how to work in collaboration. We can also share some new ideas together!&lt;/p&gt;

</description>
      <category>python</category>
      <category>ruby</category>
      <category>github</category>
      <category>meetnewpeople</category>
    </item>
  </channel>
</rss>
