p is a product of Dropseed

P is for project.


As in, "How the hell do I work on this project."

The problem

It can often take several minutes just to figure out how to start working on something.

Every project is different, but damn near every project comes with a set of development commands or scripts to run common actions. And if it doesn’t, then it probably should. Different languages, people, and tools accomplish this in different ways. Some projects use the good ol’ Makefile, while others use package.json “scripts”, bash scripts, rake, fabric, and so on and so on…

A solution

Running p will show you which commands are available for the project you are on.

For example:

$ cd project
$ p

  --help     Show this message and exit.

  mypy        Using: ./scripts/mypy
  pre-commit  Using: ./scripts/pre-commit
  setup       Using: pipenv sync --dev
  test        Using: ./scripts/test

It does this by discovering scripts and commands that already exist within the project, and by adding automatically preset commands for known package managers or tools.

P is not a project requirement or dependency -- it is a personal tool. Nothing in your project should depend on p, but rather conform to p-friendly standards which are usable with or without p itself.

Ideally, p will “just work”. But if not, it is often in your project’s best interest to design a developer experience that would work if someone were using p. That is – script out some of the most commonly used actions for your project (install, test, deploy, etc.), and put them in a uniform place where contributors can easily figure out how to use them. P is simply a small abstraction layer to make it even easier yet for people that use it.

Install it for yourself

Don't add it to a project. Add it to your machine, system-wide or user-wide.

$ pip3 install -U git+https://github.com/dropseed/p.git#egg=p

Project commands

Local scripts

P will automatically find executable scripts (with no file extension) in ./scripts or ./bin. The filename will be added as a command so that they can simply be run by doing p {script-name}.

$ tree scripts/
├── compile-assets
├── load-fixtures
├── pre-commit
├── setup
├── start-postgres
├── test
└── work

Will result in:

$ p
  Usage: p [OPTIONS] COMMAND [ARGS]...

    --help     Show this message and exit.

    compile-assets  Using: ./scripts/compile-assets
    load-fixtures   Using: ./scripts/load-fixtures
    pre-commit      Using: ./scripts/pre-commit
    setup           Using: ./scripts/setup
    start-postgres  Using: ./scripts/start-postgres
    test            Using: ./scripts/test
    work            Using: ./scripts/work


If there is a Makefile in your project, p will automatically parse .PHONY and make those commands available via p. So if you have make test, it will also be available to p users via p test.

package.json scripts

Entries in your package.json "scripts" will automatically be mapped to p commands.

For example:

  "scripts": {
    "start": "react-scripts start"

Would result in:


  --help     Show this message and exit.

  install  Using: yarn install
  start    Using: npm run start

Preset commands

P will automatically add commands for known package managers. These can be overridden by providing your own script of the same name in one of the recognized locations. So, for example, if you want contributors to use something more specific than a regular yarn install, just add an “install” script to package.json.

We only add things as people need them. If you don't see what you need, tell us!



.terraform or terraform.tfstate



Cartfile or Cartfile.resolved

Gopkg.toml or Gopkg.lock

Git hooks

P also provides automatically installation of git hooks, if you use commands named pre-commit or post-merge. On p install or p {git-hook-name} it will prompt you to install it into your local .githooks.

Grouping (advanced)

To make the p help more user friendly you can group and hide commands from the top-level. This works automatically by using a : in your command name.

For example, if you have commands like db:load and db:reset, you'll get a db group. You can run p db to see the subcommands in db, and run p db load to run a subcommand.

$ p

  --help     Show this message and exit.


$ p db load

(You can also invoke the grouped commands directly as p db:load.)

Inspired by

by Dropseed