mps-rs 1.0.0

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

Production Rust rewrite of [MPS (MonoPsyches)](https://github.com/mash-97/mps) — a plain-text personal productivity CLI. Single binary, no runtime dependency, backward-compatible with all Ruby-generated `.mps` files and config.

## Install

### From local source (recommended during development)

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

> **Do not** run `cargo install mps` — there is an unrelated crate by that name on crates.io.

### Build release binary manually

```bash
cargo build --release
# binary at: target/release/mps
cp target/release/mps ~/.local/bin/mps   # or any directory on $PATH
```

## Quick start

```bash
mps                   # open today's file in $EDITOR
mps list              # print today's elements
mps list --since monday           # all elements from last Monday
mps append task "Fix auth bug" --tags work,backend
mps search "auth" --since "last week"
mps stats --since monday
mps export --format csv --since "20260501" > may.csv
mps autogit           # stage + commit + pull + push
```

## Commands

| Command | Description |
|---------|-------------|
| `mps [open] [DATE]` | Open date's file in `$EDITOR` (default: today) |
| `mps list [DATE]` | Print elements as indented tree |
| `mps append TYPE BODY` | Append one element without opening editor |
| `mps search QUERY` | Full-text search across all `.mps` files |
| `mps stats [DATE]` | Element counts and log durations |
| `mps export [DATE]` | JSON or CSV to stdout |
| `mps autogit` | Stage, commit, pull, push |
| `mps git ARGS` | Any git command inside storage dir |
| `mps cmd ARGS` | Any shell command inside storage dir |
| `mps version` | Print version |

### list flags

| Flag | Short | Description |
|------|-------|-------------|
| `--type TYPE` | `-t` | Filter: `task`, `note`, `log`, `reminder` |
| `--tag TAG` | `-g` | Filter by tag name |
| `--status STATUS` | `-s` | Filter tasks by `open` or `done` (excludes all other types) |
| `--since DATE` | `-S` | Show elements from DATE up to target date |

### append flags

| Flag | Description |
|------|-------------|
| `--tags t1,t2` | Comma-separated tags |
| `--status open\|done` | Task status (default: open) |
| `--at TIME` | Time for reminders (e.g. `5pm`) |
| `--start-time HH:MM` | Start time for logs |
| `--end-time HH:MM` | End time for logs |

### search / stats / export flags

| Flag | Short | Description |
|------|-------|-------------|
| `--type TYPE` | `-t` | Filter by element type |
| `--tag TAG` | `-g` | Filter by tag (search only) |
| `--since DATE` | `-S` | Date range lower bound |
| `--format json\|csv` | `-f` | Export format (default: json) |

### Date formats accepted everywhere

| Input | Meaning |
|-------|---------|
| `today`, `yesterday` | Relative day |
| `monday``sunday` | Last occurrence of weekday |
| `last friday` | Explicit "last" weekday |
| `3 days ago` | N days before today |
| `last week` | 7 days ago |
| `20260421` | Explicit YYYYMMDD |
| `2026-04-21` | Explicit YYYY-MM-DD |

## File format

Same as the Ruby gem — fully compatible:

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

@note{
  The auth token expiry edge case
}

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

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

@mps{
  @task[backend]{
    Nested task inside a sub-block
  }
}
```

Brackets are optional — `@task{ body }` is valid. Files are named `YYYYMMDD.<epoch>.mps`.

## Configuration

Reads `~/.mps_config.yaml` (same file the Ruby gem writes — no migration needed):

```yaml
mps_dir: /home/you/.mps
storage_dir: /home/you/.mps/mps
log_file: /home/you/.mps/mps.log
git_remote: origin
git_branch: master
```

Created automatically on first run if absent.

## Architecture

```
src/
  main.rs        entry point + clap dispatch
  cli.rs         Cli struct + Commands enum (#[derive(Parser)])
  config.rs      Config struct; YAML load/init; handles Ruby symbol-key YAML
  constants.rs   file-name regexes, new_file_name()
  date_parse.rs  parse_date() — natural-language dates, no external crate
  error.rs       MpsError enum (thiserror)
  parser.rs      position-based stack parser; mirrors Ruby Engines::Parser
  store.rs       Store — all file-system operations
  elements/      Element enum (Task/Note/Log/Reminder/MpsGroup/Unknown)
  commands/      one file per command + shared display helpers
```

See [DESIGN_RUST.md](../mps/DESIGN_RUST.md) in the Ruby project for the full architecture rationale.

## Development

```bash
cargo build           # debug build
cargo build --release # optimized (~4MB binary)
cargo test            # 36 unit tests
cargo doc --open      # API docs in browser
```

## Requirements

- Rust 1.70+ (uses `std::sync::OnceLock`)
- Git (for `git` / `autogit`)
- `$EDITOR` or `vim` (for `open`)

## License

MIT