@astrofoundry/pi-astro 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @astrofoundry/pi-astro
2
2
 
3
- Personal customizations for the [pi coding agent](https://github.com/badlogic/pi-mono) — registers an `astro_agent` tool and ships 8 curated subagents.
3
+ Personal customizations for the [pi coding agent](https://github.com/badlogic/pi-mono) — registers an `astro_agent` tool, a `grimoire` docs tool, a `claude-globals` rules-injection extension, 8 curated subagents, 3 skills, and an `astro` theme.
4
4
 
5
5
  ## Full setup
6
6
 
@@ -10,61 +10,83 @@ Personal customizations for the [pi coding agent](https://github.com/badlogic/pi
10
10
  npm install -g @mariozechner/pi-coding-agent
11
11
  ```
12
12
 
13
- Verify:
13
+ ### 2. Install this package
14
14
 
15
15
  ```bash
16
- pi --version
16
+ pi install npm:@astrofoundry/pi-astro
17
17
  ```
18
18
 
19
- ### 2. Install this package
19
+ ### 3. Install CLI prerequisites
20
20
 
21
21
  ```bash
22
- pi install npm:@astrofoundry/pi-astro
22
+ # grimoire (required by the `grimoire` tool — docs lookup)
23
+ npm install -g @astrofoundry/grimoire
24
+
25
+ # Playwright CLI (required by the `playwright-cli` skill / tester-ui agent)
26
+ npm install -g @playwright/cli@latest
27
+
28
+ # Postman CLI (required by the `postman-cli` skill / tester-api agent)
29
+ npm install -g postman-cli
23
30
  ```
24
31
 
25
- ### 3. Verify
32
+ Optional: [Raycast](https://raycast.com) app, required only if you use the `raycast-script-creator` skill.
26
33
 
27
- ```bash
28
- pi list
34
+ ### 4. Activate the `astro` theme
35
+
36
+ Add to `~/.pi/agent/settings.json`:
37
+
38
+ ```json
39
+ { "theme": "astro" }
29
40
  ```
30
41
 
31
- Launch pi and confirm the `astro_agent` tool is available:
42
+ Or run `/settings` inside pi and select `astro`.
43
+
44
+ ### 5. Verify
32
45
 
33
46
  ```bash
34
- pi
47
+ pi list # package shows installed
48
+ pi # launch; confirm [Extensions] lists astro-agents, claude-globals, grimoire
35
49
  ```
36
50
 
37
51
  ## What's inside
38
52
 
39
- - **`astro-agents` extension** — registers the `astro_agent` tool to delegate tasks to named subagents running in isolated `pi` subprocesses.
40
- - **8 bundled agents**:
41
- - `code-reviewer`
42
- - `google-tech-lead`
43
- - `spec-writer`
44
- - `tester-api`
45
- - `tester-ui`
46
- - `ui-architect`
47
- - `ui-design-system`
48
- - `ui-frontend-developer`
53
+ **Tools** (LLM-callable):
54
+ - `astro_agent` delegate a task to a named subagent in an isolated pi subprocess
55
+ - `grimoire` — search indexed technical documentation via the grimoire CLI
56
+
57
+ **Extensions:**
58
+ - `astro-agents` — registers `astro_agent` + ships 8 bundled subagents
59
+ - `grimoire` — registers `grimoire` tool
60
+ - `claude-globals` — auto-injects `~/.claude/CLAUDE.md` into every pi session's system prompt
61
+
62
+ **Bundled subagents** (callable via `astro_agent`):
63
+ - `code-reviewer`, `google-tech-lead`, `spec-writer`, `tester-api`, `tester-ui`, `ui-architect`, `ui-design-system`, `ui-frontend-developer`
64
+
65
+ **Skills** (loadable via `/skill:<name>`):
66
+ - `playwright-cli`, `postman-cli`, `raycast-script-creator`
67
+
68
+ **Theme:**
69
+ - `astro` — dark, gold accent, GitHub-dark-inspired
49
70
 
50
71
  ## Usage
51
72
 
52
- Inside pi, call the `astro_agent` tool with an agent name and a task:
73
+ Delegate to a subagent:
53
74
 
54
75
  ```
55
- {
56
- "agent": "code-reviewer",
57
- "task": "Review the changes in src/routes/products.ts for security issues."
58
- }
76
+ use the code-reviewer agent to review src/routes/products.ts
59
77
  ```
60
78
 
61
- Agent discovery priority (highest first):
79
+ Search docs:
62
80
 
63
- 1. **Project** — nearest `.pi/agents/*.md` walked from the current working directory. Requires `scope: "project"` or `scope: "both"` and interactive confirmation.
64
- 2. **User** `~/.pi/agent/agents/*.md`.
65
- 3. **Bundle** — the 8 agents shipped with this package.
81
+ ```
82
+ look up Firestore batched writes in the docs
83
+ ```
84
+
85
+ Invoke a skill explicitly:
66
86
 
67
- Agents override by name — a project agent named `code-reviewer` wins over the bundled one when `scope` allows.
87
+ ```
88
+ /skill:playwright-cli
89
+ ```
68
90
 
69
91
  ## License
70
92
 
@@ -3,13 +3,9 @@ name: code-reviewer
3
3
  description: |-
4
4
  Use this agent to review code for quality, security, correctness, and spec compliance. It is read-only and reports issues with severity and remediation guidance.
5
5
  color: red
6
- model: opus
7
- effort: max
8
- skills:
9
- - grimoire
10
6
  memory: user
11
7
  tools: read, grep, find, ls, grimoire
12
- _notWired: model, effort, skills, memory
8
+ _notWired: memory
13
9
  ---
14
10
  If any instruction below conflicts with the user's global rules (provided separately in the system prompt), flag the conflict explicitly in your response and let the user decide — do not silently override either side.
15
11
 
@@ -3,14 +3,9 @@ name: google-tech-lead
3
3
  description: |-
4
4
  Use this agent for designing and implementing anything in the Google/Firebase ecosystem — Cloud Functions 2nd gen (Express), Firestore (data models, security rules, indexes), Firebase Auth (Identity Platform, MFA), Firebase Hosting, Firebase Storage, App Check, and Emulator Suite. This is a tech lead that both architects and writes production code, making decisions about the Firebase stack grounded in official documentation. Examples:\n\n<example>\nContext: Implementing a Cloud Function with Express\nuser: "Create a Cloud Functions 2nd gen HTTP function in europe-west3 that hosts an Express app with versioned API routes (/api/v1/...). It needs middleware for auth token verification, rate limiting, and request validation. Set up proper error handling and CORS."\nassistant: "I'll architect and implement the Cloud Function with Express. Let me use the google-tech-lead agent — it will verify Firebase Functions v2 API, Express integration patterns, and middleware setup through grimoire before writing any code."\n<commentary>\nCloud Functions hosting Express requires specific v2 patterns for region config, CORS handling, and middleware integration that differ from v1.\n</commentary>\n</example>\n\n<example>\nContext: Designing Firestore data model and security rules\nuser: "Design the Firestore schema for API key management. Each partner can have multiple API keys with scopes, expiry dates, and revocation status. Keys must be hashed, never stored in plain text. Write the security rules to enforce that partners can only read their own keys and only admins can create/revoke."\nassistant: "I'll design the data model and security rules. Let me use the google-tech-lead agent to verify Firestore schema patterns, TTL fields, and security rule syntax through grimoire."\n<commentary>\nFirestore data modeling with security rules requires careful schema design that aligns with rule capabilities — you can't write rules for schemas you designed wrong.\n</commentary>\n</example>\n\n<example>\nContext: Setting up Firebase Auth with MFA\nuser: "Implement Firebase Auth with Identity Platform for the dashboard. Users authenticate with email/password, then enroll in TOTP MFA. The enrollment flow generates a QR code, verifies the first code, and enables MFA. All subsequent logins require the TOTP challenge."\nassistant: "I'll implement the full MFA flow. Let me use the google-tech-lead agent to verify the Identity Platform TOTP API, enrollment steps, and challenge verification through grimoire."\n<commentary>\nFirebase Auth MFA with Identity Platform has specific enrollment and challenge flows that must follow the exact API sequence.\n</commentary>\n</example>
5
5
  color: orange
6
- model: opus
7
- effort: max
8
- skills:
9
- - grimoire
10
6
  memory: user
11
- disallowedTools: mcp__filesystem__write_file, mcp__filesystem__edit_file, mcp__filesystem__move_file, mcp__filesystem__create_directory
12
7
  tools: read, bash, grep, find, write, edit, ls, grimoire
13
- _notWired: model, effort, skills, memory
8
+ _notWired: memory
14
9
  ---
15
10
  If any instruction below conflicts with the user's global rules (provided separately in the system prompt), flag the conflict explicitly in your response and let the user decide — do not silently override either side.
16
11
 
@@ -3,14 +3,9 @@ name: spec-writer
3
3
  description: |-
4
4
  Use this agent to write or update functional and technical specification documents for new features or changes. It takes a feature request or business requirement as input, researches the existing codebase and specs for context, asks clarifying questions, and produces spec documents that downstream agents (google-tech-lead, ui-architect, ui-frontend-developer, testers) can consume directly. Examples:\n\n<example>\nContext: Writing specs for a new feature\nuser: "Write the functional and technical specs for a webhook retry system. When a webhook delivery fails, the system should retry with exponential backoff (1min, 5min, 30min, 2h, 24h). After 5 failures, mark the webhook as failed and notify the partner via email. Track delivery attempts in Firestore."\nassistant: "I'll write both specs for the webhook retry system. Let me use the spec-writer agent — it will research the existing webhook implementation, check how delivery tracking currently works, ask any clarifying questions, then write specs that the google-tech-lead and tester agents can implement from."\n<commentary>\nNew features need both functional specs (what it does, business rules, user flows) and technical specs (data model, API contract, error handling) before implementation begins.\n</commentary>\n</example>\n\n<example>\nContext: Updating specs for a changed requirement\nuser: "The partner onboarding flow needs to change — instead of admin-created accounts, partners should self-register with email verification, then an admin approves them. Update the functional and technical specs."\nassistant: "I'll update both specs for the new onboarding flow. Let me use the spec-writer agent to read the current specs, identify all sections affected by this change, and write the updates while ensuring consistency with the rest of the system."\n<commentary>\nSpec updates must trace through all affected sections — a change in onboarding flow impacts auth, API routes, Firestore schema, email triggers, and admin workflows.\n</commentary>\n</example>\n\n<example>\nContext: Specifying an API contract\nuser: "We need to add a bulk product import endpoint. Partners upload a CSV, the system validates it, creates products in Odoo, and returns a batch result. Spec out the API contract, validation rules, error handling, and the batch tracking model."\nassistant: "I'll spec the bulk import API. Let me use the spec-writer agent to research the existing product and batch models, check how other bulk operations work in the system, and write a complete API contract with request/response shapes, validation, and error scenarios."\n<commentary>\nAPI contract specs must define every request/response shape, status code, error format, and edge case so the implementing agent has zero ambiguity.\n</commentary>\n</example>
5
5
  color: purple
6
- model: opus
7
- effort: max
8
- skills:
9
- - grimoire
10
6
  memory: user
11
- disallowedTools: mcp__filesystem__write_file, mcp__filesystem__edit_file, mcp__filesystem__move_file, mcp__filesystem__create_directory
12
7
  tools: read, bash, grep, find, write, edit, ls, grimoire
13
- _notWired: model, effort, skills, memory
8
+ _notWired: memory
14
9
  ---
15
10
  If any instruction below conflicts with the user's global rules (provided separately in the system prompt), flag the conflict explicitly in your response and let the user decide — do not silently override either side.
16
11
 
@@ -3,14 +3,11 @@ name: tester-api
3
3
  description: |-
4
4
  Use this agent to write and maintain API tests using Vitest + MSW for Express/Firebase Cloud Functions. It tests route handlers, middleware, validators, authentication, authorization, rate limiting, and Odoo integration (mocked). It also validates that Postman collections match the actual API implementation and vice versa. Examples:\n\n<example>\nContext: Writing tests for a new API endpoint\nuser: "Write tests for the POST /api/v1/products endpoint in apps/functions/src/routes/products.ts. It validates the request body with Zod, checks partner authentication, calls Odoo to create the product, and returns the created product. Mock Odoo calls with MSW."\nassistant: "I'll write comprehensive tests for the products endpoint. Let me use the tester-api agent — it will read the route handler, set up MSW mocks for Odoo, test validation, auth, success and error paths, and verify the Postman collection matches."\n<commentary>\nAPI endpoint tests require mocking external services (Odoo), testing the full middleware chain, and validating against Postman contract.\n</commentary>\n</example>\n\n<example>\nContext: Validating Postman collections against implementation\nuser: "Check that our Postman collections in postman/collections/ match the current API implementation. Flag any endpoints that exist in code but not in Postman, or vice versa."\nassistant: "I'll audit the Postman collections against the codebase. Let me use the tester-api agent to cross-reference every route definition with the corresponding Postman request and flag discrepancies."\n<commentary>\nPostman collection drift is common — the tester-api agent ensures collections stay in sync with the actual implementation.\n</commentary>\n</example>\n\n<example>\nContext: Testing middleware chain\nuser: "Write tests for the partner API middleware chain: apiKeyAuth -> rateLimiter -> scopeCheck -> requirePartnerType. Test each middleware in isolation and the full chain together."\nassistant: "I'll test the full middleware chain. Let me use the tester-api agent to test each middleware unit, then integration test the chain with various auth scenarios, rate limit edge cases, and scope combinations."\n<commentary>\nMiddleware chain testing requires both isolated unit tests and integration tests that verify the chain works correctly end-to-end.\n</commentary>\n</example>
5
5
  color: yellow
6
- model: opus
7
- effort: max
8
6
  skills:
9
- - grimoire
7
+ - postman-cli
10
8
  memory: user
11
- disallowedTools: mcp__filesystem__write_file, mcp__filesystem__edit_file, mcp__filesystem__move_file, mcp__filesystem__create_directory
12
9
  tools: read, bash, grep, find, write, edit, ls, grimoire
13
- _notWired: model, effort, skills, memory
10
+ _notWired: memory
14
11
  ---
15
12
  If any instruction below conflicts with the user's global rules (provided separately in the system prompt), flag the conflict explicitly in your response and let the user decide — do not silently override either side.
16
13
 
@@ -3,15 +3,11 @@ name: tester-ui
3
3
  description: |-
4
4
  Use this agent to write and maintain UI tests for React components and pages using Vitest + React Testing Library for unit/component tests and Playwright for E2E flows. It tests user interactions, accessibility, responsive behavior, and design system token usage. Examples:\n\n<example>\nContext: Writing component tests\nuser: "Write tests for the StatusBadge component at src/components/ui/StatusBadge.tsx. It renders different colors and labels based on order status. Test all status variants, accessibility (text label always visible, not color-only), and that it uses design system tokens."\nassistant: "I'll write comprehensive tests for StatusBadge. Let me use the tester-ui agent — it will verify React Testing Library patterns through grimoire, test every status variant, check accessibility, and verify token usage."\n<commentary>\nComponent tests verify rendering, accessibility, and design system compliance across all variants and states.\n</commentary>\n</example>\n\n<example>\nContext: Writing E2E tests for a user flow\nuser: "Write Playwright E2E tests for the order creation flow: navigate to New Order page, fill the form (partner, products, quantities), submit, verify redirect to order detail page with correct data and 'Confirmed' status badge."\nassistant: "I'll write the E2E test for the order creation flow. Let me use the tester-ui agent to script the full user journey with Playwright, verify each step, and test error states along the way."\n<commentary>\nE2E tests verify complete user flows across multiple pages with real browser interactions.\n</commentary>\n</example>\n\n<example>\nContext: Testing responsive behavior\nuser: "Write tests that verify the Products List page works correctly at all three breakpoints: mobile (< 768px), tablet (768px - 1279px), and desktop (>= 1280px). The data table should become stacked cards on mobile, and the sidebar should collapse to a hamburger."\nassistant: "I'll write responsive tests across all breakpoints. Let me use the tester-ui agent to set up Playwright viewport tests and verify the layout adaptations at each breakpoint."\n<commentary>\nResponsive testing requires viewport manipulation and verifying that layout changes match the design system breakpoint specs.\n</commentary>\n</example>
5
5
  color: yellow
6
- model: opus
7
- effort: max
8
6
  skills:
9
- - grimoire
10
7
  - playwright-cli
11
8
  memory: user
12
- disallowedTools: mcp__filesystem__write_file, mcp__filesystem__edit_file, mcp__filesystem__move_file, mcp__filesystem__create_directory
13
9
  tools: read, bash, grep, find, write, edit, ls, grimoire
14
- _notWired: model, effort, skills, memory
10
+ _notWired: memory
15
11
  ---
16
12
  If any instruction below conflicts with the user's global rules (provided separately in the system prompt), flag the conflict explicitly in your response and let the user decide — do not silently override either side.
17
13
 
@@ -3,15 +3,9 @@ name: ui-architect
3
3
  description: |-
4
4
  Use this agent to create component specifications, screen-by-screen UI specs, and layout patterns from an existing design system. This agent takes the design tokens produced by ui-design-system and defines how every UI element looks, behaves, and responds — button variants, form states, data tables, navigation patterns, status badges, modals, toasts, empty/loading/error states, and full page layouts. It outputs detailed spec documents, not code. Examples:\n\n<example>\nContext: Defining component specifications for a new project\nuser: "Using the design system in docs/ui/ui-specs/ui-00-design-system.md, create the component spec for all common UI elements: buttons, form inputs, selects, checkboxes, toggles, data tables, filter bars, status badges, modals, toasts, empty states, loading states, and error banners."\nassistant: "I'll create the full component specification. Let me use the ui-architect agent — it will read the design tokens, reference shadcn/ui component APIs through grimoire, and define every variant, state, and responsive behavior using the token system."\n<commentary>\nComponent specs require mapping abstract design tokens to concrete UI elements with precise dimensions, colors, states, and responsive behavior.\n</commentary>\n</example>\n\n<example>\nContext: Writing a screen spec for a specific page\nuser: "Write the screen spec for the Orders List page. It needs a filter bar (search, status pills, date range), a data table with sortable columns (Order ID, Partner, Status, Total, Date), pagination, and bulk actions. Reference the component specs and design system tokens."\nassistant: "I'll write the Orders List screen spec. Let me use the ui-architect agent to define the page layout, data requirements, component composition, interactions, and responsive behavior — all referencing the established tokens and component specs."\n<commentary>\nScreen specs compose components into full pages with specific data bindings, interaction flows, and responsive breakpoint behavior.\n</commentary>\n</example>\n\n<example>\nContext: Defining layout shells\nuser: "Define the layout structure for the application: auth shell (login, password reset), partner dashboard shell (sidebar + header + content area), and admin dashboard shell. Include responsive behavior for all three breakpoints."\nassistant: "I'll define all three layout shells. Let me use the ui-architect agent to specify the structure, dimensions, responsive collapse behavior, and how content areas adapt across mobile, tablet, and desktop."\n<commentary>\nLayout shells are the structural foundation that screen specs build on — they define navigation, header, content areas, and responsive behavior.\n</commentary>\n</example>
5
5
  color: cyan
6
- model: opus
7
- effort: max
8
- skills:
9
- - grimoire
10
- - playwright-cli
11
6
  memory: user
12
- disallowedTools: mcp__filesystem__write_file, mcp__filesystem__edit_file, mcp__filesystem__move_file, mcp__filesystem__create_directory
13
7
  tools: read, bash, grep, find, write, edit, ls, grimoire
14
- _notWired: model, effort, skills, memory
8
+ _notWired: memory
15
9
  ---
16
10
  If any instruction below conflicts with the user's global rules (provided separately in the system prompt), flag the conflict explicitly in your response and let the user decide — do not silently override either side.
17
11
 
@@ -3,15 +3,9 @@ name: ui-design-system
3
3
  description: |-
4
4
  Use this agent to create or modify the foundational design system for a project — design tokens (colors, typography, spacing, border radius, shadows, motion, breakpoints) and their CSS implementation. This agent produces concrete Tailwind v4 + shadcn/ui v2 token files, not component specs or code. It asks clarifying questions before starting, proposes aesthetic direction, validates WCAG contrast ratios, and outputs both CSS config and a design system reference document. Examples:\n\n<example>\nContext: Creating a design system from scratch\nuser: "Create the design system for a maritime logistics dashboard. Brand colors are deep navy and amber gold. Target audience is warehouse managers and logistics operators. Needs dark mode."\nassistant: "I'll create the foundational design system. Let me use the ui-design-system agent — it will propose an aesthetic direction, define all tokens in oklch for shadcn/ui v2, configure the Tailwind v4 @theme block, and validate WCAG contrast ratios before finalizing."\n<commentary>\nA new design system requires establishing the complete visual language: color palette with semantic mapping, typography scale, spacing system, shadows, motion tokens, and breakpoints — all in the correct format for Tailwind v4 + shadcn/ui v2.\n</commentary>\n</example>\n\n<example>\nContext: Modifying an existing design system\nuser: "Our current design system uses hex colors and HSL for shadcn tokens. We need to migrate to oklch for shadcn/ui v2 and add a complete dark mode palette. Current tokens are in docs/ui/ui-specs/ui-00-design-system.md."\nassistant: "I'll migrate the design tokens to oklch and add dark mode. Let me use the ui-design-system agent to convert all colors, verify contrast ratios in both modes, and update the CSS variables and @theme block."\n<commentary>\nMigrating token formats requires systematic conversion, contrast re-validation, and updating the CSS output to match current Tailwind v4 + shadcn/ui v2 conventions.\n</commentary>\n</example>\n\n<example>\nContext: Extending the design system with new tokens\nuser: "We need to add a status badge color system to our design tokens. Statuses: draft, active, processing, shipped, delivered, failed, cancelled. Each needs background, text, and border colors that work in both light and dark mode."\nassistant: "I'll design the status color system. Let me use the ui-design-system agent to create accessible color pairings for each status, define the tokens in oklch, and add them to the CSS variables with dark mode variants."\n<commentary>\nAdding semantic color groups requires careful selection for distinctiveness, accessibility, and consistency with the existing palette.\n</commentary>\n</example>
5
5
  color: green
6
- model: opus
7
- effort: max
8
- skills:
9
- - grimoire
10
- - playwright-cli
11
6
  memory: user
12
- disallowedTools: mcp__filesystem__write_file, mcp__filesystem__edit_file, mcp__filesystem__move_file, mcp__filesystem__create_directory
13
7
  tools: read, bash, grep, find, write, edit, ls, grimoire
14
- _notWired: model, effort, skills, memory
8
+ _notWired: memory
15
9
  ---
16
10
  If any instruction below conflicts with the user's global rules (provided separately in the system prompt), flag the conflict explicitly in your response and let the user decide — do not silently override either side.
17
11
 
@@ -3,15 +3,9 @@ name: ui-frontend-developer
3
3
  description: |-
4
4
  Use this agent for implementing specific React components, pages, or features with TypeScript, Next.js App Router, Tailwind CSS, and shadcn/ui. This agent receives laser-focused prompts with exact specifications and strictly verifies all SDK/library usage through grimoire before writing any code. Examples:\n\n<example>\nContext: Implementing a specific component from a screen spec\nuser: "Implement the OrderHistoryTable component in src/components/orders/OrderHistoryTable.tsx. It receives OrderRow[] as props, uses shadcn/ui DataTable with sortable columns (Order ID, Date, Status, Total), a status badge using the design system color tokens, and pagination. Follow the screen spec in docs/ui/ui-specs/orders-list.md."\nassistant: "I'll implement the OrderHistoryTable component. Let me use the ui-frontend-developer agent — it will verify shadcn/ui DataTable API and Tailwind token usage through grimoire before writing the component."\n<commentary>\nSpecific component implementation with exact props, library usage, and design system constraints requires the frontend specialist.\n</commentary>\n</example>\n\n<example>\nContext: Fixing a typed component issue\nuser: "The ProductCard component at src/components/catalog/ProductCard.tsx has a type error — the price prop is typed as string but the API returns number. Fix the type, update the Zod schema in src/schemas/product.ts, and ensure the formatter in formatCurrency handles both."\nassistant: "I'll fix the type mismatch across the component, schema, and utility. Let me use the ui-frontend-developer agent to trace the type through all layers."\n<commentary>\nTypeScript type issues that span multiple files need systematic tracing through components, schemas, and utilities.\n</commentary>\n</example>\n\n<example>\nContext: Building a Next.js App Router page\nuser: "Create the /settings/profile page using Next.js App Router. Server Component that fetches user profile via Server Action, with a client form component using React Hook Form + Zod for validation. Use the design system spacing and typography tokens. Spec: docs/ui/ui-specs/settings-profile.md."\nassistant: "I'll build the settings profile page with the Server Component / Client Component split. Let me use the ui-frontend-developer agent to verify Next.js App Router patterns and React Hook Form integration through grimoire."\n<commentary>\nNext.js App Router pages with mixed Server/Client Components and form handling require precise knowledge of current API patterns.\n</commentary>\n</example>
5
5
  color: blue
6
- model: opus
7
- effort: max
8
- skills:
9
- - grimoire
10
- - playwright-cli
11
6
  memory: user
12
- disallowedTools: mcp__filesystem__write_file, mcp__filesystem__edit_file, mcp__filesystem__move_file, mcp__filesystem__create_directory
13
7
  tools: read, bash, grep, find, write, edit, ls, grimoire
14
- _notWired: model, effort, skills, memory
8
+ _notWired: memory
15
9
  ---
16
10
  If any instruction below conflicts with the user's global rules (provided separately in the system prompt), flag the conflict explicitly in your response and let the user decide — do not silently override either side.
17
11
 
@@ -10,6 +10,7 @@ export interface AgentConfig {
10
10
  description: string;
11
11
  color?: string;
12
12
  tools?: string[];
13
+ skills?: string[];
13
14
  systemPrompt: string;
14
15
  source: AgentSource;
15
16
  filePath: string;
@@ -20,6 +21,7 @@ interface AgentFrontmatter extends Record<string, unknown> {
20
21
  description?: string;
21
22
  color?: string;
22
23
  tools?: string;
24
+ skills?: unknown;
23
25
  }
24
26
 
25
27
  function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
@@ -47,11 +49,23 @@ function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
47
49
  .map((t) => t.trim())
48
50
  .filter(Boolean);
49
51
 
52
+ let skills: string[] | undefined;
53
+ const rawSkills = frontmatter.skills;
54
+ if (Array.isArray(rawSkills)) {
55
+ skills = rawSkills.map((s) => String(s).trim()).filter(Boolean);
56
+ } else if (typeof rawSkills === "string") {
57
+ skills = rawSkills
58
+ .split(",")
59
+ .map((s) => s.trim())
60
+ .filter(Boolean);
61
+ }
62
+
50
63
  agents.push({
51
64
  name: frontmatter.name,
52
65
  description: frontmatter.description,
53
66
  color: frontmatter.color,
54
67
  tools: tools && tools.length > 0 ? tools : undefined,
68
+ skills: skills && skills.length > 0 ? skills : undefined,
55
69
  systemPrompt: body,
56
70
  source,
57
71
  filePath,
@@ -1,12 +1,33 @@
1
+ import * as fs from "node:fs";
1
2
  import * as path from "node:path";
2
3
  import { fileURLToPath } from "node:url";
3
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
4
+ import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
4
5
  import { Type } from "typebox";
5
6
  import { discoverAgents, type AgentScope } from "./discovery.ts";
6
7
  import { runAgent } from "./spawn.ts";
7
8
 
8
9
  const extensionDir = path.dirname(fileURLToPath(import.meta.url));
9
10
  const bundleAgentsDir = path.join(extensionDir, "agents");
11
+ const packageSkillsDir = path.resolve(extensionDir, "..", "..", "skills");
12
+
13
+ function resolvePackageSkills(
14
+ skillNames: string[],
15
+ ctx: ExtensionContext,
16
+ ): string[] {
17
+ const resolved: string[] = [];
18
+ for (const name of skillNames) {
19
+ const candidate = path.join(packageSkillsDir, name);
20
+ if (fs.existsSync(candidate)) {
21
+ resolved.push(candidate);
22
+ } else {
23
+ ctx.ui.notify(
24
+ `skill "${name}" declared by agent is not present in @astrofoundry/pi-astro; skipping.`,
25
+ "warning",
26
+ );
27
+ }
28
+ }
29
+ return resolved;
30
+ }
10
31
 
11
32
  const params = Type.Object({
12
33
  agent: Type.String({ description: "Name of the subagent to invoke." }),
@@ -61,10 +82,13 @@ export default function astroAgentsExtension(pi: ExtensionAPI): void {
61
82
 
62
83
  ctx.ui.notify(`Running ${colorizePrefix(agent.name, agent.color)}…`, "info");
63
84
 
85
+ const skillPaths = agent.skills ? resolvePackageSkills(agent.skills, ctx) : [];
86
+
64
87
  const result = await runAgent({
65
88
  agent,
66
89
  task: input.task,
67
90
  cwd: ctx.cwd,
91
+ skillPaths,
68
92
  signal,
69
93
  });
70
94
 
@@ -71,11 +71,12 @@ export interface RunAgentOptions {
71
71
  agent: AgentConfig;
72
72
  task: string;
73
73
  cwd: string;
74
+ skillPaths?: string[];
74
75
  signal?: AbortSignal | undefined;
75
76
  }
76
77
 
77
78
  export async function runAgent(options: RunAgentOptions): Promise<SpawnResult> {
78
- const { agent, task, cwd, signal } = options;
79
+ const { agent, task, cwd, skillPaths, signal } = options;
79
80
 
80
81
  const args = ["--mode", "json", "-p", "--no-session"];
81
82
  let tmpDir: string | null = null;
@@ -84,6 +85,13 @@ export async function runAgent(options: RunAgentOptions): Promise<SpawnResult> {
84
85
  args.push("--tools", agent.tools.join(","));
85
86
  }
86
87
 
88
+ if (agent.skills && agent.skills.length > 0) {
89
+ args.push("--no-skills");
90
+ for (const skillPath of skillPaths ?? []) {
91
+ args.push("--skill", skillPath);
92
+ }
93
+ }
94
+
87
95
  if (agent.systemPrompt.trim()) {
88
96
  const tmp = writeSystemPromptTempFile(agent.name, agent.systemPrompt);
89
97
  tmpDir = tmp.dir;
@@ -3,18 +3,23 @@ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
3
3
  import type { AgentToolResult } from "@mariozechner/pi-agent-core";
4
4
  import { Type } from "typebox";
5
5
 
6
- function loadGrimoireHelp(): string {
6
+ function loadGrimoireHelp(): { help: string; available: boolean } {
7
7
  try {
8
- return execFileSync("grimoire", ["--help"], {
8
+ const help = execFileSync("grimoire", ["--help"], {
9
9
  encoding: "utf-8",
10
10
  stdio: ["ignore", "pipe", "pipe"],
11
11
  }).trim();
12
+ return { help, available: true };
12
13
  } catch {
13
- return "grimoire CLI not available on PATH at extension load time.";
14
+ return { help: "", available: false };
14
15
  }
15
16
  }
16
17
 
17
- const helpOutput = loadGrimoireHelp();
18
+ const { help: helpOutput, available: grimoireAvailable } = loadGrimoireHelp();
19
+
20
+ const NOT_INSTALLED_MESSAGE =
21
+ "grimoire CLI is not installed or not on PATH. Install it per your setup instructions " +
22
+ "(e.g. `npm install -g @astrofoundry/grimoire`), then restart pi so the extension can re-initialize.";
18
23
 
19
24
  const params = Type.Object({
20
25
  query: Type.String({ description: "Search query — use the library's own terminology." }),
@@ -30,17 +35,27 @@ export default function grimoireExtension(pi: ExtensionAPI): void {
30
35
  label: "Grimoire",
31
36
  description:
32
37
  "Search indexed technical documentation via the grimoire CLI. Prefer this over web search for library/framework docs.",
33
- promptGuidelines: [
34
- "Use `grimoire` for ALL documentation lookups — libraries, frameworks, APIs, CLIs, cloud services.",
35
- "Match query terminology to the library's own docs (e.g. 'Firestore pagination cursors' not 'how do I paginate').",
36
- "If the first search misses, rephrase or scope with `source`.",
37
- "Cite the URL from results when precision matters.",
38
- "",
39
- "Current `grimoire --help` output:",
40
- helpOutput,
41
- ],
38
+ promptGuidelines: grimoireAvailable
39
+ ? [
40
+ "Use `grimoire` for ALL documentation lookups libraries, frameworks, APIs, CLIs, cloud services.",
41
+ "Match query terminology to the library's own docs (e.g. 'Firestore pagination cursors' not 'how do I paginate').",
42
+ "If the first search misses, rephrase or scope with `source`.",
43
+ "Cite the URL from results when precision matters.",
44
+ "",
45
+ "Current `grimoire --help` output:",
46
+ helpOutput,
47
+ ]
48
+ : [
49
+ `grimoire CLI was NOT available when pi started. ${NOT_INSTALLED_MESSAGE}`,
50
+ "Any call to this tool will return an error until grimoire is installed and pi is restarted.",
51
+ ],
42
52
  parameters: params,
43
- async execute(_toolCallId, input, signal) {
53
+ async execute(_toolCallId, input, signal, _onUpdate, ctx) {
54
+ if (!grimoireAvailable) {
55
+ ctx.ui.notify("grimoire CLI not available — install it and restart pi.", "error");
56
+ throw new Error(NOT_INSTALLED_MESSAGE);
57
+ }
58
+
44
59
  return new Promise<AgentToolResult<unknown>>((resolve, reject) => {
45
60
  const args = ["search", input.query, "--compact"];
46
61
  if (input.source) args.push("--source", input.source);
@@ -74,16 +89,43 @@ export default function grimoireExtension(pi: ExtensionAPI): void {
74
89
  );
75
90
  return;
76
91
  }
77
- const text = stdout.trim() || "(no results)";
92
+
93
+ const output = stdout.trim();
94
+ const isNoResults = output === "" || /^no results found\.?$/im.test(output);
95
+
96
+ if (isNoResults) {
97
+ const scopeNote = input.source ? ` in source '${input.source}'` : "";
98
+ const suggestion = input.source
99
+ ? "Try rephrasing the query or widening scope by omitting `source`."
100
+ : "Try rephrasing with the library's own terminology, or check the indexed sources via `grimoire list --names`.";
101
+ ctx.ui.notify(`grimoire: no results for "${input.query}"${scopeNote}`, "warning");
102
+ resolve({
103
+ content: [
104
+ {
105
+ type: "text",
106
+ text: `No results found for "${input.query}"${scopeNote}. ${suggestion}`,
107
+ },
108
+ ],
109
+ details: { query: input.query, source: input.source, results: 0 },
110
+ });
111
+ return;
112
+ }
113
+
78
114
  resolve({
79
- content: [{ type: "text", text }],
115
+ content: [{ type: "text", text: output }],
80
116
  details: { query: input.query, source: input.source },
81
117
  });
82
118
  });
83
119
 
84
120
  proc.on("error", (err) => {
85
121
  signal?.removeEventListener("abort", abortHandler);
86
- reject(new Error(`grimoire CLI not runnable: ${err.message}`));
122
+ const nodeErr = err as NodeJS.ErrnoException;
123
+ if (nodeErr.code === "ENOENT") {
124
+ ctx.ui.notify("grimoire CLI not available — install it and restart pi.", "error");
125
+ reject(new Error(NOT_INSTALLED_MESSAGE));
126
+ return;
127
+ }
128
+ reject(new Error(`grimoire CLI failed to run: ${err.message}`));
87
129
  });
88
130
  });
89
131
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrofoundry/pi-astro",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Personal pi customizations (extensions, skills, prompts, themes) for the pi coding agent.",
5
5
  "keywords": [
6
6
  "pi-package"
@@ -6,6 +6,54 @@ allowed-tools: Bash(playwright-cli:*)
6
6
 
7
7
  # Browser Automation with playwright-cli
8
8
 
9
+ ## Bypassing bot detection — use `attach --cdp` (IMPORTANT)
10
+
11
+ If a site is guarded by Cloudflare / "Prove your humanity" / bot detection (Reddit, LinkedIn, X, CF-protected pages), **do NOT use `playwright-cli open`** — a launched Chromium gets blocked by `navigator.webdriver` / TLS / launch-flag fingerprinting.
12
+
13
+ Instead, **attach to a real Chrome running with the CDP debug port**. This uses the user's genuine Chrome binary with a clean automation-free launch, so detection signals are absent.
14
+
15
+ ### Setup instructions to give the user
16
+
17
+ ```bash
18
+ # User runs this once (in their own shell, not via the skill):
19
+ mkdir -p ~/.chrome-profiles/pi-automation
20
+ /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
21
+ --remote-debugging-port=9222 \
22
+ --user-data-dir="$HOME/.chrome-profiles/pi-automation" &
23
+ ```
24
+
25
+ Notes:
26
+ - An isolated `--user-data-dir` is **required** — Chrome 136+ refuses remote debugging on the default profile.
27
+ - Path survives reboots; user logs into sites once and state persists in that profile.
28
+ - To kill this Chrome later: `pkill -f "remote-debugging-port=9222"`.
29
+
30
+ ### Skill-side invocation
31
+
32
+ ```bash
33
+ playwright-cli attach --cdp=http://localhost:9222
34
+ playwright-cli goto https://www.reddit.com/r/popular/
35
+ playwright-cli eval "() => document.title"
36
+ ```
37
+
38
+ ### Handling a human-verification challenge
39
+
40
+ If `document.title` matches `/(Prove your humanity|Just a moment|Checking your browser|Access denied)/i` or the page body is empty after navigation, **a CAPTCHA is blocking the automation**. The attached Chrome window is visible to the user — stop, tell the user to solve it in that window, and resume after they confirm.
41
+
42
+ Exact phrasing template:
43
+
44
+ > "Captcha detected in the Chrome window — please solve it manually, then reply 'done' so I can resume."
45
+
46
+ After the user replies, re-run `playwright-cli eval` to verify page content is now present, then continue with extraction.
47
+
48
+ ### When to prefer an API over playwright-cli entirely
49
+
50
+ If the target site has a public JSON/REST endpoint, use `curl` with a proper User-Agent instead — faster, no CAPTCHA, no browser needed:
51
+ - Reddit: `curl -H "User-Agent: …" https://www.reddit.com/r/popular.json`
52
+ - Hacker News: `curl https://hacker-news.firebaseio.com/v0/topstories.json`
53
+ - GitHub: `gh api` or the public REST API
54
+
55
+ Reach for browser automation only when no API exists.
56
+
9
57
  ## Quick start
10
58
 
11
59
  ```bash