Skip to content

Commit 2daf8c3

Browse files
authored
Merge pull request #9 from pipedrive/AINATIVEM-47
AINATIVEM-47 AI plugin layer — CLI subcommands and Claude Code plugin
2 parents 409d899 + 6323220 commit 2daf8c3

28 files changed

Lines changed: 1314 additions & 65 deletions

File tree

.agents/plugins/marketplace.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "pipedrive",
3+
"interface": {
4+
"displayName": "Create pipedrive app"
5+
},
6+
"plugins": [
7+
{
8+
"name": "create-pipedrive-app",
9+
"source": {
10+
"source": "local",
11+
"path": "./plugins/create-pipedrive-app"
12+
},
13+
"policy": {
14+
"installation": "AVAILABLE",
15+
"authentication": "ON_INSTALL"
16+
},
17+
"category": "Coding"
18+
}
19+
]
20+
}

.claude-plugin/marketplace.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "pipedrive",
3+
"owner": {
4+
"name": "Pipedrive",
5+
"url": "https://www.pipedrive.com/"
6+
},
7+
"metadata": {
8+
"description": "Pipedrive developer tools for Claude Code."
9+
},
10+
"plugins": [
11+
{
12+
"name": "create-pipedrive-app",
13+
"source": "./plugin",
14+
"description": "Slash commands for scaffolding and extending Pipedrive Marketplace integration projects"
15+
}
16+
]
17+
}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ docs/superpowers/
77
*-app/
88
apps/
99

