mps-rs 1.1.0

MPS — plain-text personal productivity CLI (Rust)
Documentation

mps

A plain-text personal productivity CLI. Append journal entries, tasks, reminders, logs, and notes to daily .mps files; search, list, and export them; sync via git. Single binary, no runtime dependencies.

Rust rewrite of mps (Ruby). Fully backward-compatible with all Ruby-generated files and config.


Install

cargo install mps-rs

The installed binary is named mps.

From source

git clone https://github.com/mash-97/mps-rs
cd mps-rs
cargo install --path .

Quick start

mps                                          # open today's file in $EDITOR
mps list                                     # print today's elements
mps list --since monday                      # all elements since last Monday
mps append task "Fix the auth bug" --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
mps append character "Helped me think through the design" --name "Dr. Alice" --tags mentor
mps done task-1                              # mark task-1 done
mps search "auth" --since "last week"
mps stats --since monday
mps export --format csv --since "20260501" > may.csv
mps autogit                                  # stage + commit + pull + push

Element types

Type Description
task Something to do, with open/done status
note Free-form observation or thought
reminder Time-anchored alert
log Timed work block (start/end time → duration)
character Running monologue about a person

Commands

mps [open] [DATE]

Open the .mps file for DATE in $EDITOR (falls back to vim). Creates the file if absent.

mps                   # today
mps open yesterday
mps open last friday

mps list [DATE]

Print elements for DATE as an indented tree.

Flag Short Description
--type TYPE -t Filter by type: task, note, log, reminder, character
--tag TAG -g Filter by tag name
--status STATUS -s Filter tasks by open or done (hides all non-task elements)
--name NAME -n Filter character entries by person name
--since DATE -S Show elements from DATE up to the target date
--refs -r Show human-readable ref column (task-1, mps-1.2, …)
--all -a List across the entire archive, not just one date
mps list
mps list --type task --status open
mps list --since monday --refs
mps list --all --name "Dr. Alice"

mps append TYPE BODY [FLAGS]

Append one element to today's file without opening an editor. TYPE is resolved through type_aliases from config (e.g. ttask).

Flag Description
--tags t1,t2 Comma-separated tags
--status open|done Task status (default: open)
--at TIME Time for reminders (5pm, 10:30, …)
--start-time HH:MM Start time for logs
--end-time HH:MM End time for logs
--name NAME -n Person name for character entries
mps append task "Review the PR" --tags work,backend
mps append note "Cache invalidation approach"
mps append reminder "1:1 with manager" --at 2pm
mps append log "Debugging session" --start-time 14:00 --end-time 16:30
mps append character "Explained the system clearly" --name "Mahfuz Vai" --tags mentor,work
mps append task "Write tests" --status done --tags ci

mps update REFPATH [FLAGS]

Update one element's attributes in-place. REFPATH is a human ref (task-1, mps-1.2) or an epoch ref (20260428.1732500287.1).

Flag Description
--status open|done Set task status
--start-time HH:MM Set log start time
--end-time HH:MM Set log end time
--at TIME Set reminder time
--date DATE -d Date context for human refs (default: today)
mps update task-1 --status done
mps update mps-1.2 --end-time 17:00
mps update task-3 --status done --date yesterday

mps done REFPATH [--date DATE]

Shorthand for mps update REFPATH --status done.

mps done task-1
mps done task-2 --date yesterday

mps search QUERY [FLAGS]

Full-text search across all .mps files. Returns matching elements with date and ref.

Flag Short Description
--type TYPE -t Filter by element type
--tag TAG -g Filter by tag
--name NAME -n Filter character entries by person name
--since DATE -S Search from DATE onward
mps search "auth"
mps search "design" --type character --name "Dr. Alice"
mps search "deploy" --since "last week" --type log

mps stats [DATE] [FLAGS]

Show element counts and total log durations.

Flag Short Description
--since DATE -S Stats from DATE up to target date
--all -a Stats across the entire archive
mps stats
mps stats --since monday
mps stats --all

mps tags [DATE] [FLAGS]

Show tag usage as a frequency bar chart.

