rewelo

Rewelo CLI

Prioritisation tool using the relative weight method. Stores data in SQLite.

Installation

npm install
npm run build

The CLI is available as rw (via npm link) or directly with node dist/index.js.

Global Options

OptionDescription
--db <path>Path to SQLite file, must end in .db (default: ./relative-weight.db)
--jsonOutput as JSON
--csvOutput as CSV (where supported)
--quietMinimal output: commands that change data print nothing (create prints the new UUID), lists print one item per line
--no-colorAccepted for compatibility; rw never prints colour
--versionShow version

An option that takes one value may be given once; --title A --title B is an error. Options marked repeatable, such as --tag, collect every value.

Only project create and import json create the database file; other commands report a missing database instead of creating an empty one. The database uses SQLite's write-ahead log, so commands can read while another rw process writes; <name>.db-wal and <name>.db-shm files appear next to the database while it is in use. Back up with rw export json, or copy the .db file while no rw process runs.

Commands

project

rw project create <name>
rw project list
rw project delete <name> [--force]
rw project history --project <name> [--since <timestamp>] [--limit <n>] [--offset <n>]
rw project diff --project <name> --since <timestamp>

delete prompts for confirmation unless --force is passed. history lists the revisions of all tickets, newest first; with --since, the revisions right after it, oldest first. --limit and --offset page through them. diff compares the project now with its state at --since: new, updated and deleted tickets and net tag changes. Timestamps are ISO dates or date-times; without an offset they are read as UTC.

ticket

rw ticket create --project <name> --title <title> [--description <text>] \
  [--benefit <n>] [--penalty <n>] [--estimate <n>] [--risk <n>]

rw ticket list --project <name> [--tag <prefix:value>...] \
  [--exclude-tag <prefix:value>...] [--search <text>] \
  [--sort <field>] [--limit <n>] [--offset <n>] \
  [--min-priority <n>] [--min-value <n>] [--max-cost <n>]

rw ticket update --project <name> --title <title> [--new-title <title>] \
  [--description <text>] [--benefit <n>] [--penalty <n>] \
  [--estimate <n>] [--risk <n>]

rw ticket delete --project <name> --title <title>

rw ticket history --project <name> --title <title> [--limit <n>] [--offset <n>]

rw ticket upsert --project <name> --title <title> [--description <text>] \
  [--benefit <n>] [--penalty <n>] [--estimate <n>] [--risk <n>]

upsert creates the ticket if no ticket has that title, and updates it otherwise.

Scores use the Fibonacci scale: 1, 2, 3, 5, 8, 13, 21.

Sort fields: priority, value, cost, benefit, penalty, estimate, risk.

priority here, in report summary and on the dashboard is always the unweighted value / cost. The project's weights (config weights) apply only to the weighted priority that rw calc priority shows next to it.

ticket list supports filtering, search, pagination, and score thresholds:

# multiple tag filters (intersection)
rw ticket list --project Acme --tag state:backlog --tag team:backend

# exclude done items
rw ticket list --project Acme --exclude-tag state:done

# search by title
rw ticket list --project Acme --search "login"

# pagination
rw ticket list --project Acme --sort priority --limit 20
rw ticket list --project Acme --sort priority --limit 20 --offset 20

# score thresholds
rw ticket list --project Acme --min-priority 1.5
rw ticket list --project Acme --max-cost 5       # quick wins
rw ticket list --project Acme --min-value 10      # high-value items

--min-priority (like report health --threshold) compares the exact value / cost, not the two decimals shown: a ticket shown with 1.62 (21/13 = 1.615…) is below --min-priority 1.62.

JSON output includes { total, offset, items } for pagination. ticket list also supports --csv output. ticket history shows the revision log for a ticket, oldest first; --limit and --offset page through it.

tag

Tags use a prefix:value format (e.g. state:wip, team:backend). A prefix works like a field: a ticket holds one value per prefix. Assigning state:done to a ticket tagged state:wip replaces it (the output says replaced "state:wip"), and asking for two values of one prefix in one command, e.g. feature:auth feature:login, is an error. Use different prefixes for independent classifications.

rw tag create <prefix:value> --project <name>
rw tag assign <tags...> --project <name> --ticket <title> [--ticket <title>...]
rw tag remove <prefix:value> --project <name> --ticket <title>
rw tag list --project <name>
rw tag delete <prefix:value> --project <name>     # only a tag no ticket holds
rw tag rename --project <name> --prefix <prefix> --old <value> --new <value>
rw tag log --project <name> --ticket <title>

