npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

taskops

v0.5.0

Published

Markdown-first task/run graph CLI with EoW closure, delegation, and Obsidian-friendly TaskOps work trees.

Readme

TaskOps CLI

TaskOps is a work-truth protocol, not just a task manager.

It exists to keep human + AI work honest: agents must not silently stop, pretend work is done, or continue executing a wrong plan. Plans, execution logs, blockers, delegation, and closure evidence stay inspectable and versionable in plain markdown.

It separates two truths:

  • Task graph — the decomposition truth: objective, task groups, selected snapshots, readiness, and explicit terminal EoW nodes.
  • Run graph — the execution truth: what actually happened, including execution, exploration, decomposition, delegation, waiting, verification, failure, and closure.

Why TaskOps exists

Traditional task lists usually blur three different questions:

  1. What is the right decomposition of the work?
  2. What is actually runnable right now?
  3. What happened during execution, including delegation or waiting?

TaskOps keeps those layers separate so an agent or human can make honest decisions instead of pretending every task is a flat checklist item.

Core concepts

  • work — the top-level objective container (entityType: work).
  • task-groups/ — versioned decomposition trees.
  • snapshots/ — selected version paths through the task graph.
  • runs/<run-id>/ — independent execution graphs.
  • eow — explicit End of Work nodes attached to terminal task/run branches.
  • runRefs — task-side references to run nodes.
  • sourceTaskId / sourceTaskGroupVersionId — run-side references back to the task graph.
  • type: delegate + status: waiting — explicit human/AI/agent delegation points.

Install

npm install -g taskops

Then run:

taskops --help

Quick start: the smallest useful loop

# 1. Create a work tree around one objective
taskops init ./my-work \
  --id my-work \
  --title "My Work" \
  --objective "Ship the first useful version" \
  --language en

# 2. Validate and summarize the current graph
taskops validate ./my-work
taskops summary ./my-work

# 3. Inspect machine-readable state
taskops show ./my-work --json

# 4. Classify what can honestly happen next
taskops classify-runnable ./my-work task-design --json

# 5. Advance bounded work
taskops run ./my-work --executor dry-run --max-steps 1 --json

taskops run dispatches by readiness: runnable tasks execute, needs_decomposition tasks expand the task graph, needs_exploration tasks create exploratory run evidence, and blocked/waiting/delegated work stops instead of being silently skipped.

Example: AI-assisted OAuth refactor

A large refactor should not be trusted to a flat checklist or a disappearing chat transcript. With TaskOps:

  1. A work captures the objective: “Refactor the OAuth flow safely.”
  2. The task graph decomposes analysis, token validation changes, regression tests, migration notes, and review.
  3. The runner classifies each task as runnable, needs_decomposition, needs_exploration, or blocked.
  4. The run graph records what the agent actually did, which tests failed, what was delegated, and why each branch was closed.
  5. Reviewers inspect taskops summary, runs/<run-id>/events.jsonl, and EoW nodes before trusting completion.

TaskOps tells agents how the work is actually getting done.

Commands

taskops init <dir> --id <id> --title <title> --objective <objective> [--language en|ko]
taskops validate <path>
taskops summary <path> [--write]
taskops show <path> [--json]
taskops classify-runnable <work-dir> <task-id> [--json]
taskops next <work-dir> [--json]
taskops explain <work-dir> [--json]
taskops close <work-dir> <run-node-id|task-id> [--reason <reason>] [--json]
taskops unblock-check <work-dir> [--dry-run] [--json]
taskops run <work-dir> [--run-id <id>] [--agent <agent-id>] [--executor dry-run|openclaw-agent] [--max-steps <n>] [--until <iso-timestamp>] [--timeout <seconds>] [--json]
taskops decompose <work-dir> --task-group-id <id> --spec <spec.json>
taskops refactor <work-dir> --task-group-id <id> --spec <spec.json> --supersedes <version-id>
taskops vault-init <vault-dir> [--repo-url <url>] [--branch main] [--auto-sync true|false]
taskops git-status <vault-dir>
taskops git-sync <vault-dir> [--message <msg>] [--branch <branch>]
taskops watch-sync <vault-dir> [--message <msg>] [--debounce-ms <ms>] [--branch <branch>]

Honest-action commands

