Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions docs/listing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Task Listing

`vp run --list` shows all available tasks across the workspace and exits without running anything. Combined with `--json`, it produces machine-readable output for CI pipelines, shell completion, and tooling integration.

`vp run --help` displays a hint about the `--list` flag so that users (and AI agents) can discover it.

## `--list` / `-l`

```sh
vp run --list
vp run -l # short alias
```

Prints a flat list of all tasks with their commands:

```
@vrowzer/fs#build tsdown
@vrowzer/fs#build:docs typedoc --excludeInternal
@vrowzer/example-vue#build vite build
@vrowzer/example-vue#dev vite
test:unit:vite pnpm run --color "/^test:unit:vite:/"
test:unit:vrowzer vitest run --project vrowzer:unit
typecheck pnpm -r --if-present typecheck
```

Tasks from named packages use the `package#task` format. Tasks from the workspace root (when the root `package.json` has no `name` field) are shown without a prefix.

The flag is mutually exclusive with `--last-details`.

## `--json`

```sh
vp run --list --json
```

Outputs the task list as a JSON array. Requires `--list`.

```json
[
{
"package": "@vrowzer/fs",
"task": "build",
"command": "tsdown",
"packagePath": "packages/fs"
},
{
"package": "@vrowzer/fs",
"task": "build:docs",
"command": "typedoc --excludeInternal",
"packagePath": "packages/fs"
},
{
"package": "@vrowzer/example-vue",
"task": "build",
"command": "vite build",
"packagePath": "examples/vue"
},
{
"package": "@vrowzer/example-vue",
"task": "dev",
"command": "vite",
"packagePath": "examples/vue"
},
{
"package": null,
"task": "test:unit:vite",
"command": "pnpm run --color \"/^test:unit:vite:/\"",
"packagePath": "."
},
{
"package": null,
"task": "test:unit:vrowzer",
"command": "vitest run --project vrowzer:unit",
"packagePath": "."
},
{
"package": null,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"package": null,
"packageName": "",

Internally, we treat a package.json file without a name field as if the name is an empty string. Tasks within these packages can be matched with #task.

Also, every package is allowed to have an empty name, not just the workspace root.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense to use an empty string since it's easier to handle!

"task": "typecheck",
"command": "pnpm -r --if-present typecheck",
"packagePath": "."
}
]
```

The `package` field is `null` when the task belongs to a workspace root whose `package.json` has no `name` field. `packagePath` is the package directory relative to the workspace root.

## Filtering

`--list` works with the standard package filter flags to scope the output:

```sh
vp run --list -r # all packages (same as bare --list)
vp run --list -F app # only tasks in "app" package
vp run --list --filter "./packages/*" # packages under packages/
vp run --list -w # workspace root only
```

Without any filter flag, `--list` shows tasks from all packages in the workspace.

## Use Cases

### Onboarding

New developers can quickly see what tasks are available across the monorepo:

```sh
vp run --list
```

### CI/CD Task Verification

Check whether a task exists before running it:

```sh
if vp run --list --json | jq -e '.[] | select(.task == "typecheck")' > /dev/null; then
vp run typecheck
fi
```

### Shell Completion

Dynamically populate tab-completion candidates:

```sh
# zsh completion function
_vp_run_tasks() {
local tasks=$(vp run --list --json | jq -r '.[].task')
compadd $tasks
}
```

### AI/LLM Integration

LLMs and AI agents can retrieve structured task information to understand the project:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we auto-detect the agent and print that by default (or generally in non-interactive mode)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your feedback!

Ideally auto-detecting the agent and adapting stdout accordingly would be great, but I can't see how to implement it reliably, there's no standardized way to detect which agent (Claude Code, Cursor, Copilot, Cline, etc.) is running, and each uses different environment variables (or none at all) 😅
We'd also need to keep adding detection logic as new agents appear.

For now, --list / --json as explicit flags feels like the pragmatic approach.
If a standard for agent detection emerges in the future, we can revisit auto-detection then.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
I didn't know about std-env's agent detection 🙈

That changes things. With this, when an agent is detected and vp run is executed, we could default to non-tractive output.


```sh
vp run --list --json
# Returns task names, commands, and package paths as structured JSON
```

### Documentation Generation

Generate a Markdown task inventory from JSON:

```sh
vp run --list --json | jq -r '.[] | "- `\(.package // "(root)")#\(.task)`: \(.command)"'
```

### Package-Scoped Inspection

Inspect tasks for a specific package or directory:

```sh
# Tasks in the "app" package
vp run --list -F app

# Tasks under the infra directory
vp run --list --filter "./infra/*"
```

## Flag Interactions

| Combined with | Behavior |
| ---------------- | ------------------------------------------ |
| `--json` | Output as JSON array instead of plain text |
| `-r` | Show all packages (same as bare `--list`) |
| `-F <pattern>` | Scope to matching packages |
| `--filter <pat>` | Scope to matching packages |
| `-w` | Show workspace root tasks only |
| `-t` | Show current package and transitive deps |
| `--last-details` | **Error** — mutually exclusive |

`--json` without `--list` is an error.

## Discoverability

`vp run --help` includes a hint about the `--list` flag so that users and AI agents can discover it without prior knowledge:

```
Options:
-l, --list List all available tasks and exit without running
--json Output task list as JSON (requires --list)
...

Tip: use `--list` to see all available tasks.
```

This hint is rendered via clap's `after_help` attribute on the `run` subcommand.