-
Notifications
You must be signed in to change notification settings - Fork 16
feat: task listing wihtout no-intractive (--list and --json flags)
#320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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, | ||
| "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: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) 😅 For now,
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use isAgent from std-env
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! That changes things. With this, when an agent is detected and |
||
|
|
||
| ```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. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Internally, we treat a
package.jsonfile without anamefield 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.
There was a problem hiding this comment.
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!