diff --git a/CLAUDE.md b/CLAUDE.md index 6162ac0f..85627949 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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 # 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 # 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 `` Slugs also work but issue IDs are preferred. ```bash -pad create "title" [--status X] [--priority X] -pad list [collection] [--status X] [--all] -pad show # e.g. pad show TASK-5 -pad update [--status X] [--priority X] -pad delete -pad move -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 # e.g. pad blocks TASK-5 TASK-8 -pad blocked-by -pad deps # Show dependencies -pad unblock -pad collections # List collections -pad collections create "Name" --fields "key:type[:opts]; ..." -pad edit # 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 "title" [--status X] [--priority X] +pad item list [collection] [--status X] [--all] +pad item show # e.g. pad item show TASK-5 +pad item update [--status X] [--priority X] +pad item delete +pad item move +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 # e.g. pad item block TASK-5 TASK-8 +pad item blocked-by +pad item deps # Show dependencies +pad item unblock +pad collection list # List collections +pad collection create "Name" --fields "key:type[:opts]; ..." +pad item edit # 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 # 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 [--role X] # Invite user to workspace -pad join # 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 [--role X] # Invite user to workspace +pad workspace join # 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 diff --git a/Makefile b/Makefile index 9bd90ab6..fcec4c01 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/README.md b/README.md index 403419de..4867e858 100644 --- a/README.md +++ b/README.md @@ -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 "title" Create item (task, idea, phase, doc, ...) -pad list [collection] List items (filters: --status, --priority, --all) -pad show Show item detail -pad update Update item fields -pad delete Delete item -pad move Move item between collections -pad edit 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 Show direct relationships for an item -pad implemented-by Show incoming implementers for an item -pad collections List collections with item counts -pad comment "text" Add comment to an item -pad comments View item comments -pad note "summary" Append an implementation note to an item -pad decide "decision" Append a decision log entry to an item +pad workspace init [name] Initialize workspace in current directory +pad workspace link Link current directory to an existing workspace +pad workspace list List all workspaces +pad workspace switch Switch active workspace +pad workspace onboard Analyze project and suggest conventions +pad workspace members List workspace members +pad workspace invite Invite a workspace member +pad workspace join Accept an invitation +pad workspace export Export workspace data +pad workspace import 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 Create dependency -pad blocked-by Mark item as blocked -pad deps Show dependencies -pad unblock Remove dependency +pad item create "title" Create item (task, idea, phase, doc, ...) +pad item list [collection] List items (filters: --status, --priority, --all) +pad item show Show item detail +pad item update Update item fields +pad item delete Delete item +pad item move Move item between collections +pad item edit Open item in $EDITOR +pad item search "query" Full-text search across all items +pad item comment "text" Add comment to an item +pad item comments View item comments +pad item note "summary" Append an implementation note to an item +pad item decide "decision" Append a decision log entry to an item +pad item block Create dependency +pad item blocked-by Mark item as blocked +pad item deps Show dependencies +pad item unblock Remove dependency +pad item related Show direct relationships for an item +pad item implemented-by 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 Create a custom collection + +pad library list Browse convention and playbook library +pad library activate 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 diff --git a/cmd/pad/configure.go b/cmd/pad/configure.go index eabfef32..9aa053ae 100644 --- a/cmd/pad/configure.go +++ b/cmd/pad/configure.go @@ -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 diff --git a/cmd/pad/groups.go b/cmd/pad/groups.go new file mode 100644 index 00000000..82a2bf97 --- /dev/null +++ b/cmd/pad/groups.go @@ -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() + }, + } +} diff --git a/cmd/pad/lineage.go b/cmd/pad/lineage.go index c221ee8c..10b8be1e 100644 --- a/cmd/pad/lineage.go +++ b/cmd/pad/lineage.go @@ -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{ diff --git a/cmd/pad/main.go b/cmd/pad/main.go index 13070663..b59d069a 100644 --- a/cmd/pad/main.go +++ b/cmd/pad/main.go @@ -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 == "" { diff --git a/cmd/pad/query.go b/cmd/pad/query.go index 839d2817..5dc83d1a 100644 --- a/cmd/pad/query.go +++ b/cmd/pad/query.go @@ -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 { diff --git a/internal/cli/agents.go b/internal/cli/agents.go index 78c3e64f..918e76d9 100644 --- a/internal/cli/agents.go +++ b/internal/cli/agents.go @@ -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 { diff --git a/internal/cli/detect.go b/internal/cli/detect.go index d1cb5eec..c7bae5fd 100644 --- a/internal/cli/detect.go +++ b/internal/cli/detect.go @@ -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 } diff --git a/internal/cli/server.go b/internal/cli/server.go index 6ccb3d33..624b5733 100644 --- a/internal/cli/server.go +++ b/internal/cli/server.go @@ -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 diff --git a/internal/cli/workspace.go b/internal/cli/workspace.go index 85264e5e..be536f3b 100644 --- a/internal/cli/workspace.go +++ b/internal/cli/workspace.go @@ -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. diff --git a/internal/collections/convention_library.go b/internal/collections/convention_library.go index 6f1c75b1..04b58fd1 100644 --- a/internal/collections/convention_library.go +++ b/internal/collections/convention_library.go @@ -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", diff --git a/internal/server/handlers_auth.go b/internal/server/handlers_auth.go index 38f519fa..999b5a44 100644 --- a/internal/server/handlers_auth.go +++ b/internal/server/handlers_auth.go @@ -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 } diff --git a/skills/INSTALL.md b/skills/INSTALL.md index b8f8ba42..1c59938b 100644 --- a/skills/INSTALL.md +++ b/skills/INSTALL.md @@ -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 ``` diff --git a/skills/pad/SKILL.md b/skills/pad/SKILL.md index 6b8b0a6e..5d565a47 100644 --- a/skills/pad/SKILL.md +++ b/skills/pad/SKILL.md @@ -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 diff --git a/web/src/lib/components/OnboardingChecklist.svelte b/web/src/lib/components/OnboardingChecklist.svelte index 0b855334..75af8c01 100644 --- a/web/src/lib/components/OnboardingChecklist.svelte +++ b/web/src/lib/components/OnboardingChecklist.svelte @@ -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> diff --git a/web/src/lib/components/auth/SetupRequiredNotice.svelte b/web/src/lib/components/auth/SetupRequiredNotice.svelte index 6387c9d4..e26200bb 100644 --- a/web/src/lib/components/auth/SetupRequiredNotice.svelte +++ b/web/src/lib/components/auth/SetupRequiredNotice.svelte @@ -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} diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index fe8b9266..28c89931 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -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}