tag assign auto-creates tags if they don't exist. It accepts multiple tags and multiple --ticket flags, assigning every tag to every ticket:

# multiple tags on one ticket
rw tag assign state:backlog priority:p1 --project Acme --ticket "Login page"

# one tag on multiple tickets
rw tag assign state:done --project Acme --ticket "Login page" --ticket "Signup flow"

# both combined (cross product)
rw tag assign state:wip team:backend --project Acme --ticket "Login page" --ticket "Signup flow"

tag log shows the audit trail of tag changes on a ticket.

config

rw config weights --project <name>                    # view
rw config weights --project <name> --set --w1 2 --w3 1  # set (omitted weights keep current value)
rw config weights --project <name> --reset             # reset to defaults (all 1.5)

Weights w1-w4 control how much each factor contributes to weighted priority:

calc

rw calc weights --project <name> [--tag <prefix:value>...]
rw calc priority --project <name> [--tag <prefix:value>...] [--w1 <n>] [--w2 <n>] [--w3 <n>] [--w4 <n>]

export

rw export csv --project <name> [--output <path>] [--with-calculations]
rw export json --project <name> [--output <path>] [--with-history]

Without --output, data is written to stdout. export json contains the tickets with their tags, the project's tags, its relations (by ticket title) and its weight configuration.

import

rw import csv <file> --project <name>
rw import json <file> --project <name>

import csv reads the columns written by export csv: title (required), description, benefit, penalty, estimate, risk and tags; value, cost and priority are ignored. Any other column is an error.

import json creates the project if it does not exist yet, and restores relations and weights when the file has them (weights replace the project's current ones). A file written with --with-history also restores each ticket's creation and last update time, revisions and tag changes, so lead and cycle times survive a backup and restore. Imports are all-or-nothing: if any row fails, nothing is imported.

relation

rw relation create --project <name> --source <title> --type <type> --target <title>
rw relation remove --project <name> --source <title> --type <type> --target <title>
rw relation list --project <name> --ticket <title>
rw relation list-all --project <name>

Relation types: blocks, depends-on, relates-to, duplicates, supersedes, precedes, tests, implements, addresses, splits-into, informs, see-also.

A relation can't contradict an existing one: B blocks A is refused when A blocks B exists, and so are A depends-on B and B precedes A, which put the two tickets in the opposite order.

report

rw report summary --project <name> [--top <n>]
rw report group --project <name> --prefix <prefix>
rw report distribution --project <name>
rw report health --project <name> [--threshold <n>]
rw report times --project <name>
rw report dashboard --project <name> --output <path> [--limit <n>]
rw report event-log --project <name> [--since <timestamp>] [--after <sequence>] [--limit <n>]
ReportDescription
summaryTotal tickets, breakdown by state: tag, top-N open tickets (not state:done) by priority (default 5)
groupGroup tickets by a tag prefix and show average priority per group
distributionHistogram of Fibonacci scores across benefit, penalty, estimate, risk
healthHigh/low priority ratio, total backlog cost, done vs open counts
timesLead time (created → done) and cycle time (wip → done) per ticket
dashboardSelf-contained static HTML dashboard: tickets by priority, score distribution, backlog health and a table of relations; the ticket and relation tables show 500 rows unless --limit says otherwise
event-logTicket creations, updates, deletions and tag changes: the newest first (default 50), or after --since/--after, oldest first. --after takes an event's sequence (in --json) and polls without missing events

times requires state:wip and state:done tags to be assigned to tickets. States are recognised by name: work starts the first time a ticket gets a tag called state:wip at that moment, and a ticket is done while it holds the tag now called state:done (report health counts done tickets the same way). Renaming a state tag changes its meaning: after state:done becomes state:cancelled, those tickets are no longer done.

serve (MCP)

rw serve [--db <path>] [--channel]

Starts the MCP server over stdio. The database path can also be set via the RW_DB_PATH environment variable. --channel pushes changes made outside the session into Claude Code as channel messages; see Live events.

Docker

# Build (APP_VERSION labels the image; rw --version works without it)
docker build --build-arg APP_VERSION="$(node -p "require('./package.json').version")" -t rw .

# Run CLI commands
docker run --rm -v rw-data:/data rw project list

# Run MCP server
docker run --rm -i -v rw-data:/data rw serve

The container stores the database at /data/relative-weight.db. Use a named volume or bind mount to persist data between runs; without one, rw warns on stderr that the database is lost when the container is removed.

Edit cli.md on GitHub