These three read-only/guarded commands are the "honest loop" surface. They never lie about progress:

  • taskops next <work-dir> [--json] — return the one next honest action: execute, decompose, explore, wait, delegation_pending, blocked, done, or no_runnable. The output also includes the target task or run node and a recommended command. It does not mutate state.
  • taskops explain <work-dir> [--json] — explain why the work is or is not done. Reports the closure summary, the next honest action, and the concrete reasons the work is still open (missing terminal EoW, blockers, waiting delegations, runnable/decompose/explore tasks, validation errors). It does not mutate state.
  • taskops close <work-dir> <run-node-id|task-id> [--reason <reason>] [--json] — make EoW closure explicit and guarded. Refuses to close a task that already has an EoW, has open child branches, or is not yet done unless --reason manual_verified is supplied (in which case the task status is also flipped to done so closure counts stay honest). Refuses to close a run node that is not done/cancelled unless an explicit reason (failure, superseded, cancelled, manual_verified) is supplied; refuses delegated/waiting nodes unless one of manual_verified|cancelled|superseded is given. On success it writes an EoW file (and a closes_with run edge for run nodes).
taskops next ./my-work --json
taskops explain ./my-work
taskops close ./my-work task-foo --reason manual_verified

Run a TaskOps work

taskops run <work-dir> executes runnable tasks against the canonical markdown state. It is the bridge between the passive task graph and an actual run graph: agents (OpenClaw or otherwise) invoke this command rather than mutating files by hand.

# bounded single step using the safe synthetic executor
taskops run ./my-work --executor dry-run --max-steps 1

# real execution against an OpenClaw agent, capped by a deadline
taskops run ./my-work --executor openclaw-agent --agent main --until 2026-05-13T09:00:00+09:00

# machine-readable summary for programmatic callers
taskops run ./my-work --max-steps 3 --json

The runner:

  • Re-uses an existing active run when there is exactly one, else creates/uses runs/run-main/. Override with --run-id.
  • Rechecks blocked tasks that declare blockedBy references before selecting the next action. When every blocker is resolved, the runner reopens the task (status: pending) and clears runReadiness: blocked unless unblockRunReadiness says what readiness to use next. Use taskops unblock-check <work-dir> --dry-run --json to inspect the same transition without mutating files.
  • Picks the next task deterministically: active snapshot order, then task.order, then id lexicographic. Only tasks with status pending/active are eligible. Tasks classified as blocked are excluded; tasks classified as runnable, needs_decomposition, or needs_exploration are dispatched to the matching runner step.
  • For runnable tasks: creates the run node, mutates task status to done, attaches task and run EoW nodes, and writes the closes_with edge.
  • For needs_decomposition tasks: creates a type: decomposition run node, expands the task graph by writing a child task group and version (dry-run synthesizes a deterministic placeholder; openclaw-agent delegates authoring to the agent), updates the parent task's childTaskGroupId, marks the parent done with an EoW reason decomposed_by_runner, closes the run node with an EoW reason decomposition_recorded, and extends the active snapshot's selectedVersions so the new child task group/version becomes visible to subsequent steps of the same runner invocation.
  • For needs_exploration tasks: creates a type: exploration run node, writes a reflection artifact under runs/<run-id>/artifacts/<run-node-id>.md, marks the parent task done with an EoW reason exploration_recorded_by_runner and runReadiness: needs_decomposition (ready for an informed decomposition pass), and closes the run node with an EoW reason exploration_recorded.
  • Pauses immediately when it encounters a status: waiting task or run node, or a type: delegate run node that is not yet done/cancelled. Delegated run nodes are classified by type first, so type: delegate + status: waiting reports delegation_pending rather than generic waiting.
  • Appends a JSONL event log at runs/<run-id>/events.jsonl plus human entries in runs/<run-id>/run-log.md.
  • Holds a .taskops-runner.lock directory under the work root and removes it on exit. A second runner against the same work refuses to start.

Stop conditions

--max-steps and --until are both optional and combine with OR semantics: the runner stops before starting a new step if either limit is reached. When neither is supplied the runner defaults to --max-steps 1 (one bounded step). Every action — execute, decompose, or explore — counts as one step against --max-steps.