10+
# repo-local Codex plugin
11+
!plugins/create-pipedrive-app/
12+
!plugins/create-pipedrive-app/**
13+
1014
.idea/

CLAUDE.md

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ npm run typecheck # type-check without emitting
1414
npm run lint # ESLint
1515
npm run format # Prettier (120 char width, tabs, trailing commas)
1616
npm test # Vitest suite
17-
npm run generate # generate test project in apps/test-app/ (gitignored)
17+
npm run generate # generate test project in apps/test-app/ (gitignored)
18+
npm run clean # delete generated apps/ directory
1819
```
1920

2021
Run a single test file:
@@ -33,28 +34,36 @@ The tool is **CLI-first**, with an **AI plugin layer** built on top:
3334
### Interactive prompts (CLI)
3435

3536
The CLI asks for:
36-
- Backend: Node.js/Express, Node.js/Fastify, or PHP/Laravel
37+
- Project name
3738
- Database: Postgres, MySQL, or SQLite
3839
- App Extensions frontend: multi-select of `custom-panel` and/or `custom-modal` (or neither)
39-
- Webhooks: Yes/No
4040

41-
`GeneratorOptions.appExtensions` is `AppExtensionType[]` where `AppExtensionType = 'custom-panel' | 'custom-modal'`. Check membership with `.includes('custom-panel')`, not boolean equality.
41+
`GeneratorOptions.appExtensions` is `AppExtensionType[]` where `AppExtensionType` is derived from the `APP_EXTENSION_TYPES` const (`'custom-panel' | 'custom-modal'`). Use `isAppExtensionType(value)` to validate CLI input. Check membership with `.includes('custom-panel')`, not boolean equality.
42+
43+
### CLI subcommands
44+
45+
Beyond the interactive main flow, the CLI supports subcommands invoked by the AI plugin skills:
46+
47+
```bash
48+
npx create-pipedrive-app add-app-extension --app-extensions custom-panel|custom-modal [--output-dir <dir>]
49+
```
50+
51+
Subcommand dispatch happens in `dispatchSubcommand()` in `cli.ts` before the interactive flow runs.
4252

4353
### Generator flow
4454

4555
```
4656
cli.ts (collects prompts)
47-
→ prompts/ (projectName, database, appExtensions, webhooks)
57+
→ prompts/ (projectName, database, appExtensions)
4858
→ nodeGenerator (orchestrates sub-generators via NodeProjectBuilder)
49-
→ oauth.ts, database.ts, app.ts
50-
→ webhooks.ts (conditional)
59+
→ oauth.ts, database.ts, app.ts, pipedriveClient.ts, crypto.ts
5160
→ appExtensions.ts (conditional)
5261
→ appExtensions/panel.ts — backend router + React snippet contributions
5362
→ appExtensions/modal.ts — backend router + React snippet contributions
5463
→ appExtensions/frontend.ts — Vite + React frontend (index.html, App.tsx, etc.)
5564
→ appExtensions/sdk.ts — usePipedriveSdk hook wrapper
5665
→ appExtensions/router.ts — shared Express static-file router
57-
→ serverEntry, packageJson, tsConfig, envExample, dockerCompose
66+
→ serverEntry, packageJson, tsConfig, envExample, dockerCompose, readme
5867
```
5968

6069
**There is no template directory.** Generators build file content as strings using `dedent()`, with conditional string interpolation for optional features. The `src/utils/writeFile.ts` utility writes files, creates parent directories, and auto-formats output with Prettier — generated code is formatted automatically without an explicit format step.
@@ -67,9 +76,8 @@ cli.ts (collects prompts)
6776
app.ts # Express app, mounts all routers
6877
index.ts # Server entry with DB retry loop
6978
oauth/ # Authorization redirect, callback, token exchange, refresh
70-
pipedrive-client/ # Official API client wrapper
79+
pipedrive/ # Official API client wrapper (getClient, token refresh via onTokenUpdate)
7180
database/ # Drizzle schema, migrations, db setup
72-
webhooks/ # Optional webhook handlers
7381
app-extensions/
7482
panel/ # Express router serving built frontend (custom-panel)
7583
modal/ # Express router serving built frontend (custom-modal)
@@ -78,7 +86,6 @@ cli.ts (collects prompts)
7886
.env.example
7987
README.md
8088
docker-compose.yml
81-
marketplace-checklist.md
8289
```
8390

8491
## App Extensions pattern
@@ -105,7 +112,7 @@ The scaffold generator uses `NodeProjectBuilder` + `BuildStep` (`src/generators/
105112
2. Add a named method to `NodeProjectBuilder`: `addMyFeature(): this { return this.addStep(new MyFeatureStep()); }`
106113
3. Call it in `index.ts`, via `when()` if conditional:
107114
```ts
108-
.when(options.webhooks, b => b.addWebhooks())
115+
.when(options.appExtensions.length > 0, b => b.addAppExtensions())
109116
```
110117

111118
**Rule: never put conditional logic inside `execute()`** — use `when()` at the call site. Steps must be unconditional internally; the builder chain controls what runs.
@@ -122,21 +129,20 @@ The scaffold generator uses `NodeProjectBuilder` + `BuildStep` (`src/generators/
122129
- **New App Extension type**: add a file under `src/generators/node/appExtensions/` that exports an `async generate*` function and a `*ReactSnippets()` function returning `ReactSnippetContribution`, then wire it in `appExtensions.ts` and `frontend.ts`
123130
- **Modify generated scaffold**: edit template strings in the corresponding generator file
124131

125-
## Core Modules
132+
## Generated Project Modules
126133

127-
### OAuth (`backend/oauth/`)
128-
Full OAuth 2.0: app registration guidance, authorization redirect, callback handling, token exchange, token refresh, state validation.
134+
### OAuth (`src/oauth/`)
135+
Full OAuth 2.0: authorization redirect, callback handling, token exchange, HMAC-signed state parameter with TTL validation.
129136

130-
### Database (`backend/database/`)
137+
### Database (`src/database/`)
131138
Uses **Drizzle ORM** (`drizzle-orm` + `drizzle-kit`) for schema definition and migrations. Supports Postgres, MySQL, and SQLite with the same TypeScript API.
132139

133-
Structure:
134140
- `schema.ts` — Drizzle table definitions (tenants, oauth_tokens, installations)
135141
- `migrations/` — SQL migration files managed by `drizzle-kit`
136142
- `db.ts` — driver setup (selects `postgres-js`, `mysql2`, or `better-sqlite3` based on chosen DB)
137143

138-
### Pipedrive API client (`backend/pipedrive-client/`)
139-
Wrapper around the official Pipedrive Node.js client with preconfigured authentication and helpers for common API calls.
144+
### Pipedrive API client (`src/pipedrive/`)
145+
Wraps the official Pipedrive Node.js SDK. `getClient(companyId)` loads the stored OAuth token and configures `onTokenUpdate` so the SDK handles token refresh automatically.
140146

141147
### App Extensions frontend (`frontend/app-extension-ui/`)
142148
Generated when the user selects `custom-panel` and/or `custom-modal`. Iframe-based React + Vite UI using the App Extensions SDK (`usePipedriveSdk` hook), with: SDK initialization, theme handling, resize, snackbar, confirmation dialog, signed token, and extension-type-specific actions (open modal from panel, close modal).
@@ -145,11 +151,15 @@ Generated when the user selects `custom-panel` and/or `custom-modal`. Iframe-bas
145151

146152
Vitest. Tests generate files into a `tmpdir()/cpa-app-test` directory, read them back to verify content, and clean up in `afterEach`.
147153

148-
## AI Plugin Commands (future layer)
154+
## AI Plugin Layer
149155

150-
```
151-
/pipedrive-new-app
152-
/pipedrive-add-oauth
153-
/pipedrive-add-app-extension
154-
/pipedrive-review-marketplace-readiness
155-
```
156+
The `plugin/` directory is shipped with the npm package (`"files": ["dist", "plugin"]`) and contains Claude Code skills that wrap the CLI for AI-assisted development. Each skill is a markdown instruction document in `plugin/skills/<name>/SKILL.md`.
157+
158+
| Skill | Purpose |
159+
|-------|---------|
160+
| `pipedrive-new-app` | Scaffold a new app interactively via `npx create-pipedrive-app` |
161+
| `pipedrive-add-app-extension` | Add a panel or modal extension via the `add-app-extension` subcommand |
162+
| `pipedrive-api` | Guide on using the Pipedrive REST API and SDK within a generated project |
163+
| `pipedrive-review-marketplace-readiness` | Gap analysis before marketplace submission: checks token refresh, HTTPS, error handling, and rate limit handling |
164+
165+
Skills use `allowed-tools` frontmatter to restrict which Claude tools they can invoke. Adding a new skill means creating a `SKILL.md` in a new subdirectory under `plugin/skills/`.

README.md

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,86 @@
11
# create-pipedrive-app
22

3-
CLI scaffolding tool for Pipedrive Marketplace integrations.
3+
CLI scaffolding tool for Pipedrive Marketplace integrations. Generates an Express + TypeScript + Drizzle ORM project with OAuth 2.0, a Pipedrive API client, and optional App Extensions frontend (React + Vite). The CLI can be used standalone without any AI tooling.
44

55
## Usage
66

77
```bash
8-
npx create-pipedrive-app <project-name>
8+
npx create-pipedrive-app
99
```
1010

11-
The CLI will prompt for:
11+
The CLI prompts for:
1212

13+
- **Project name**
1314
- **Database**: Postgres, MySQL, or SQLite
14-
- **App Extensions**: custom panel, custom modal, or none
15-
- **Webhooks**: yes or no
15+
- **App Extensions**: custom panel, custom modal, or neither
1616

1717
## Generated project
1818

1919
```
2020
<project-name>/
2121
src/
22-
index.ts # server entry point (port 3000)
23-
app.ts # Express app with OAuth router (+ optional webhooks/extensions)
22+
index.ts # server entry point
23+
app.ts # Express app with OAuth router (+ optional App Extensions)
2424
oauth/ # OAuth 2.0 install, callback, token exchange, refresh
25+
pipedrive/ # Pipedrive API client wrapper
2526
database/ # Drizzle ORM schema, migrations, db driver
26-
pipedrive-client/ # Pipedrive API client wrapper
27-
webhooks/ # Webhook handlers (if selected)
2827
app-extensions/ # App Extensions handlers (if selected)
2928
frontend/
3029
app-extension-ui/ # React + Vite iframe UI (if App Extensions selected)
3130
.env.example
32-
docker-compose.yml # Postgres, MySQL, and/or App Extensions UI (if applicable)
31+
docker-compose.yml
3332
README.md
3433
package.json
3534
tsconfig.json
3635
```
3736

3837
The generated project uses **Express + TypeScript + Drizzle ORM** (ESM, Node.js).
3938

40-
When App Extensions are selected, the generated project also includes a shared React iframe app for custom panels and custom modals. `docker-compose up --watch` starts the backend and Vite dev server in containers with Compose Watch. Local Developer Hub iframe URLs should point at an HTTPS tunnel to the Vite dev server, for example `https://<your-vite-tunnel>/extensions/panel` or `https://<your-vite-tunnel>/extensions/modal`. After `npm run build`, production iframe URLs can point at the backend-hosted `/extensions/panel` and `/extensions/modal` routes.
39+
When App Extensions are selected, the project includes a shared React iframe app for custom panels and modals. `docker-compose up --watch` starts the backend and Vite dev server in containers with Compose Watch. Local Developer Hub iframe URLs must point at an HTTPS tunnel to the Vite dev serverfor example `https://<your-vite-tunnel>/extensions/panel` or `https://<your-vite-tunnel>/extensions/modal`. After `npm run build`, production iframe URLs can point at the backend-hosted routes.
4140

42-
## Next steps after generation
41+
## Requirements
42+
43+
- Node.js (to run `npx create-pipedrive-app`)
44+
- Docker (for Postgres/MySQL databases and App Extensions development)
45+
46+
## Using with an AI coding assistant
47+
48+
The package ships plugins for **Claude Code** and **Codex** that wrap the CLI with guided slash commands. The plugins require the CLI — they call `npx create-pipedrive-app` under the hood.
49+
50+
### Claude Code
51+
52+
This repository acts as the Claude Code plugin marketplace. Claude reads the marketplace catalog from `.claude-plugin/marketplace.json`, then installs the plugin from `plugin/`.
53+
54+
After this repository is public, install the plugin with:
4355

4456
```bash
45-
cd <project-name>
46-
cp .env.example .env
47-
docker-compose up -d db # if Postgres or MySQL was selected
48-
npm install
49-
npm run dev
57+
claude plugin marketplace add pipedrive/create-pipedrive-app
58+
claude plugin install create-pipedrive-app@pipedrive
59+
```
60+
61+
Inside Claude Code, use the equivalent slash commands:
62+
63+
```text
64+
/plugin marketplace add pipedrive/create-pipedrive-app
65+
/plugin install create-pipedrive-app@pipedrive
66+
/reload-plugins
5067
```
5168

52-
If App Extensions were selected, use Compose Watch instead of the local dev server:
69+
The plugin calls `npx create-pipedrive-app` under the hood, so the npm package must also be published or otherwise available to users.
70+
71+
### Codex
5372

5473
```bash
55-
docker-compose up --watch
74+
codex plugin install create-pipedrive-app
5675
```
5776

58-
Fill in `PIPEDRIVE_CLIENT_ID`, `PIPEDRIVE_CLIENT_SECRET`, and `DATABASE_URL` in `.env`.
77+
### Available commands
5978

60-
## Requirements
79+
Both plugins expose the same slash commands:
6180

62-
- Node.js 18+
63-
- Docker (if using Postgres, MySQL, or App Extensions frontend development)
81+
| Command | What it does |
82+
|---------|-------------|
83+
| `/pipedrive-new-app` | Scaffold a new integration project |
84+
| `/pipedrive-add-app-extension` | Add a custom panel or modal extension |
85+
| `/pipedrive-api` | Get guidance on using the Pipedrive API |
86+
| `/pipedrive-review-marketplace-readiness` | Check for gaps before submitting to the marketplace |

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
"version": "0.1.0",
44
"description": "Scaffold a production-ready Pipedrive Marketplace app",
55
"type": "module",
6+
"files": [
7+
"dist",
8+
"plugin",
9+
"plugins"
10+
],
611
"bin": {
712
"create-pipedrive-app": "./dist/cli.js"
813
},

plugin/.claude-plugin/plugin.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "create-pipedrive-app",
3+
"description": "Slash commands for scaffolding and extending Pipedrive Marketplace integration projects",
4+
"version": "0.1.0",
5+
"author": {
6+
"name": "Pipedrive"
7+
}
8+
}

0 commit comments

Comments
 (0)