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

@jonacem/do-file

v0.2.0

Published

A small YAML task runner with dependencies, arguments, and env-file interpolation.

Readme

do-file

do-file is a small YAML task runner for commands you use repeatedly in a project. A DO file can contain simple commands, documented tasks, task dependencies, declared arguments, and variables loaded from dotenv-style files.

Install

@jonacem/do-file is the npm package name. It installs the official dof and do-file commands. Bun is required to run it.

npm install --global @jonacem/do-file

You can also install it globally with Bun:

bun install --global @jonacem/do-file

Confirm the command is available:

dof --help

Until the first npm release is published, run bun run build and then npm install --global . from the repository root.

Run a task from the directory containing your DO file with dof <task> [arguments]. The longer do-file command works identically.

Development

Install dependencies and run the source version:

bun install
bun run src/index.ts <task> [arguments]

Create the publishable executable with bun run build. npm pack and npm publish build it automatically, while the publish lifecycle also runs the type-check and tests.

Publish to npm

The package is published as @jonacem/do-file, and its bin mapping installs both dof and do-file.

npm login
npm publish --access public

The @jonacem scope avoids npm's unscoped-name similarity restriction while keeping the product name. For later releases, change the version first, for example with npm version patch, and publish the new version.

Quick start

Create a file named DO in the project root:

env:
  file: .env.do

tasks:
  install: bun install

  dev:
    description: Start the development server
    needs: install
    args:
      name:
        description: Name shown by the development server
        default: developer
      port:
        description: Port to listen on
        required: true
    run: echo "Starting ${name} on ${HOST}:${port}"

Create the explicitly loaded environment file:

HOST=127.0.0.1
port=3000

Then run:

dof dev --name Ada
dof dev --name="Ada Lovelace" --port=4000

The first command uses port=3000 from .env.do. The second command overrides it with the inline value 4000.

Tasks

A task can be a command string:

tasks:
  test: bun test

Or it can use the expanded form:

tasks:
  check:
    description: Run all checks
    needs: generate
    run: bun test

needs names another task that must finish successfully first. Dependency cycles and missing dependencies are reported as errors.

Multiple commands

Commands written on separate indented lines execute one at a time, in order:

tasks:
  build:
    run:
      mkdir -p bin
      go build -o ./bin/app ./cmd/app

Standard YAML literal blocks are also supported:

tasks:
  build:
    run: |
      mkdir -p bin
      go build -o ./bin/app ./cmd/app

Or write each command as a YAML list item:

tasks:
  build:
    run:
      - mkdir -p bin
      - go build -o ./bin/app ./cmd/app

Each command gets its own shell execution. If one fails, the remaining commands in that task do not run.

Arguments and variables

Declare required arguments as a list:

tasks:
  greet:
    args: [name]
    run: echo "Hello ${name}"
dof greet --name Ada

Use a mapping to provide defaults or argument metadata:

tasks:
  serve:
    args:
      host: localhost
      port:
        description: HTTP port
        default: 3000
      token:
        description: API token
        required: true
    run: server --host "${host}" --port "${port}" --token "${token}"

Both CLI forms are accepted:

dof serve --token secret
dof serve --token=secret --port=8080

Arguments declared by a task dependency are also accepted when running the parent task. Unknown arguments and arguments without values are rejected, which helps catch typos.

Variable values use this precedence, from highest to lowest:

  1. Inline CLI argument (--name value or --name=value)
  2. Variable from the configured env file or files
  3. Default declared under args

Every ${name} placeholder must resolve. Interpolation intentionally does not read the runner's global process environment. Only inline arguments, the env files selected by env.file, and defaults in the DO file are interpolation sources.

Values are inserted into the command before it is passed to the shell. Quote placeholders when they may contain spaces, and treat values supplied to tasks as trusted shell input.

Environment files

Environment loading is opt-in and local to the DO file:

env:
  file: .env.do

Load multiple files by using a list. Files are loaded in order, and a value in a later file overrides the same key from an earlier file:

env:
  file:
    - .env
    - .env.do

The file accepts KEY=value, comments, quoted values, and optional dotenv-style export prefixes:

# Used by DO tasks
API_URL=https://api.example.com
APP_NAME="Example App"
export LOG_LEVEL=debug

Loaded values are available both to ${KEY} interpolation and to the child command's environment. The runner does not automatically load .env; name every file explicitly in env.file.

Complete example

env:
  file: .env.do

tasks:
  generate: bun run generate

  dev:
    description: Generate code, then start the app
    needs: generate
    args:
      app: web
      port:
        required: true
    run: bun run dev --app "${app}" --port "${port}" --api "${API_URL}"

  deploy:
    args: [environment]
    run: ./scripts/deploy.sh "${environment}"
dof dev --port 3000
dof deploy --environment production