| Stop reason | Meaning | | ---------------------- | -------------------------------------------------------------------------------------------------------- | | all_closed | The selected work is fully closed: every terminal task is closed by task EoW, every run terminal node is closed by run EoW, and no waiting/delegated/blocked work remains. This is the closure-complete terminal state. | | no_runnable | No remaining task is actionable (runnable, decomposable, or explorable), but the work is not yet closed (terminal EoW coverage incomplete, or otherwise inconsistent). Treat this as a state to inspect rather than a successful finish. | | blocked_only | Open tasks remain but they are all classified as blocked; resolve the blockers before continuing. | | waiting | A task or run node is in status: waiting; resolve or cancel it before continuing. | | delegation_pending | A type: delegate run node is still pending (not done/cancelled); resolve the delegation first. | | max_steps | The --max-steps budget is exhausted. | | deadline_reached | --until has already passed when the next step would start. | | task_failed | The executor reported a non-zero exit, timeout, or refused to author the expected decomposition/artifact.| | validation_failed | A mid-run re-parse found errors and the runner refused to act. |

--until accepts any value Date.parse understands. When both --until and --timeout are supplied, the per-task timeout is capped at the remaining time before the deadline.

Executors

  • --executor dry-run (default) — no external process. Synthesises a successful result and mutates the markdown graph. For decomposition steps it writes a deterministic child task group/version with a single blocked placeholder task asking for human input. For exploration steps it writes a deterministic reflection artifact under runs/<run-id>/artifacts/. Intended for smoke tests, dress rehearsals, and skill reviews. It does not perform real work. Pass --executor openclaw-agent to dispatch a real run.
  • --executor openclaw-agent — spawns openclaw agent --agent <agent-id> --message <prompt> --json [--timeout <seconds>]. The prompt is tailored to the picked action — execute, decompose, or explore — and instructs the agent not to recursively invoke taskops run. After the agent returns the runner verifies that the expected artifact (the executed task's outcome, the decomposition version index, or the exploration artifact) was authored before marking the step done. Default --agent is main.

Canonical file layout

<taskops-work>/
  index.md                  # entityType: work
  work-log.md
  task-groups/
    <task-group-id>/
      index.md
      versions/
        <version-id>/
          index.md
          tasks/
            <task-id>.md
          eow/
            <eow-id>.md
  snapshots/
    <snapshot-id>.md
  runs/
    <run-id>/
      index.md
      nodes/
        <run-node-id>.md
        <eow-id>.md
      edges/
        <run-edge-id>.md
  derived/
    canvases/
    views/

Run readiness

TaskOps classifies each task before execution:

  • runnable — send it to a run graph.
  • needs_decomposition — split it into a child task group/version.
  • needs_exploration — run/search/try/debug first to learn enough for honest decomposition.
  • blocked — resolve the dependency before continuing.

Closure and delegation

TaskOps does not treat done as the same thing as closure.

A branch is closed when an explicit EoW node is attached. The summary reports closure state, for example:

Terminal task EoW coverage: 4/4
Waiting delegations: 0
Open blockers: 0
Work completion: complete

Delegation is represented in the run graph rather than hidden as a vague blocker:

entityType: runNode
type: delegate
status: waiting
delegateeType: human
delegateeRef: jimmy
request: Confirm the constraints needed before downstream execution.
expectedOutput: A clear decision and any constraints that update the task graph.

Obsidian and Git-backed vaults

TaskOps works well with Obsidian because canonical state is plain markdown.

Initialize a vault with automatic Git sync metadata:

taskops vault-init ~/vaults/my-taskops-vault \
  --repo-url [email protected]:ORG/my-taskops-vault.git \
  --branch main \
  --auto-sync true \
  --language en

Then sync manually or watch for changes:

taskops git-status ~/vaults/my-taskops-vault
taskops git-sync ~/vaults/my-taskops-vault --message "Sync TaskOps vault"
taskops watch-sync ~/vaults/my-taskops-vault --debounce-ms 5000

The companion Obsidian plugin can read the same markdown state and export derived canvas views.

Examples and docs

  • GitHub: https://github.com/jimmylegendary/taskops
  • Canonical example: examples/taskops-canonical-minimal-v1/
  • Core model: docs/CORE_MODEL.md
  • Markdown format: docs/MD_FIRST_FORMAT.md
  • Run readiness: docs/RUN_READINESS.md

Development

git clone [email protected]:jimmylegendary/taskops.git
cd taskops
npm install
npm run verify
npm run release:preflight

License

MIT