refactor(cli): group first-release commands for TASK-127 (#45)

This commit is contained in:
xarmian
2026-04-02 15:28:16 -04:00
committed by GitHub
parent f1e4618013
commit f5649b912e
19 changed files with 491 additions and 418 deletions
+43 -43
View File
@@ -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
+6 -6
View File
@@ -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
+94 -79
View File
@@ -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
+2 -2
View File
@@ -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
+162
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+1 -1
View File
@@ -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 {
+2 -2
View File
@@ -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
}
+1 -1
View File
@@ -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
+1 -1
View 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.
+1 -1
View File
@@ -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",
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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 &lt;container&gt; pad setup</code>
<code>docker exec -it &lt;container&gt; 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}
+1 -1
View File
@@ -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}