Flag Short Description
--type TYPE -t Count tags for this element type only
--status STATUS -s Restrict to tasks with this status
--name NAME -n Restrict to character entries for this person
--since DATE -S Tags from DATE up to target date
--all -a Count across the entire archive
mps tags
mps tags --all --type task --status open
mps tags --since monday --name "Dr. Alice"

mps export [DATE] [FLAGS]

Export elements to stdout as JSON or CSV.

Flag Short Description
--format json|csv -f Output format (default: json)
--type TYPE -t Filter by element type
--since DATE -S Export from DATE up to target date

CSV columns: date, ref, type, tags, body, status, at, start, end, name

mps export --format json
mps export --format csv --since "20260501" > may.csv
mps export --since monday --type log

mps config [show|edit]

View or edit configuration.

mps config         # same as mps config show
mps config show
mps config edit    # opens config file in $EDITOR

mps git ARGS / mps autogit / mps cmd ARGS

Run git or shell commands inside the storage directory.

mps git status
mps git auto          # add . + commit + pull + push
mps git autocommit    # add . + commit only
mps autogit           # same as mps git auto
mps cmd ls -la        # any shell command in storage dir

mps version

Print the version string.


File format

Files are named YYYYMMDD.<epoch>.mps (or YYYYMMDD.mps for files without an epoch). The format is identical to the Ruby gem — no migration needed.

@task[work, release, status: done]{
  Ship the API refactor
}

@note{
  The auth token expiry edge case only appears under concurrent load
}

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

@log[work, start: 09:00, end: 11:30]{
  Debugging the auth flow
}

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

@mps[sprint-42]{
  @task[backend]{
    Nested task inside a sprint block
  }
  @note{
    Retrospective note
  }
}

Brackets are optional — @task{ body } is valid. Tags and named attributes share the bracket: [tag1, tag2, status: done, at: 5pm].


Date formats

Accepted everywhere a DATE is expected:

Input Meaning
today Today
yesterday Yesterday
mondaysunday Most recent occurrence of that weekday
last friday The Friday before the most recent one
3 days ago 3 days before today
last week 7 days ago
20260421 Explicit YYYYMMDD
2026-04-21 Explicit YYYY-MM-DD

Configuration

Config file: ~/.mps_config.yaml. Created automatically on first run. The same file written by the Ruby gem is accepted without changes (Ruby symbol-key YAML like :storage_dir: is handled transparently).

mps_dir: /home/you/.mps
storage_dir: /home/you/.mps/mps
log_file: /home/you/.mps/mps.log
git_remote: origin
git_branch: master
default_command: list    # command run by bare `mps` invocation (open or list)

# Short-hand element type aliases (also accepts legacy key: aliases)
type_aliases:
  t: task
  n: note
  r: reminder
  l: log
  c: character

# Short-hand command aliases
command_aliases:
  a: append
  "+": append
  s: search
  l: list

With the above config:

  • mps a t "Fix the bug" --tags work → appends a task (aappend, ttask)
  • mps + n "Interesting observation" → appends a note
  • mps s "auth" → searches for "auth"

Override the config path:

mps --config-path /path/to/other.yaml list
# or
MPS_CONFIG=/path/to/other.yaml mps list

Architecture

src/
  main.rs        Entry point — alias pre-processing, clap dispatch
  cli.rs         Cli + Commands (#[derive(Parser)])
  config.rs      Config struct; YAML load/init; Ruby symbol-key normalization
  constants.rs   Filename regexes, new_file_name()
  date_parse.rs  parse_date() — natural-language + absolute formats
  error.rs       MpsError (thiserror)
  parser.rs      Position-based stack parser; mirrors Ruby Engines::Parser
  ref_resolver.rs Bidirectional epoch ↔ human ref (task-1, mps-1.2)
  store.rs       Store — all filesystem I/O; append, parse, search, rewrite
  elements/      Element enum + per-type Data structs
  commands/      One module per command + shared display helpers

Requirements

  • Rust 1.70+
  • git (for git / autogit commands)
  • $EDITOR or $VISUAL (for open / config edit; falls back to vim)

License

MIT