mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-10 23:15:40 +00:00
refactor(cli): group first-release commands for TASK-127 (#45)
This commit is contained in:
@@ -89,17 +89,17 @@ REST API at `/api/v1/`. Key endpoints:
|
||||
|
||||
## Authentication
|
||||
|
||||
User-based authentication with email/password. When no users exist (fresh install), everything works without auth until the instance is initialized with `pad setup`. Once the first admin exists, all API requests require authentication.
|
||||
User-based authentication with email/password. When no users exist (fresh install), everything works without auth until the instance is initialized with `pad auth setup`. Once the first admin exists, all API requests require authentication.
|
||||
|
||||
```bash
|
||||
# First-time setup
|
||||
pad setup # Create the first admin account on the server host
|
||||
pad auth setup # Create the first admin account on the server host
|
||||
|
||||
# Subsequent logins
|
||||
pad login # Email + password prompt
|
||||
pad whoami # Show current user
|
||||
pad logout # Sign out
|
||||
pad reset-password user@example.com # Generate reset link (admin fallback)
|
||||
pad auth login # Email + password prompt
|
||||
pad auth whoami # Show current user
|
||||
pad auth logout # Sign out
|
||||
pad auth reset-password user@example.com # Generate reset link (admin fallback)
|
||||
|
||||
# Credentials stored in ~/.pad/credentials.json (0600 permissions)
|
||||
# CLI auto-attaches auth token to all API requests
|
||||
@@ -107,10 +107,10 @@ pad reset-password user@example.com # Generate reset link (admin fallback)
|
||||
|
||||
### Workspace membership
|
||||
```bash
|
||||
pad members # List workspace members
|
||||
pad invite user@example.com # Invite (adds directly if user exists, creates join code if not)
|
||||
pad invite user@example.com --role viewer # Invite with specific role
|
||||
pad join <code> # Accept a workspace invitation
|
||||
pad workspace members # List workspace members
|
||||
pad workspace invite user@example.com # Invite (adds directly if user exists, creates join code if not)
|
||||
pad workspace invite user@example.com --role viewer # Invite with specific role
|
||||
pad workspace join <code> # Accept a workspace invitation
|
||||
```
|
||||
|
||||
Roles: `owner` (full access), `editor` (CRUD items), `viewer` (read-only).
|
||||
@@ -132,41 +132,41 @@ Items are referenced by **issue ID** (e.g. `TASK-5`, `BUG-8`) wherever a `<ref>`
|
||||
Slugs also work but issue IDs are preferred.
|
||||
|
||||
```bash
|
||||
pad create <collection> "title" [--status X] [--priority X]
|
||||
pad list [collection] [--status X] [--all]
|
||||
pad show <ref> # e.g. pad show TASK-5
|
||||
pad update <ref> [--status X] [--priority X]
|
||||
pad delete <ref>
|
||||
pad move <ref> <target-collection>
|
||||
pad search "query"
|
||||
pad status # Project dashboard
|
||||
pad next # Recommended next task
|
||||
pad standup [--days N] # Daily standup report
|
||||
pad changelog [--days N] # Release notes from completed items
|
||||
pad blocks <source> <target> # e.g. pad blocks TASK-5 TASK-8
|
||||
pad blocked-by <item> <blocker>
|
||||
pad deps <ref> # Show dependencies
|
||||
pad unblock <source> <target>
|
||||
pad collections # List collections
|
||||
pad collections create "Name" --fields "key:type[:opts]; ..."
|
||||
pad edit <ref> # Open in $EDITOR
|
||||
pad init [--template X] # Create workspace
|
||||
pad install [tool] # Install /pad skill for AI tools
|
||||
pad onboard # Analyze codebase, suggest conventions
|
||||
pad open # Open web UI in browser
|
||||
pad watch # Real-time activity stream
|
||||
pad item create <collection> "title" [--status X] [--priority X]
|
||||
pad item list [collection] [--status X] [--all]
|
||||
pad item show <ref> # e.g. pad item show TASK-5
|
||||
pad item update <ref> [--status X] [--priority X]
|
||||
pad item delete <ref>
|
||||
pad item move <ref> <target-collection>
|
||||
pad item search "query"
|
||||
pad project dashboard # Project dashboard
|
||||
pad project next # Recommended next task
|
||||
pad project standup [--days N] # Daily standup report
|
||||
pad project changelog [--days N] # Release notes from completed items
|
||||
pad item block <source> <target> # e.g. pad item block TASK-5 TASK-8
|
||||
pad item blocked-by <item> <blocker>
|
||||
pad item deps <ref> # Show dependencies
|
||||
pad item unblock <source> <target>
|
||||
pad collection list # List collections
|
||||
pad collection create "Name" --fields "key:type[:opts]; ..."
|
||||
pad item edit <ref> # Open in $EDITOR
|
||||
pad workspace init [--template X] # Create workspace
|
||||
pad agent install [tool] # Install /pad skill for AI tools
|
||||
pad workspace onboard # Analyze codebase, suggest conventions
|
||||
pad server open # Open web UI in browser
|
||||
pad project watch # Real-time activity stream
|
||||
pad github link [item-ref] # Link current branch's PR to item
|
||||
pad github status [item-ref] # Show PR status for linked items
|
||||
pad github unlink <item-ref> # Remove PR link from item
|
||||
pad bulk-update --status done TASK-5 TASK-8 # Batch operations
|
||||
pad webhooks list/create/delete/test # Webhook management
|
||||
pad setup # Initialize a fresh instance with the first admin
|
||||
pad login # Log in
|
||||
pad logout # Sign out
|
||||
pad whoami # Show current user
|
||||
pad members # List workspace members
|
||||
pad invite <email> [--role X] # Invite user to workspace
|
||||
pad join <code> # Accept workspace invitation
|
||||
pad item bulk-update --status done TASK-5 TASK-8 # Batch operations
|
||||
pad webhook list/create/delete/test # Webhook management
|
||||
pad auth setup # Initialize a fresh instance with the first admin
|
||||
pad auth login # Log in
|
||||
pad auth logout # Sign out
|
||||
pad auth whoami # Show current user
|
||||
pad workspace members # List workspace members
|
||||
pad workspace invite <email> [--role X] # Invite user to workspace
|
||||
pad workspace join <code> # Accept workspace invitation
|
||||
```
|
||||
|
||||
Collection names accept singular forms: `task`→`tasks`, `idea`→`ideas`, `doc`→`docs`.
|
||||
@@ -177,7 +177,7 @@ Collection names accept singular forms: `task`→`tasks`, `idea`→`ideas`, `doc
|
||||
- **Items** have structured `fields` JSON + optional rich `content` (markdown)
|
||||
- **Wiki-links** `[[Title]]` resolve across all items, rendered as clickable links
|
||||
- **Default collections:** Tasks, Ideas, Phases, Docs
|
||||
- **Templates:** startup (default), scrum, product — set via `pad init --template`
|
||||
- **Templates:** startup (default), scrum, product — set via `pad workspace init --template`
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
@@ -25,24 +25,24 @@ install: build
|
||||
rm -f ~/.pad/pad.pid
|
||||
@echo "Installed $(BINARY) to $(INSTALL_DIR)/$(BINARY)"
|
||||
@# Trigger server auto-start by running a command
|
||||
@$(INSTALL_DIR)/$(BINARY) status 2>/dev/null || true
|
||||
@$(INSTALL_DIR)/$(BINARY) auth whoami 2>/dev/null || true
|
||||
@echo "Server restarted."
|
||||
|
||||
test:
|
||||
go test ./... -v
|
||||
|
||||
dev: build-go
|
||||
./$(BINARY) serve --host $(HOST)
|
||||
./$(BINARY) server start --host $(HOST)
|
||||
|
||||
serve: build
|
||||
-./$(BINARY) stop 2>/dev/null
|
||||
-./$(BINARY) server stop 2>/dev/null
|
||||
@sleep 1
|
||||
./$(BINARY) serve --host $(HOST)
|
||||
./$(BINARY) server start --host $(HOST)
|
||||
|
||||
restart: build-go
|
||||
-./$(BINARY) stop 2>/dev/null
|
||||
-./$(BINARY) server stop 2>/dev/null
|
||||
@sleep 1
|
||||
./$(BINARY) serve --host $(HOST)
|
||||
./$(BINARY) server start --host $(HOST)
|
||||
|
||||
web:
|
||||
cd web && npm ci && npm run build
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
```bash
|
||||
brew install xarmian/tap/pad
|
||||
cd your-project
|
||||
pad configure
|
||||
pad init
|
||||
pad open
|
||||
pad auth configure
|
||||
pad workspace init
|
||||
pad server open
|
||||
```
|
||||
|
||||
For a local install, choose `Local` in `pad configure`. Pad will remember that this client manages a local server, auto-start it when needed, and open the web UI at `localhost:7777`.
|
||||
For a local install, choose `Local` in `pad auth configure`. Pad will remember that this client manages a local server, auto-start it when needed, and open the web UI at `localhost:7777`.
|
||||
|
||||
## Why Pad?
|
||||
|
||||
@@ -38,7 +38,7 @@ Tools like Linear, Jira, and Notion are built for teams on the cloud. Pad is bui
|
||||
|
||||
| | Pad | Linear / Jira | Notion |
|
||||
|---|---|---|---|
|
||||
| **Setup** | `pad configure` + `pad init` | Create account, invite team, configure | Create account, pick template |
|
||||
| **Setup** | `pad auth configure` + `pad workspace init` | Create account, invite team, configure | Create account, pick template |
|
||||
| **AI agents** | Native `/pad` skill for 7+ tools | Third-party integrations | Third-party integrations |
|
||||
| **Data** | Local SQLite, you own it | Their cloud | Their cloud |
|
||||
| **Offline** | Full functionality | Read-only cache at best | Limited |
|
||||
@@ -52,12 +52,12 @@ Tools like Linear, Jira, and Notion are built for teams on the cloud. Pad is bui
|
||||
**CLI that doesn't get in your way.** Create tasks, search items, check status — without leaving the terminal.
|
||||
|
||||
```bash
|
||||
pad create task "Fix OAuth redirect" --priority high
|
||||
pad create idea "Real-time collaboration" --category infrastructure
|
||||
pad list tasks --status in-progress
|
||||
pad search "authentication"
|
||||
pad status # Project dashboard
|
||||
pad next # What should I work on?
|
||||
pad item create task "Fix OAuth redirect" --priority high
|
||||
pad item create idea "Real-time collaboration" --category infrastructure
|
||||
pad item list tasks --status in-progress
|
||||
pad item search "authentication"
|
||||
pad project dashboard # Project dashboard
|
||||
pad project next # What should I work on?
|
||||
```
|
||||
|
||||
**Web UI that stays out of your way.** A clean, dark-themed interface at `localhost:7777` with:
|
||||
@@ -76,7 +76,7 @@ pad next # What should I work on?
|
||||
**Your agent becomes a project partner.** Install the `/pad` skill once, and your AI coding tool can read, create, and update project items through natural language.
|
||||
|
||||
```bash
|
||||
pad install # Auto-detects your tools and installs the skill
|
||||
pad agent install # Auto-detects your tools and installs the skill
|
||||
```
|
||||
|
||||
Works with **Claude Code**, **Cursor**, **Windsurf**, **Codex**, **GitHub Copilot**, **Amazon Q**, and **JetBrains Junie**.
|
||||
@@ -96,7 +96,7 @@ Then just talk to your project:
|
||||
- **Playbooks** — multi-step workflows like "when implementing a feature: read the spec, create a branch, write tests first, then implement"
|
||||
|
||||
```bash
|
||||
pad create convention "Run tests before completing tasks" \
|
||||
pad item create convention "Run tests before completing tasks" \
|
||||
--field trigger=on-task-complete \
|
||||
--field scope=all \
|
||||
--field priority=must
|
||||
@@ -107,7 +107,7 @@ Agents load relevant conventions automatically. All agent actions are attributed
|
||||
**Onboard agents to a new codebase:**
|
||||
|
||||
```bash
|
||||
pad onboard # Analyzes project structure and suggests conventions
|
||||
pad workspace onboard # Analyzes project structure and suggests conventions
|
||||
```
|
||||
|
||||
### Collections & Custom Fields
|
||||
@@ -128,7 +128,7 @@ Pad organizes work into **collections** — typed containers with structured fie
|
||||
**Create your own** with typed fields — select, text, date, number, url, relation, checkbox:
|
||||
|
||||
```bash
|
||||
pad collections create "Bug Reports" \
|
||||
pad collection create "Bug Reports" \
|
||||
--fields "severity:select:low,medium,high,critical; browser:text; reproducible:checkbox"
|
||||
```
|
||||
|
||||
@@ -180,7 +180,7 @@ Pre-built binaries for macOS, Linux, and Windows are available on the [releases
|
||||
### 1. Configure this Pad client
|
||||
|
||||
```bash
|
||||
pad configure
|
||||
pad auth configure
|
||||
```
|
||||
|
||||
For most local installs, choose `Local`. If you're connecting to another Pad server, choose `Remote` or `Docker` and enter its base URL.
|
||||
@@ -189,35 +189,35 @@ For most local installs, choose `Local`. If you're connecting to another Pad ser
|
||||
|
||||
```bash
|
||||
cd ~/projects/myapp
|
||||
pad init "My App"
|
||||
pad workspace init "My App"
|
||||
```
|
||||
|
||||
This creates a `.pad.toml` file linking your project directory to a Pad workspace with default collections. Choose a template to start with pre-configured collections:
|
||||
|
||||
```bash
|
||||
pad init "My App" --template scrum # Scrum-style with sprints
|
||||
pad init "My App" --template product # Product management focused
|
||||
pad workspace init "My App" --template scrum # Scrum-style with sprints
|
||||
pad workspace init "My App" --template product # Product management focused
|
||||
```
|
||||
|
||||
### 3. Install the AI skill
|
||||
|
||||
```bash
|
||||
pad install # Auto-detect and install for all found tools
|
||||
pad install claude # Or install for a specific tool
|
||||
pad install cursor
|
||||
pad install copilot
|
||||
pad agent install # Auto-detect and install for all found tools
|
||||
pad agent install claude # Or install for a specific tool
|
||||
pad agent install cursor
|
||||
pad agent install copilot
|
||||
```
|
||||
|
||||
### 4. Start working
|
||||
|
||||
```bash
|
||||
# From the CLI
|
||||
pad create task "Set up CI pipeline" --priority high
|
||||
pad create idea "Add WebSocket support" --category infrastructure
|
||||
pad status
|
||||
pad item create task "Set up CI pipeline" --priority high
|
||||
pad item create idea "Add WebSocket support" --category infrastructure
|
||||
pad project dashboard
|
||||
|
||||
# From the web UI
|
||||
pad open # Opens localhost:7777 in your browser
|
||||
pad server open # Opens localhost:7777 in your browser
|
||||
|
||||
# From your AI agent
|
||||
# Just use /pad in Claude Code, Cursor, etc.
|
||||
@@ -226,86 +226,101 @@ pad open # Opens localhost:7777 in your browser
|
||||
### 5. Teach your agents the rules
|
||||
|
||||
```bash
|
||||
pad onboard # Auto-analyze project and suggest conventions
|
||||
pad workspace onboard # Auto-analyze project and suggest conventions
|
||||
# Or browse the convention library
|
||||
pad library conventions # Pre-built conventions you can adopt
|
||||
pad library playbooks # Pre-built multi-step workflows
|
||||
pad library list --type conventions # Pre-built conventions you can adopt
|
||||
pad library list --type playbooks # Pre-built multi-step workflows
|
||||
```
|
||||
|
||||
## CLI Reference
|
||||
|
||||
```
|
||||
pad configure Configure how this client connects to Pad
|
||||
pad init [name] Initialize workspace in current directory
|
||||
pad open Open web UI in browser
|
||||
pad install [tool] Install /pad skill for AI coding tools
|
||||
pad onboard Analyze project and suggest conventions
|
||||
pad auth configure Configure how this client connects to Pad
|
||||
pad auth setup Initialize the first admin account
|
||||
pad auth login Sign in
|
||||
pad auth whoami Show current user
|
||||
|
||||
pad create <coll> "title" Create item (task, idea, phase, doc, ...)
|
||||
pad list [collection] List items (filters: --status, --priority, --all)
|
||||
pad show <slug> Show item detail
|
||||
pad update <slug> Update item fields
|
||||
pad delete <slug> Delete item
|
||||
pad move <slug> <collection> Move item between collections
|
||||
pad edit <slug> Open item in $EDITOR
|
||||
pad search "query" Full-text search across all items
|
||||
pad server start Start the Pad API server
|
||||
pad server stop Stop the Pad server
|
||||
pad server open Open web UI in browser
|
||||
|
||||
pad status Project dashboard
|
||||
pad next Recommended next task
|
||||
pad ready Query actionable next items
|
||||
pad stale Query stalled or attention-worthy items
|
||||
pad related <ref> Show direct relationships for an item
|
||||
pad implemented-by <ref> Show incoming implementers for an item
|
||||
pad collections List collections with item counts
|
||||
pad comment <slug> "text" Add comment to an item
|
||||
pad comments <slug> View item comments
|
||||
pad note <ref> "summary" Append an implementation note to an item
|
||||
pad decide <ref> "decision" Append a decision log entry to an item
|
||||
pad workspace init [name] Initialize workspace in current directory
|
||||
pad workspace link <workspace> Link current directory to an existing workspace
|
||||
pad workspace list List all workspaces
|
||||
pad workspace switch <workspace> Switch active workspace
|
||||
pad workspace onboard Analyze project and suggest conventions
|
||||
pad workspace members List workspace members
|
||||
pad workspace invite <email> Invite a workspace member
|
||||
pad workspace join <code> Accept an invitation
|
||||
pad workspace export Export workspace data
|
||||
pad workspace import <file> Import workspace data
|
||||
|
||||
pad standup [--days N] Daily standup report
|
||||
pad changelog [--days N] Release notes from completed items
|
||||
pad watch Real-time activity stream
|
||||
pad project dashboard Project dashboard
|
||||
pad project next Recommended next task
|
||||
pad project ready Query actionable next items
|
||||
pad project stale Query stalled or attention-worthy items
|
||||
pad project standup [--days N] Daily standup report
|
||||
pad project changelog [--days N] Release notes from completed items
|
||||
pad project watch Real-time activity stream
|
||||
pad project reconcile Reconcile item and PR state
|
||||
|
||||
pad blocks <src> <target> Create dependency
|
||||
pad blocked-by <item> <blk> Mark item as blocked
|
||||
pad deps <slug> Show dependencies
|
||||
pad unblock <src> <target> Remove dependency
|
||||
pad item create <coll> "title" Create item (task, idea, phase, doc, ...)
|
||||
pad item list [collection] List items (filters: --status, --priority, --all)
|
||||
pad item show <ref> Show item detail
|
||||
pad item update <ref> Update item fields
|
||||
pad item delete <ref> Delete item
|
||||
pad item move <ref> <collection> Move item between collections
|
||||
pad item edit <ref> Open item in $EDITOR
|
||||
pad item search "query" Full-text search across all items
|
||||
pad item comment <ref> "text" Add comment to an item
|
||||
pad item comments <ref> View item comments
|
||||
pad item note <ref> "summary" Append an implementation note to an item
|
||||
pad item decide <ref> "decision" Append a decision log entry to an item
|
||||
pad item block <src> <target> Create dependency
|
||||
pad item blocked-by <item> <blk> Mark item as blocked
|
||||
pad item deps <ref> Show dependencies
|
||||
pad item unblock <src> <target> Remove dependency
|
||||
pad item related <ref> Show direct relationships for an item
|
||||
pad item implemented-by <ref> Show incoming implementers for an item
|
||||
pad item bulk-update --status X Batch update multiple items
|
||||
|
||||
pad collection list List collections with item counts
|
||||
pad collection create <name> Create a custom collection
|
||||
|
||||
pad library list Browse convention and playbook library
|
||||
pad library activate <title> Activate a convention or playbook
|
||||
|
||||
pad agent install [tool] Install /pad skill for AI coding tools
|
||||
pad agent status Show supported tools and installation status
|
||||
pad agent update Update installed tool integrations
|
||||
|
||||
pad github link [item-ref] Link current branch's PR to item
|
||||
pad github status [item-ref] Show PR status for linked items
|
||||
pad github unlink <item-ref> Remove PR link from item
|
||||
|
||||
pad webhooks list List workspace webhooks
|
||||
pad webhooks create <url> Create webhook
|
||||
pad bulk-update --status X Batch update multiple items
|
||||
|
||||
pad export Export workspace data
|
||||
pad import <file> Import workspace data
|
||||
|
||||
pad workspaces List all workspaces
|
||||
pad switch <workspace> Switch active workspace
|
||||
pad library [type] Browse convention and playbook library
|
||||
pad webhook list List workspace webhooks
|
||||
pad webhook create <url> Create webhook
|
||||
```
|
||||
|
||||
All commands accept `--format json` for machine-readable output and `--workspace` to target a specific workspace.
|
||||
|
||||
### Authentication
|
||||
|
||||
Pad runs without authentication by default for frictionless local use. On a fresh instance, run `pad setup` on the server host to create the first admin account:
|
||||
Pad runs without authentication by default for frictionless local use. On a fresh instance, run `pad auth setup` on the server host to create the first admin account:
|
||||
|
||||
```bash
|
||||
pad setup # Initialize the first admin account
|
||||
pad login # Sign in
|
||||
pad whoami # Show current user
|
||||
pad logout # Sign out
|
||||
pad auth setup # Initialize the first admin account
|
||||
pad auth login # Sign in
|
||||
pad auth whoami # Show current user
|
||||
pad auth logout # Sign out
|
||||
```
|
||||
|
||||
Once a user exists, all API requests and web UI access require authentication. Credentials are stored in `~/.pad/credentials.json`. Multiple users can be invited to workspaces with role-based access control (`owner`, `editor`, `viewer`).
|
||||
|
||||
```bash
|
||||
pad members # List workspace members
|
||||
pad invite user@example.com # Invite to workspace
|
||||
pad join <code> # Accept invitation
|
||||
pad workspace members # List workspace members
|
||||
pad workspace invite user@example.com
|
||||
pad workspace join <code>
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -63,7 +63,7 @@ func getConfiguredConfig() *config.Config {
|
||||
}
|
||||
|
||||
if !canPromptForConfig() {
|
||||
fmt.Fprintln(os.Stderr, "Pad is not configured. Run 'pad configure' first.")
|
||||
fmt.Fprintln(os.Stderr, "Pad is not configured. Run 'pad auth configure' first.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func getConfiguredConfig() *config.Config {
|
||||
|
||||
cfg = getConfig()
|
||||
if !cfg.IsConfigured() {
|
||||
fmt.Fprintln(os.Stderr, "Error: Pad configuration was not saved. Run 'pad configure' again.")
|
||||
fmt.Fprintln(os.Stderr, "Error: Pad configuration was not saved. Run 'pad auth configure' again.")
|
||||
os.Exit(1)
|
||||
}
|
||||
return cfg
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
package main
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func authCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "auth",
|
||||
Short: "Configure authentication and account access",
|
||||
}
|
||||
cmd.AddCommand(
|
||||
configureCmd(),
|
||||
setupCmd(),
|
||||
loginCmd(),
|
||||
logoutCmd(),
|
||||
whoamiCmd(),
|
||||
resetPasswordCmd(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func serverCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Manage the Pad server process and web UI",
|
||||
}
|
||||
cmd.AddCommand(
|
||||
serveCmd(),
|
||||
stopCmd(),
|
||||
openCmd(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func workspaceCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "workspace",
|
||||
Short: "Manage workspaces and workspace membership",
|
||||
}
|
||||
cmd.AddCommand(
|
||||
initCmd(),
|
||||
linkCmd(),
|
||||
switchCmd(),
|
||||
workspacesCmd(),
|
||||
onboardCmd(),
|
||||
membersCmd(),
|
||||
inviteCmd(),
|
||||
joinCmd(),
|
||||
exportCmd(),
|
||||
importCmd(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func projectCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "project",
|
||||
Short: "Inspect project state, reports, and activity",
|
||||
}
|
||||
cmd.AddCommand(
|
||||
statusCmd(),
|
||||
nextCmd(),
|
||||
readyCmd(),
|
||||
staleCmd(),
|
||||
standupCmd(),
|
||||
changelogCmd(),
|
||||
watchCmd(),
|
||||
reconcileCmd(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func itemCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "item",
|
||||
Short: "Create, update, relate, and discuss Pad items",
|
||||
}
|
||||
cmd.AddCommand(
|
||||
createCmd(),
|
||||
listCmd(),
|
||||
showCmd(),
|
||||
updateCmd(),
|
||||
deleteCmd(),
|
||||
moveCmd(),
|
||||
editCmd(),
|
||||
searchCmd(),
|
||||
bulkUpdateCmd(),
|
||||
commentCmd(),
|
||||
commentsCmd(),
|
||||
noteCmd(),
|
||||
decideCmd(),
|
||||
blocksCmd(),
|
||||
blockedByCmd(),
|
||||
depsCmd(),
|
||||
unblockCmd(),
|
||||
splitFromCmd(),
|
||||
supersedesCmd(),
|
||||
implementsCmd(),
|
||||
unsplitCmd(),
|
||||
unsupersedeCmd(),
|
||||
unimplementsCmd(),
|
||||
relatedCmd(),
|
||||
implementedByCmd(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func collectionCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "collection",
|
||||
Short: "List and create collections",
|
||||
}
|
||||
cmd.AddCommand(
|
||||
collectionsCmd(),
|
||||
collectionsCreateCmd(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func libraryGroupCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "library",
|
||||
Short: "Browse and activate pre-built conventions and playbooks",
|
||||
}
|
||||
cmd.AddCommand(
|
||||
libraryCmd(),
|
||||
libraryActivateCmd(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func agentCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "agent",
|
||||
Short: "Install and manage Pad agent skills",
|
||||
}
|
||||
cmd.AddCommand(
|
||||
installCmd(),
|
||||
agentUpdateCmd(),
|
||||
agentStatusCmd(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func agentUpdateCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Update installed Pad skills across all supported tools",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return installUpdate()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func agentStatusCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "status",
|
||||
Short: "Show installed Pad skill status across supported tools",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return installList()
|
||||
},
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -23,7 +23,7 @@ func splitFromCmd() *cobra.Command {
|
||||
|
||||
The first item is the derived item, and the second item is the original source.
|
||||
For example:
|
||||
pad split-from TASK-122 TASK-121`,
|
||||
pad item split-from TASK-122 TASK-121`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return createLineageLink(lineageLinkSpec{
|
||||
@@ -42,7 +42,7 @@ func supersedesCmd() *cobra.Command {
|
||||
|
||||
The first item is the newer replacement, and the second item is the older item.
|
||||
For example:
|
||||
pad supersedes TASK-130 TASK-118`,
|
||||
pad item supersedes TASK-130 TASK-118`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return createLineageLink(lineageLinkSpec{
|
||||
@@ -61,7 +61,7 @@ func implementsCmd() *cobra.Command {
|
||||
|
||||
The first item is the implementation work item, and the second item is the item being implemented.
|
||||
For example:
|
||||
pad implements TASK-121 IDEA-108`,
|
||||
pad item implements TASK-121 IDEA-108`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return createLineageLink(lineageLinkSpec{
|
||||
|
||||
+85
-188
@@ -73,66 +73,17 @@ func main() {
|
||||
rootCmd.PersistentFlags().StringVar(&urlFlag, "url", "", "server URL override (e.g., https://api.getpad.dev)")
|
||||
|
||||
rootCmd.AddCommand(
|
||||
serveCmd(),
|
||||
stopCmd(),
|
||||
configureCmd(),
|
||||
setupCmd(),
|
||||
openCmd(),
|
||||
loginCmd(),
|
||||
logoutCmd(),
|
||||
whoamiCmd(),
|
||||
initCmd(),
|
||||
linkCmd(),
|
||||
onboardCmd(),
|
||||
workspacesCmd(),
|
||||
switchCmd(),
|
||||
skillsCmd(),
|
||||
installCmd(),
|
||||
completionCmd(),
|
||||
// v2 commands
|
||||
createCmd(),
|
||||
listCmd(),
|
||||
showCmd(),
|
||||
updateCmd(),
|
||||
deleteCmd(),
|
||||
moveCmd(),
|
||||
searchCmd(),
|
||||
reconcileCmd(),
|
||||
statusCmd(),
|
||||
nextCmd(),
|
||||
standupCmd(),
|
||||
changelogCmd(),
|
||||
collectionsCmd(),
|
||||
editCmd(),
|
||||
libraryCmd(),
|
||||
readyCmd(),
|
||||
staleCmd(),
|
||||
relatedCmd(),
|
||||
implementedByCmd(),
|
||||
commentCmd(),
|
||||
commentsCmd(),
|
||||
noteCmd(),
|
||||
decideCmd(),
|
||||
blocksCmd(),
|
||||
blockedByCmd(),
|
||||
splitFromCmd(),
|
||||
supersedesCmd(),
|
||||
implementsCmd(),
|
||||
depsCmd(),
|
||||
unblockCmd(),
|
||||
unsplitCmd(),
|
||||
unsupersedeCmd(),
|
||||
unimplementsCmd(),
|
||||
exportCmd(),
|
||||
importCmd(),
|
||||
watchCmd(),
|
||||
webhooksCmd(),
|
||||
bulkUpdateCmd(),
|
||||
authCmd(),
|
||||
serverCmd(),
|
||||
workspaceCmd(),
|
||||
projectCmd(),
|
||||
itemCmd(),
|
||||
collectionCmd(),
|
||||
libraryGroupCmd(),
|
||||
agentCmd(),
|
||||
githubCmd(),
|
||||
membersCmd(),
|
||||
inviteCmd(),
|
||||
joinCmd(),
|
||||
resetPasswordCmd(),
|
||||
webhooksCmd(),
|
||||
completionCmd(),
|
||||
)
|
||||
|
||||
rootCmd.RegisterFlagCompletionFunc("workspace", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
@@ -205,7 +156,7 @@ func serveCmd() *cobra.Command {
|
||||
var port int
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "serve",
|
||||
Use: "start",
|
||||
Short: "Start the Pad API server",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cfg := getConfig()
|
||||
@@ -354,9 +305,9 @@ func setupCmd() *cobra.Command {
|
||||
if cfg.IsConfigured() {
|
||||
switch cfg.Mode {
|
||||
case config.ModeDocker:
|
||||
return fmt.Errorf("docker-managed Pad must be initialized from inside the container; run 'docker exec -it <container> pad setup'")
|
||||
return fmt.Errorf("docker-managed Pad must be initialized from inside the container; run 'docker exec -it <container> pad auth setup'")
|
||||
case config.ModeRemote, config.ModeCloud:
|
||||
return fmt.Errorf("remote Pad instances must be initialized on the server host with 'pad setup'")
|
||||
return fmt.Errorf("remote Pad instances must be initialized on the server host with 'pad auth setup'")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,7 +325,7 @@ func setupCmd() *cobra.Command {
|
||||
fmt.Println("Pad is already initialized and you are logged in.")
|
||||
return nil
|
||||
}
|
||||
fmt.Println("Pad is already initialized. Run 'pad login' to sign in.")
|
||||
fmt.Println("Pad is already initialized. Run 'pad auth login' to sign in.")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -515,11 +466,11 @@ func printSetupRequiredHint(cfg *config.Config) {
|
||||
fmt.Println("This Pad instance has not been initialized yet.")
|
||||
switch cfg.Mode {
|
||||
case config.ModeDocker:
|
||||
fmt.Println("Run 'pad setup' inside the container, for example: docker exec -it <container> pad setup")
|
||||
fmt.Println("Run 'pad auth setup' inside the container, for example: docker exec -it <container> pad auth setup")
|
||||
case config.ModeRemote, config.ModeCloud:
|
||||
fmt.Println("Run 'pad setup' on the machine or container running the Pad server, then try again.")
|
||||
fmt.Println("Run 'pad auth setup' on the machine or container running the Pad server, then try again.")
|
||||
default:
|
||||
fmt.Println("Run 'pad setup' to create the first admin account, then try again.")
|
||||
fmt.Println("Run 'pad auth setup' to create the first admin account, then try again.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,7 +525,7 @@ func whoamiCmd() *cobra.Command {
|
||||
return fmt.Errorf("load credentials: %w", err)
|
||||
}
|
||||
if creds == nil || creds.Token == "" {
|
||||
fmt.Println("Not logged in. Run 'pad login'.")
|
||||
fmt.Println("Not logged in. Run 'pad auth login'.")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -587,7 +538,7 @@ func whoamiCmd() *cobra.Command {
|
||||
|
||||
user, err := client.GetCurrentUser()
|
||||
if err != nil {
|
||||
fmt.Println("Session expired. Run 'pad login'.")
|
||||
fmt.Println("Session expired. Run 'pad auth login'.")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -708,7 +659,7 @@ func inviteCmd() *cobra.Command {
|
||||
} else {
|
||||
code, _ := result["code"].(string)
|
||||
fmt.Printf(" Join code: %s\n", code)
|
||||
fmt.Printf(" They can accept with: pad join %s\n", code)
|
||||
fmt.Printf(" They can accept with: pad workspace join %s\n", code)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,7 +732,7 @@ func initCmd() *cobra.Command {
|
||||
Long: `Create a workspace and link it to the current directory.
|
||||
|
||||
Use --template to choose a workspace template:
|
||||
pad init myproject --template scrum
|
||||
pad workspace init myproject --template scrum
|
||||
|
||||
Use --list-templates to see available templates.`,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
@@ -927,11 +878,11 @@ func linkCmd() *cobra.Command {
|
||||
Short: "Link the current directory to an existing workspace",
|
||||
Long: `Link the current directory to an existing workspace by creating a .pad.toml file.
|
||||
|
||||
Unlike 'pad init', this does NOT create a new workspace — it only links to one that already exists.
|
||||
Unlike 'pad workspace init', this does NOT create a new workspace — it only links to one that already exists.
|
||||
|
||||
pad link myproject
|
||||
pad workspace link myproject
|
||||
|
||||
Use 'pad workspaces' to see available workspaces.`,
|
||||
Use 'pad workspace list' to see available workspaces.`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -968,7 +919,7 @@ Use 'pad workspaces' to see available workspaces.`,
|
||||
for _, w := range workspaces {
|
||||
fmt.Fprintf(os.Stderr, " %-20s (slug: %s)\n", w.Name, w.Slug)
|
||||
}
|
||||
return fmt.Errorf("workspace %q does not exist — use 'pad init %s' to create it", nameOrSlug, nameOrSlug)
|
||||
return fmt.Errorf("workspace %q does not exist — use 'pad workspace init %s' to create it", nameOrSlug, nameOrSlug)
|
||||
}
|
||||
|
||||
if err := cli.WriteWorkspaceLink(cwd, ws.Slug); err != nil {
|
||||
@@ -1016,7 +967,7 @@ func offerSkillInstall() {
|
||||
recordInstallation(tool.Name, path)
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n/pad skill already installed for %d tool(s). Run 'pad install --update' to update.\n", len(detected))
|
||||
fmt.Printf("\n/pad skill already installed for %d tool(s). Run 'pad agent update' to update.\n", len(detected))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1055,7 +1006,7 @@ func offerSkillInstall() {
|
||||
|
||||
choice := readChoice()
|
||||
if choice == "n" || choice == "N" {
|
||||
fmt.Println("Skipped. Run 'pad install' later.")
|
||||
fmt.Println("Skipped. Run 'pad agent install' later.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1099,7 +1050,7 @@ func printOnboardingHints() {
|
||||
fmt.Printf(" %s %s\n", cyan.Sprint("/pad"), "create a phase for what I'm working on")
|
||||
fmt.Println()
|
||||
fmt.Printf("Or open the web UI at %s\n", bold.Sprint("http://localhost:7777"))
|
||||
fmt.Println(dim.Sprint("Run 'pad status' to see your project dashboard"))
|
||||
fmt.Println(dim.Sprint("Run 'pad project dashboard' to see your project dashboard"))
|
||||
}
|
||||
|
||||
// --- onboard ---
|
||||
@@ -1187,7 +1138,7 @@ recommend conventions from the built-in library.`,
|
||||
if !cli.IsTerminal() {
|
||||
// Non-interactive: just print suggestions
|
||||
fmt.Println()
|
||||
fmt.Println("Run 'pad onboard' in a terminal to activate, or use:")
|
||||
fmt.Println("Run 'pad workspace onboard' in a terminal to activate, or use:")
|
||||
fmt.Println(" /pad what conventions should this project follow?")
|
||||
return nil
|
||||
}
|
||||
@@ -1242,53 +1193,6 @@ recommend conventions from the built-in library.`,
|
||||
return cmd
|
||||
}
|
||||
|
||||
// --- skills ---
|
||||
|
||||
func skillsCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "skills",
|
||||
Short: "Manage skill installation (use 'pad install' for multi-tool support)",
|
||||
}
|
||||
|
||||
installCmd := &cobra.Command{
|
||||
Use: "install",
|
||||
Short: "Install Claude Code skills",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
global, _ := cmd.Flags().GetBool("global")
|
||||
target := "project"
|
||||
if global {
|
||||
target = "global"
|
||||
}
|
||||
path, err := cli.InstallSkill(pad.PadSkill, target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Installed /pad skill to %s\n", path)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
installCmd.Flags().Bool("global", false, "install to ~/.claude/skills/")
|
||||
|
||||
updateCmd := &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Update all installed skills across all projects",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return installUpdate()
|
||||
},
|
||||
}
|
||||
|
||||
statusSubCmd := &cobra.Command{
|
||||
Use: "status",
|
||||
Short: "Show skill installation status across all projects",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return installList()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(installCmd, updateCmd, statusSubCmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// --- install ---
|
||||
|
||||
func installCmd() *cobra.Command {
|
||||
@@ -1310,11 +1214,11 @@ Supported tools:
|
||||
junie JetBrains Junie (.junie/guidelines/)
|
||||
|
||||
Examples:
|
||||
pad install # Auto-detect and install
|
||||
pad install claude # Install for Claude Code
|
||||
pad install cursor # Install for Cursor/Codex/Windsurf
|
||||
pad install --all # Install for all detected tools
|
||||
pad install --list # Show supported tools and status`,
|
||||
pad agent install # Auto-detect and install
|
||||
pad agent install claude # Install for Claude Code
|
||||
pad agent install cursor # Install for Cursor/Codex/Windsurf
|
||||
pad agent install --all # Install for all detected tools
|
||||
pad agent status # Show supported tools and status`,
|
||||
ValidArgs: cli.AllToolNames(),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
listFlag, _ := cmd.Flags().GetBool("list")
|
||||
@@ -1409,7 +1313,7 @@ func installList() error {
|
||||
}
|
||||
|
||||
if outdatedCount > 0 {
|
||||
fmt.Printf("\n %d installation(s) can be updated. Run 'pad install --update' to update all.\n", outdatedCount)
|
||||
fmt.Printf("\n %d installation(s) can be updated. Run 'pad agent update' to update all.\n", outdatedCount)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1437,7 +1341,7 @@ func installUpdate() error {
|
||||
reg, err := cli.LoadRegistry()
|
||||
if err != nil {
|
||||
if localUpdated == 0 {
|
||||
fmt.Println("No tools installed. Run 'pad install' first.")
|
||||
fmt.Println("No tools installed. Run 'pad agent install' first.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1463,7 +1367,7 @@ func installUpdate() error {
|
||||
total := localUpdated + remoteUpdated
|
||||
if total == 0 {
|
||||
if localUpdated == 0 && len(reg.Installations) == 0 {
|
||||
fmt.Println("No tools installed. Run 'pad install' first.")
|
||||
fmt.Println("No tools installed. Run 'pad agent install' first.")
|
||||
} else {
|
||||
fmt.Println("All installations are up to date.")
|
||||
}
|
||||
@@ -1497,7 +1401,7 @@ func recordInstallation(toolName, skillPath string) {
|
||||
func installForTool(name string) error {
|
||||
tool := cli.ResolveTool(name)
|
||||
if tool == nil {
|
||||
return fmt.Errorf("unknown tool %q. Run 'pad install --list' to see supported tools", name)
|
||||
return fmt.Errorf("unknown tool %q. Run 'pad agent status' to see supported tools", name)
|
||||
}
|
||||
|
||||
content := cli.FormatForTool(*tool, pad.PadSkill)
|
||||
@@ -1574,7 +1478,7 @@ func installInteractive() error {
|
||||
choice := readChoice()
|
||||
if choice == "n" || choice == "N" {
|
||||
fmt.Println()
|
||||
fmt.Println("Install individually with: pad install <tool>")
|
||||
fmt.Println("Install individually with: pad agent install <tool>")
|
||||
fmt.Println("Supported tools:", strings.Join(cli.AllToolNames(), ", "))
|
||||
return nil
|
||||
}
|
||||
@@ -1597,9 +1501,8 @@ func installInteractive() error {
|
||||
|
||||
func workspacesCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "workspaces",
|
||||
Aliases: []string{"ws"},
|
||||
Short: "List all workspaces",
|
||||
Use: "list",
|
||||
Short: "List all workspaces",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
workspaces, err := client.ListWorkspaces()
|
||||
@@ -1607,7 +1510,7 @@ func workspacesCmd() *cobra.Command {
|
||||
return err
|
||||
}
|
||||
if len(workspaces) == 0 {
|
||||
fmt.Println("No workspaces. Run 'pad init' to create one.")
|
||||
fmt.Println("No workspaces. Run 'pad workspace init' to create one.")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1709,10 +1612,10 @@ func createCmd() *cobra.Command {
|
||||
Long: `Create a new item in the specified collection.
|
||||
|
||||
Examples:
|
||||
pad create task "Fix OAuth redirect" --priority high
|
||||
pad create idea "Real-time collaboration" --category infrastructure
|
||||
pad create phase "API Redesign" --status active
|
||||
pad create doc "Payment Architecture" --category architecture --stdin
|
||||
pad item create task "Fix OAuth redirect" --priority high
|
||||
pad item create idea "Real-time collaboration" --category infrastructure
|
||||
pad item create phase "API Redesign" --status active
|
||||
pad item create doc "Payment Architecture" --category architecture --stdin
|
||||
|
||||
Run with --help-collections to see available collections and their status values.`,
|
||||
ValidArgsFunction: completeCollectionNames,
|
||||
@@ -1849,11 +1752,11 @@ func listCmd() *cobra.Command {
|
||||
in that collection are shown. Items with status "done" are hidden by default.
|
||||
|
||||
Examples:
|
||||
pad list # all items, all collections
|
||||
pad list tasks # tasks (open + in_progress by default)
|
||||
pad list tasks --status done # only done tasks
|
||||
pad list ideas --status exploring # ideas being explored
|
||||
pad list --all # include done/completed items`,
|
||||
pad item list # all items, all collections
|
||||
pad item list tasks # tasks (open + in_progress by default)
|
||||
pad item list tasks --status done # only done tasks
|
||||
pad item list ideas --status exploring # ideas being explored
|
||||
pad item list --all # include done/completed items`,
|
||||
Aliases: []string{"ls"},
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
ValidArgsFunction: completeCollectionNames,
|
||||
@@ -2158,9 +2061,9 @@ func updateCmd() *cobra.Command {
|
||||
Items can be referenced by issue ID (e.g. TASK-5) or slug.
|
||||
|
||||
Examples:
|
||||
pad update TASK-5 --status done
|
||||
pad update PHASE-2 --status active --priority high
|
||||
pad update DOC-3 --stdin < updated-doc.md`,
|
||||
pad item update TASK-5 --status done
|
||||
pad item update PHASE-2 --status active --priority high
|
||||
pad item update DOC-3 --stdin < updated-doc.md`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -2319,8 +2222,8 @@ Incompatible fields are dropped. Use --field to set values for target-specific f
|
||||
Items can be referenced by issue ID (e.g. TASK-5) or slug.
|
||||
|
||||
Examples:
|
||||
pad move BUG-3 tasks # Move to tasks collection
|
||||
pad move IDEA-7 tasks --field priority=high # Move idea to tasks with priority`,
|
||||
pad item move BUG-3 tasks # Move to tasks collection
|
||||
pad item move IDEA-7 tasks --field priority=high # Move idea to tasks with priority`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -2416,12 +2319,12 @@ func commentsCmd() *cobra.Command {
|
||||
|
||||
func blocksCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "blocks <source-ref> <target-ref>",
|
||||
Use: "block <source-ref> <target-ref>",
|
||||
Short: "Mark that one item blocks another",
|
||||
Long: `Create a blocking dependency between two items.
|
||||
|
||||
The source item blocks the target item. For example:
|
||||
pad blocks TASK-5 TASK-8 # TASK-5 blocks TASK-8`,
|
||||
pad item block TASK-5 TASK-8 # TASK-5 blocks TASK-8`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -2476,7 +2379,7 @@ func blockedByCmd() *cobra.Command {
|
||||
Long: `Create a blocking dependency (reverse direction).
|
||||
|
||||
The source item is blocked by the blocker item. For example:
|
||||
pad blocked-by TASK-5 TASK-3 # TASK-5 is blocked by TASK-3`,
|
||||
pad item blocked-by TASK-5 TASK-3 # TASK-5 is blocked by TASK-3`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -2535,7 +2438,7 @@ Shows two sections:
|
||||
Blocked by: items that are blocking this item
|
||||
|
||||
Example:
|
||||
pad deps TASK-5`,
|
||||
pad item deps TASK-5`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -2616,7 +2519,7 @@ func unblockCmd() *cobra.Command {
|
||||
Long: `Remove a "blocks" relationship where source blocks target.
|
||||
|
||||
Example:
|
||||
pad unblock TASK-5 TASK-8 # TASK-5 no longer blocks TASK-8`,
|
||||
pad item unblock TASK-5 TASK-8 # TASK-5 no longer blocks TASK-8`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -2749,7 +2652,7 @@ func searchCmd() *cobra.Command {
|
||||
|
||||
func statusCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "status",
|
||||
Use: "dashboard",
|
||||
Short: "Show project dashboard — progress, attention items, suggested next",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -3424,10 +3327,9 @@ func collectionDefaultIcon(slug string) string {
|
||||
// --- collections ---
|
||||
|
||||
func collectionsCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "collections",
|
||||
Short: "List and manage collections",
|
||||
Aliases: []string{"coll"},
|
||||
return &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List collections with item counts",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
ws := getWorkspace()
|
||||
@@ -3445,9 +3347,6 @@ func collectionsCmd() *cobra.Command {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(collectionsCreateCmd())
|
||||
return cmd
|
||||
}
|
||||
|
||||
func collectionsCreateCmd() *cobra.Command {
|
||||
@@ -3469,8 +3368,8 @@ Fields DSL format: key:type[:option1,option2,...]
|
||||
Separate multiple fields with newlines or semicolons.
|
||||
|
||||
Examples:
|
||||
pad collections create "Bugs" --fields "status:select:new,triaged,fixing,resolved;severity:select:low,medium,high,critical;component:text"
|
||||
pad collections create "Decisions" --icon "⚖️" --fields "status:select:proposed,accepted,rejected;impact:select:low,medium,high"`,
|
||||
pad collection create "Bugs" --fields "status:select:new,triaged,fixing,resolved;severity:select:low,medium,high,critical;component:text"
|
||||
pad collection create "Decisions" --icon "⚖️" --fields "status:select:proposed,accepted,rejected;impact:select:low,medium,high"`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -3716,16 +3615,16 @@ func libraryCmd() *cobra.Command {
|
||||
var typeFilter string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "library",
|
||||
Short: "Browse and activate pre-built conventions and playbooks",
|
||||
Use: "list",
|
||||
Short: "Browse pre-built conventions and playbooks",
|
||||
Long: `Browse the convention and playbook libraries and activate items in your workspace.
|
||||
|
||||
Examples:
|
||||
pad library # List both conventions and playbooks
|
||||
pad library --type conventions # List conventions only
|
||||
pad library --type playbooks # List playbooks only
|
||||
pad library --category git # Filter by category
|
||||
pad library --format json # JSON output
|
||||
pad library list # List both conventions and playbooks
|
||||
pad library list --type conventions # List conventions only
|
||||
pad library list --type playbooks # List playbooks only
|
||||
pad library list --category git # Filter by category
|
||||
pad library list --format json # JSON output
|
||||
pad library activate "Commit after task completion" # Activate a convention or playbook`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -3806,8 +3705,6 @@ Examples:
|
||||
|
||||
cmd.Flags().StringVar(&categoryFilter, "category", "", "filter by category")
|
||||
cmd.Flags().StringVar(&typeFilter, "type", "", "filter by type: conventions, playbooks")
|
||||
|
||||
cmd.AddCommand(libraryActivateCmd())
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -4220,15 +4117,15 @@ func watchCmd() *cobra.Command {
|
||||
|
||||
func webhooksCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "webhooks",
|
||||
Use: "webhook",
|
||||
Short: "Manage workspace webhooks",
|
||||
Long: `Manage webhooks that receive POST notifications when events occur.
|
||||
|
||||
Examples:
|
||||
pad webhooks list
|
||||
pad webhooks create https://httpbin.org/post --events "item.created,item.updated"
|
||||
pad webhooks delete 7fde5e41
|
||||
pad webhooks test 7fde5e41`,
|
||||
pad webhook list
|
||||
pad webhook create https://httpbin.org/post --events "item.created,item.updated"
|
||||
pad webhook delete 7fde5e41
|
||||
pad webhook test 7fde5e41`,
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
@@ -4329,9 +4226,9 @@ func webhooksCreateCmd() *cobra.Command {
|
||||
Long: `Register a new webhook URL to receive event notifications.
|
||||
|
||||
Examples:
|
||||
pad webhooks create https://httpbin.org/post
|
||||
pad webhooks create https://slack.com/webhook/... --events "item.created,item.updated"
|
||||
pad webhooks create https://example.com/hook --secret "mysecret"`,
|
||||
pad webhook create https://httpbin.org/post
|
||||
pad webhook create https://slack.com/webhook/... --events "item.created,item.updated"
|
||||
pad webhook create https://example.com/hook --secret "mysecret"`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, _ := getClient()
|
||||
@@ -4430,9 +4327,9 @@ func bulkUpdateCmd() *cobra.Command {
|
||||
Items can be referenced by issue ID (e.g. TASK-5) or slug.
|
||||
|
||||
Examples:
|
||||
pad bulk-update --status done TASK-5 TASK-8 TASK-12
|
||||
pad bulk-update --priority high IDEA-3 IDEA-7
|
||||
pad bulk-update --status in_progress --priority urgent TASK-1 TASK-2`,
|
||||
pad item bulk-update --status done TASK-5 TASK-8 TASK-12
|
||||
pad item bulk-update --priority high IDEA-3 IDEA-7
|
||||
pad item bulk-update --status in_progress --priority urgent TASK-1 TASK-2`,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if status == "" && priority == "" {
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ func readyCmd() *cobra.Command {
|
||||
Short: "Show actionable next items for an agent",
|
||||
Long: `List the items that Pad currently considers ready to work on.
|
||||
|
||||
This is the broader query-oriented counterpart to 'pad next'. It reuses the
|
||||
This is the broader query-oriented counterpart to 'pad project next'. It reuses the
|
||||
dashboard's suggested-next logic and returns the current actionable backlog
|
||||
for active phases.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
@@ -202,7 +202,7 @@ applyTo: "**"
|
||||
}
|
||||
}
|
||||
|
||||
// AllToolNames returns all valid names and aliases that can be passed to `pad install`.
|
||||
// AllToolNames returns all valid names and aliases that can be passed to `pad agent install`.
|
||||
func AllToolNames() []string {
|
||||
var names []string
|
||||
for _, t := range SupportedTools {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
// ProjectInfo holds detected project metadata.
|
||||
type ProjectInfo struct {
|
||||
Language string // go, node, rust, python, java, etc.
|
||||
Language string // go, node, rust, python, java, etc.
|
||||
BuildTool string // make, npm, cargo, pip, maven, etc.
|
||||
TestCmd string // detected test command
|
||||
HasCI bool // CI config detected
|
||||
@@ -149,7 +149,7 @@ func SuggestedConventions(info ProjectInfo) map[string]string {
|
||||
|
||||
// Always suggest these general ones
|
||||
suggestions["Commit after task completion"] = "Create a git commit with a descriptive message after completing each discrete unit of work. Reference the task slug or item number in the commit message."
|
||||
suggestions["Update task status when starting work"] = "When starting work on a task, update its status to in-progress: `pad update <slug> --status in-progress`"
|
||||
suggestions["Update task status when starting work"] = "When starting work on a task, update its status to in-progress: `pad item update <ref> --status in-progress`"
|
||||
|
||||
return suggestions
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func EnsureServer(cfg *config.Config) error {
|
||||
return fmt.Errorf("find executable: %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(exePath, "serve")
|
||||
cmd := exec.Command(exePath, "server", "start")
|
||||
setSysProcAttr(cmd)
|
||||
|
||||
// Redirect stdout/stderr to log file
|
||||
|
||||
@@ -45,7 +45,7 @@ func DetectWorkspace(flagOverride string) (string, error) {
|
||||
dir = parent
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no workspace linked. Run 'pad init' to create one")
|
||||
return "", fmt.Errorf("no workspace linked. Run 'pad workspace init' to create one")
|
||||
}
|
||||
|
||||
// LoadPadToml finds and reads the nearest .pad.toml by walking up from cwd.
|
||||
|
||||
@@ -111,7 +111,7 @@ func ConventionLibrary() []LibraryCategory {
|
||||
Conventions: []LibraryConvention{
|
||||
{
|
||||
Title: "Update task status when starting work",
|
||||
Content: "When starting work on a task, update its status to in-progress: `pad update <slug> --status in-progress`",
|
||||
Content: "When starting work on a task, update its status to in-progress: `pad item update <ref> --status in-progress`",
|
||||
Category: "pm",
|
||||
Trigger: "on-task-start",
|
||||
Scope: "all",
|
||||
|
||||
@@ -220,7 +220,7 @@ func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
writeError(w, http.StatusForbidden, "forbidden", "This Pad instance must be initialized with pad setup")
|
||||
writeError(w, http.StatusForbidden, "forbidden", "This Pad instance must be initialized with pad auth setup")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
writeError(w, http.StatusConflict, "setup_required", "This Pad instance must be initialized with pad setup")
|
||||
writeError(w, http.StatusConflict, "setup_required", "This Pad instance must be initialized with pad auth setup")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+7
-8
@@ -18,19 +18,18 @@ cp pad /usr/local/bin/
|
||||
|
||||
```bash
|
||||
cd ~/projects/myapp
|
||||
pad init "My App"
|
||||
pad workspace init "My App"
|
||||
```
|
||||
|
||||
`pad init` will detect that the `/pad` skill isn't installed and offer to install it to your project or globally. You can also install manually:
|
||||
`pad workspace init` will detect that the `/pad` skill isn't installed and offer to install it for detected tools. You can also install manually:
|
||||
|
||||
```bash
|
||||
pad skills install # Install to .claude/skills/ in current project
|
||||
pad skills install --global # Install to ~/.claude/skills/ for all projects
|
||||
pad skills status # Check if installed and up to date
|
||||
pad skills update # Update to version bundled in binary
|
||||
pad agent install claude # Install for Claude Code
|
||||
pad agent status # Check installed integrations
|
||||
pad agent update # Update the version bundled in the binary
|
||||
```
|
||||
|
||||
When you update the `pad` binary, run `pad skills status` to check if your installed skill is outdated. If it is, run `pad skills update` to sync it.
|
||||
When you update the `pad` binary, run `pad agent status` to check if your installed integrations are outdated. If they are, run `pad agent update` to sync them.
|
||||
|
||||
### 3. Use it
|
||||
|
||||
@@ -60,6 +59,6 @@ The `/pad` skill is a natural-language interface — there are no rigid commands
|
||||
## Web UI
|
||||
|
||||
```bash
|
||||
pad open
|
||||
pad server open
|
||||
# or visit http://localhost:7777
|
||||
```
|
||||
|
||||
+75
-75
@@ -24,9 +24,9 @@ There is **one command**: `/pad <anything>`. You interpret the user's intent and
|
||||
On every `/pad` invocation, start by loading workspace context:
|
||||
|
||||
```bash
|
||||
pad status --format json # Project overview: collections, phases, attention, suggestions
|
||||
pad collections --format json # Available collections with schemas
|
||||
pad list conventions --field status=active --field trigger=always --format json # Always-on project conventions
|
||||
pad project dashboard --format json # Project overview: collections, phases, attention, suggestions
|
||||
pad collection list --format json # Available collections with schemas
|
||||
pad item list conventions --field status=active --field trigger=always --format json # Always-on project conventions
|
||||
```
|
||||
|
||||
This tells you: what collections exist, what items are in them, what's active, what needs attention, and what project conventions to always follow.
|
||||
@@ -36,7 +36,7 @@ If the conventions list includes items, treat them as project rules you must fol
|
||||
## Parse $ARGUMENTS
|
||||
|
||||
### No arguments
|
||||
Show project status conversationally. Run `pad status --format json`, and present the dashboard in a friendly, readable way — highlight what's active, what needs attention, and suggest what to work on next.
|
||||
Show project status conversationally. Run `pad project dashboard --format json`, and present the dashboard in a friendly, readable way — highlight what's active, what needs attention, and suggest what to work on next.
|
||||
|
||||
### Natural Language Routing
|
||||
|
||||
@@ -49,15 +49,15 @@ Interpret the user's intent and route to the appropriate action. Here are common
|
||||
- "document the auth architecture" → Create a Doc item
|
||||
|
||||
**Querying:**
|
||||
- "what's on my plate?" / "what should I work on?" → `pad next --format json`
|
||||
- "how far along are we?" / "show me status" → `pad status --format json`
|
||||
- "show me all tasks" / "list bugs" → `pad list <collection> --format json`
|
||||
- "find anything about OAuth" → `pad search "OAuth" --format json`
|
||||
- "what's on my plate?" / "what should I work on?" → `pad project next --format json`
|
||||
- "how far along are we?" / "show me status" → `pad project dashboard --format json`
|
||||
- "show me all tasks" / "list bugs" → `pad item list <collection> --format json`
|
||||
- "find anything about OAuth" → `pad item search "OAuth" --format json`
|
||||
|
||||
**Updating:**
|
||||
- "I finished the OAuth fix" / "mark TASK-5 as done" → `pad update TASK-5 --status done`
|
||||
- "I'm starting on TASK-3" → `pad update TASK-3 --status in-progress`
|
||||
- "deprioritize IDEA-7" → `pad update IDEA-7 --priority low`
|
||||
- "I finished the OAuth fix" / "mark TASK-5 as done" → `pad item update TASK-5 --status done`
|
||||
- "I'm starting on TASK-3" → `pad item update TASK-3 --status in-progress`
|
||||
- "deprioritize IDEA-7" → `pad item update IDEA-7 --priority low`
|
||||
|
||||
**Planning:**
|
||||
- "let's plan the next phase" → Multi-step planning workflow (see below)
|
||||
@@ -69,16 +69,16 @@ Interpret the user's intent and route to the appropriate action. Here are common
|
||||
- "what if we added X?" → Discuss, then offer to capture as an Idea
|
||||
|
||||
**Dependencies:**
|
||||
- "what's blocking TASK-5?" / "show deps for TASK-5" → `pad deps TASK-5 --format json`
|
||||
- "TASK-5 blocks TASK-8" → `pad blocks TASK-5 TASK-8`
|
||||
- "TASK-5 depends on TASK-3" → `pad blocked-by TASK-5 TASK-3`
|
||||
- "remove the dependency" → `pad unblock TASK-5 TASK-8`
|
||||
- "what's blocking TASK-5?" / "show deps for TASK-5" → `pad item deps TASK-5 --format json`
|
||||
- "TASK-5 blocks TASK-8" → `pad item block TASK-5 TASK-8`
|
||||
- "TASK-5 depends on TASK-3" → `pad item blocked-by TASK-5 TASK-3`
|
||||
- "remove the dependency" → `pad item unblock TASK-5 TASK-8`
|
||||
|
||||
**Reports:**
|
||||
- "prep for standup" / "what did we do?" → `pad standup --format json`
|
||||
- "generate changelog" / "what shipped?" → `pad changelog --format json`
|
||||
- "changelog for this phase" → `pad changelog --phase PHASE-2 --format json`
|
||||
- "changelog since Monday" → `pad changelog --since 2026-03-24 --format json`
|
||||
- "prep for standup" / "what did we do?" → `pad project standup --format json`
|
||||
- "generate changelog" / "what shipped?" → `pad project changelog --format json`
|
||||
- "changelog for this phase" → `pad project changelog --phase PHASE-2 --format json`
|
||||
- "changelog since Monday" → `pad project changelog --since 2026-03-24 --format json`
|
||||
|
||||
**Retrospective:**
|
||||
- "phase 2 is done, let's retro" → Review completed work, save retrospective
|
||||
@@ -93,20 +93,20 @@ When you are about to take action (implement code, complete a task, create a PR,
|
||||
|
||||
```bash
|
||||
# Before implementing code:
|
||||
pad list conventions --field trigger=on-implement --field status=active --format json
|
||||
pad list playbooks --field trigger=on-implement --field status=active --format json
|
||||
pad item list conventions --field trigger=on-implement --field status=active --format json
|
||||
pad item list playbooks --field trigger=on-implement --field status=active --format json
|
||||
|
||||
# Before completing a task:
|
||||
pad list conventions --field trigger=on-task-complete --field status=active --format json
|
||||
pad item list conventions --field trigger=on-task-complete --field status=active --format json
|
||||
|
||||
# Before creating a PR:
|
||||
pad list conventions --field trigger=on-pr-create --field status=active --format json
|
||||
pad item list conventions --field trigger=on-pr-create --field status=active --format json
|
||||
|
||||
# Before committing:
|
||||
pad list conventions --field trigger=on-commit --field status=active --format json
|
||||
pad item list conventions --field trigger=on-commit --field status=active --format json
|
||||
|
||||
# Before planning:
|
||||
pad list conventions --field trigger=on-plan --field status=active --format json
|
||||
pad item list conventions --field trigger=on-plan --field status=active --format json
|
||||
```
|
||||
|
||||
Follow ALL returned conventions. If a playbook exists for the action, follow its steps in order. Conventions are project-specific rules the team has established — they override your defaults.
|
||||
@@ -119,58 +119,58 @@ Follow ALL returned conventions. If a playbook exists for the action, follow its
|
||||
```bash
|
||||
# Create items (collection accepts singular or plural: task/tasks, idea/ideas, etc.)
|
||||
# The CLI prints the new item's issue ID (e.g. "Created TASK-5: ...") — use it for subsequent commands
|
||||
pad create <collection> "title" [--status X] [--priority X] [--assignee X] [--category X] [--content "..."] [--stdin]
|
||||
pad create task "Fix OAuth redirect" --priority high
|
||||
pad create idea "Real-time collaboration" --category infrastructure
|
||||
pad create phase "API Redesign" --status active
|
||||
pad create doc "Auth Architecture" --category architecture --stdin <<< "# Auth Architecture\n\n..."
|
||||
pad item create <collection> "title" [--status X] [--priority X] [--assignee X] [--category X] [--content "..."] [--stdin]
|
||||
pad item create task "Fix OAuth redirect" --priority high
|
||||
pad item create idea "Real-time collaboration" --category infrastructure
|
||||
pad item create phase "API Redesign" --status active
|
||||
pad item create doc "Auth Architecture" --category architecture --stdin <<< "# Auth Architecture\n\n..."
|
||||
|
||||
# Custom fields via --field flag (works for any collection's fields)
|
||||
pad create convention "Run tests" --field trigger=on-task-complete --field scope=all --field priority=must
|
||||
pad create roadmap "Feature X" --field quarter=2026-Q3
|
||||
pad item create convention "Run tests" --field trigger=on-task-complete --field scope=all --field priority=must
|
||||
pad item create roadmap "Feature X" --field quarter=2026-Q3
|
||||
|
||||
# List items (defaults to non-done items)
|
||||
pad list [collection] [--status X] [--priority X] [--all] [--field key=value] [--format json]
|
||||
pad list tasks # open + in_progress tasks
|
||||
pad list tasks --status done # completed tasks
|
||||
pad list conventions --field trigger=always --field status=active # filtered by custom fields
|
||||
pad list --all # everything across all collections
|
||||
pad item list [collection] [--status X] [--priority X] [--all] [--field key=value] [--format json]
|
||||
pad item list tasks # open + in_progress tasks
|
||||
pad item list tasks --status done # completed tasks
|
||||
pad item list conventions --field trigger=always --field status=active # filtered by custom fields
|
||||
pad item list --all # everything across all collections
|
||||
|
||||
# Show item detail — use the issue ID (e.g. TASK-5, BUG-8)
|
||||
pad show TASK-5 [--format json|markdown]
|
||||
pad item show TASK-5 [--format json|markdown]
|
||||
|
||||
# Update items — use the issue ID
|
||||
pad update TASK-5 --status done
|
||||
pad update IDEA-3 --priority high --assignee dave
|
||||
pad update DOC-1 --stdin < updated-doc.md
|
||||
pad item update TASK-5 --status done
|
||||
pad item update IDEA-3 --priority high --assignee dave
|
||||
pad item update DOC-1 --stdin < updated-doc.md
|
||||
|
||||
# Delete (archive) — use the issue ID
|
||||
pad delete TASK-5
|
||||
pad item delete TASK-5
|
||||
|
||||
# Search
|
||||
pad search "query" [--format json]
|
||||
pad item search "query" [--format json]
|
||||
```
|
||||
|
||||
### Intelligence
|
||||
```bash
|
||||
pad status [--format json] # Project dashboard
|
||||
pad next [--format json] # Recommended next task
|
||||
pad standup [--days N] [--format json] # Daily standup report (completed/in-progress/blockers)
|
||||
pad changelog [--days N] [--since DATE] [--phase PHASE-2] [--format json|markdown] # Release notes
|
||||
pad project dashboard [--format json] # Project dashboard
|
||||
pad project next [--format json] # Recommended next task
|
||||
pad project standup [--days N] [--format json] # Daily standup report (completed/in-progress/blockers)
|
||||
pad project changelog [--days N] [--since DATE] [--phase PHASE-2] [--format json|markdown] # Release notes
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
```bash
|
||||
pad blocks TASK-5 TASK-8 # "TASK-5 blocks TASK-8"
|
||||
pad blocked-by TASK-5 TASK-3 # "TASK-5 is blocked by TASK-3"
|
||||
pad deps TASK-5 # Show all dependencies for an item
|
||||
pad unblock TASK-5 TASK-8 # Remove a dependency
|
||||
pad item block TASK-5 TASK-8 # "TASK-5 blocks TASK-8"
|
||||
pad item blocked-by TASK-5 TASK-3 # "TASK-5 is blocked by TASK-3"
|
||||
pad item deps TASK-5 # Show all dependencies for an item
|
||||
pad item unblock TASK-5 TASK-8 # Remove a dependency
|
||||
```
|
||||
|
||||
### Collections
|
||||
```bash
|
||||
pad collections [--format json] # List collections with counts
|
||||
pad collections create "Name" --fields "key:type[:options]; ..." [--icon "X"]
|
||||
pad collection list [--format json] # List collections with counts
|
||||
pad collection create "Name" --fields "key:type[:options]; ..." [--icon "X"]
|
||||
```
|
||||
|
||||
### Webhooks
|
||||
@@ -189,38 +189,38 @@ All commands support `--format json` (for parsing) or `--format table` (default,
|
||||
|
||||
### Ideation: "Let's brainstorm about X"
|
||||
|
||||
1. **Load context:** Run `pad status --format json` and `pad list --format json --limit 20`
|
||||
2. **Search for related items:** `pad search "X" --format json`
|
||||
1. **Load context:** Run `pad project dashboard --format json` and `pad item list --format json --limit 20`
|
||||
2. **Search for related items:** `pad item search "X" --format json`
|
||||
3. **Discuss systematically:** Ask clarifying questions, explore trade-offs, reference existing items with [[Title]] links
|
||||
4. **Offer to save:** At natural checkpoints, offer to create items:
|
||||
- "Want me to save this as an Idea?" → `pad create idea "X" --content "..." --stdin`
|
||||
- "Should I create a Doc for this architecture decision?" → `pad create doc "X" --category decision --stdin`
|
||||
- "Want me to save this as an Idea?" → `pad item create idea "X" --content "..." --stdin`
|
||||
- "Should I create a Doc for this architecture decision?" → `pad item create doc "X" --category decision --stdin`
|
||||
5. **Never save without asking.** Always show what you'll create and get confirmation.
|
||||
|
||||
### Planning: "Let's plan the next phase"
|
||||
|
||||
1. **Load context:** `pad status --format json`, `pad list phases --all --format json`
|
||||
1. **Load context:** `pad project dashboard --format json`, `pad item list phases --all --format json`
|
||||
2. **Understand current state:** What phases exist? What's active? What's completed?
|
||||
3. **Propose outline:** Present phase title + 1-line summary. Ask for feedback.
|
||||
4. **Create the phase:** `pad create phase "Phase N: Title" --status draft --stdin <<< "<plan content>"`
|
||||
4. **Create the phase:** `pad item create phase "Phase N: Title" --status draft --stdin <<< "<plan content>"`
|
||||
5. **Decompose into tasks:** For each task in the plan, create a Task item:
|
||||
```bash
|
||||
pad create task "Task description" --phase PHASE-3 --priority medium
|
||||
pad item create task "Task description" --phase PHASE-3 --priority medium
|
||||
```
|
||||
6. **Each task should be PR-sized** — small enough for one branch, large enough to be meaningful.
|
||||
7. **Ask before creating each item.** Don't bulk-create without approval.
|
||||
|
||||
### Decomposition: "Break phase X into tasks"
|
||||
|
||||
1. **Load the phase:** `pad show PHASE-2 --format markdown`
|
||||
1. **Load the phase:** `pad item show PHASE-2 --format markdown`
|
||||
2. **Analyze the content** for actionable work items
|
||||
3. **Propose task list** with titles and priorities
|
||||
4. **Create approved tasks:** One `pad create task` per approved item
|
||||
4. **Create approved tasks:** One `pad item create task` per approved item
|
||||
5. **Link tasks to phase** using `--phase PHASE-2` flag (if the phase collection has a relation field)
|
||||
|
||||
### Status Check: "How are we doing?"
|
||||
|
||||
1. Run `pad status --format json`
|
||||
1. Run `pad project dashboard --format json`
|
||||
2. Present conversationally:
|
||||
- Collection summaries (Tasks: 5 open, 2 in progress, 12 done)
|
||||
- Active phase progress with bars
|
||||
@@ -230,14 +230,14 @@ All commands support `--format json` (for parsing) or `--format table` (default,
|
||||
|
||||
### Daily Standup: "Prep for standup"
|
||||
|
||||
1. Run `pad list tasks --status done --format json` (recently completed)
|
||||
2. Run `pad list tasks --status in-progress --format json` (current work)
|
||||
3. Run `pad status --format json` for blockers/attention items
|
||||
1. Run `pad item list tasks --status done --format json` (recently completed)
|
||||
2. Run `pad item list tasks --status in-progress --format json` (current work)
|
||||
3. Run `pad project dashboard --format json` for blockers/attention items
|
||||
4. Present as: Yesterday / Today / Blockers format
|
||||
|
||||
### Onboarding: "Scan this codebase" / "Set up my workspace"
|
||||
|
||||
1. **Check workspace state:** `pad status --format json` — if the workspace already has items, ask if they want to add more or start fresh sections.
|
||||
1. **Check workspace state:** `pad project dashboard --format json` — if the workspace already has items, ask if they want to add more or start fresh sections.
|
||||
2. **Analyze the codebase:** Read key project files to understand the project:
|
||||
- `README.md` or `README` — project overview, setup instructions
|
||||
- `CLAUDE.md` — existing AI/agent instructions
|
||||
@@ -256,15 +256,15 @@ All commands support `--format json` (for parsing) or `--format table` (default,
|
||||
|
||||
### Retrospective: "Phase X is done, let's retro"
|
||||
|
||||
1. Load the phase: `pad show PHASE-2 --format markdown`
|
||||
2. Load tasks: `pad list tasks --all --format json` (filter to phase)
|
||||
1. Load the phase: `pad item show PHASE-2 --format markdown`
|
||||
2. Load tasks: `pad item list tasks --all --format json` (filter to phase)
|
||||
3. Generate retro: What shipped, what was deferred, lessons learned
|
||||
4. Offer to save: `pad create doc "Phase N Retrospective" --category retro --stdin`
|
||||
5. Offer to update phase status: `pad update PHASE-2 --status completed`
|
||||
4. Offer to save: `pad item create doc "Phase N Retrospective" --category retro --stdin`
|
||||
5. Offer to update phase status: `pad item update PHASE-2 --status completed`
|
||||
|
||||
## Key Principles
|
||||
|
||||
1. **Use issue IDs, not slugs.** Every item has an ID like `TASK-5` or `BUG-8`. Use these in all commands: `pad show TASK-5`, `pad update BUG-8 --status done`. The CLI prints issue IDs in all output — look for them.
|
||||
1. **Use issue IDs, not slugs.** Every item has an ID like `TASK-5` or `BUG-8`. Use these in all commands: `pad item show TASK-5`, `pad item update BUG-8 --status done`. The CLI prints issue IDs in all output — look for them.
|
||||
2. **Discuss before acting.** Always show what you plan to create/modify and get confirmation.
|
||||
3. **Use the CLI.** Every action goes through `pad` commands — don't try to modify the database directly.
|
||||
4. **Be conversational.** You're not a command executor. You're a project partner.
|
||||
@@ -272,11 +272,11 @@ All commands support `--format json` (for parsing) or `--format table` (default,
|
||||
6. **Keep it practical.** Tasks should be PR-sized. Ideas should be actionable. Docs should be concise.
|
||||
7. **Attribution matters.** Items you create will have `created_by: agent` and `source: cli` automatically.
|
||||
8. **Follow project conventions.** Always load and follow active conventions before performing work. They are project-specific rules that override your defaults.
|
||||
9. **Learn and teach.** When the user corrects your behavior or teaches you a project-specific rule, offer to save it as a convention: "Should I save this as a project convention so future agents follow it too?" Use `pad create convention "Title" --field trigger=<inferred> --field scope=<inferred> --field priority=should --stdin` with an appropriate trigger inferred from the context.
|
||||
9. **Learn and teach.** When the user corrects your behavior or teaches you a project-specific rule, offer to save it as a convention: "Should I save this as a project convention so future agents follow it too?" Use `pad item create convention "Title" --field trigger=<inferred> --field scope=<inferred> --field priority=should --stdin` with an appropriate trigger inferred from the context.
|
||||
|
||||
## Anything Else
|
||||
|
||||
If the user's intent doesn't match any pattern above, respond helpfully. You can always:
|
||||
- Run `pad list` or `pad search` to find relevant items
|
||||
- Run `pad show TASK-5` to load any item's detail (use the issue ID from list output)
|
||||
- Run `pad item list` or `pad item search` to find relevant items
|
||||
- Run `pad item show TASK-5` to load any item's detail (use the issue ID from list output)
|
||||
- Suggest the appropriate workflow based on what they're trying to do
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
|
||||
<div class="onboarding-footer">
|
||||
<p class="footer-instructions">
|
||||
Install the Pad skill in your project with <code>pad init</code>, then paste a prompt above into Claude Code or your favorite AI agent.
|
||||
Install the Pad skill in your project with <code>pad agent install</code>, then paste a prompt above into Claude Code or your favorite AI agent.
|
||||
</p>
|
||||
<a href="/{wsSlug}/library" class="footer-link">Or browse the library for conventions and playbooks</a>
|
||||
</div>
|
||||
|
||||
@@ -25,16 +25,16 @@
|
||||
<div class="instructions">
|
||||
<div class="instruction">
|
||||
<p class="instruction-label">Local server</p>
|
||||
<code>pad setup</code>
|
||||
<code>pad auth setup</code>
|
||||
</div>
|
||||
|
||||
<div class="instruction">
|
||||
<p class="instruction-label">Docker</p>
|
||||
<code>docker exec -it <container> pad setup</code>
|
||||
<code>docker exec -it <container> pad auth setup</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="hint">If this Pad server runs on another machine, run <code>pad setup</code> there instead.</p>
|
||||
<p class="hint">If this Pad server runs on another machine, run <code>pad auth setup</code> there instead.</p>
|
||||
{/if}
|
||||
|
||||
{#if nextStep}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
{:else if workspaceStore.workspaces.length === 0}
|
||||
<h1>Welcome to Pad</h1>
|
||||
<p>Create a workspace to get started.</p>
|
||||
<p class="hint">Run <code>pad init</code> in your project directory, or use the workspace switcher in the sidebar.</p>
|
||||
<p class="hint">Run <code>pad workspace init</code> in your project directory, or use the workspace switcher in the sidebar.</p>
|
||||
{:else}
|
||||
<p>Redirecting...</p>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user