prpm 0.0.4 → 0.0.6

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
@@ -20,7 +20,7 @@ brew install prpm
20
20
  ```
21
21
 
22
22
  ### Direct Download
23
- Download the latest binary from [GitHub Releases](https://github.com/khaliqgant/prompt-package-manager/releases).
23
+ Download the latest binary from [GitHub Releases](https://github.com/pr-pm/prpm/releases).
24
24
 
25
25
  ## Quick Start
26
26
 
@@ -908,10 +908,10 @@ export PRPM_REGISTRY_URL=https://custom-registry.com
908
908
 
909
909
  ## Support & Resources
910
910
 
911
- - **GitHub**: https://github.com/khaliqgant/prompt-package-manager
912
- - **Issues**: https://github.com/khaliqgant/prompt-package-manager/issues
911
+ - **GitHub**: https://github.com/pr-pm/prpm
912
+ - **Issues**: https://github.com/pr-pm/prpm/issues
913
913
  - **Registry**: https://registry.prpm.dev
914
- - **Documentation**: https://github.com/khaliqgant/prompt-package-manager#readme
914
+ - **Documentation**: https://github.com/pr-pm/prpm#readme
915
915
 
916
916
  ## Contributing
917
917
 
@@ -169,6 +169,9 @@ async function handleIndex(options = {}) {
169
169
  console.error(`❌ Failed to index packages: ${error}`);
170
170
  process.exit(1);
171
171
  }
172
+ finally {
173
+ process.exit(0);
174
+ }
172
175
  }
173
176
  /**
174
177
  * Create the index command
@@ -115,6 +115,7 @@ async function loginWithOAuth(registryUrl) {
115
115
  const userId = `cli_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
116
116
  try {
117
117
  // Get the Nango connect session from the registry
118
+ console.log(` Connecting to: ${registryUrl}`);
118
119
  const response = await fetch(`${registryUrl}/api/v1/auth/nango/cli/connect-session`, {
119
120
  method: 'POST',
120
121
  headers: {
@@ -127,7 +128,8 @@ async function loginWithOAuth(registryUrl) {
127
128
  }),
128
129
  });
129
130
  if (!response.ok) {
130
- throw new Error('Failed to get authentication session');
131
+ const errorText = await response.text().catch(() => 'Unable to read error response');
132
+ throw new Error(`Failed to get authentication session (${response.status}): ${errorText}`);
131
133
  }
132
134
  const responseData = await response.json();
133
135
  const { connectSessionToken } = responseData;
@@ -156,6 +158,15 @@ async function loginWithOAuth(registryUrl) {
156
158
  return { token: result.token, username: result.username || 'unknown' };
157
159
  }
158
160
  catch (error) {
161
+ if (error instanceof Error) {
162
+ // Check for common network errors
163
+ if (error.message.includes('ECONNREFUSED')) {
164
+ throw new Error(`Cannot connect to registry at ${registryUrl}. Is the registry running?`);
165
+ }
166
+ else if (error.message.includes('ENOTFOUND') || error.message.includes('getaddrinfo')) {
167
+ throw new Error(`Cannot resolve registry hostname: ${registryUrl}. Check your internet connection.`);
168
+ }
169
+ }
159
170
  throw new Error(`Authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
160
171
  }
161
172
  }
@@ -172,22 +183,15 @@ async function pollForAuthentication(registryUrl, userId) {
172
183
  const { authenticated, connectionId } = await response.json();
173
184
  if (authenticated && connectionId) {
174
185
  // Authentication completed, get the JWT token
175
- const callbackResponse = await fetch(`${registryUrl}/api/v1/auth/nango/callback`, {
176
- method: 'POST',
177
- headers: {
178
- 'Content-Type': 'application/json',
179
- },
180
- body: JSON.stringify({
181
- connectionId,
182
- redirectUrl: '/cli-success',
183
- }),
184
- });
185
- if (callbackResponse.ok) {
186
- const result = await callbackResponse.json();
187
- return {
188
- token: result.token,
189
- username: result.username,
190
- };
186
+ const statusResponse = await fetch(`${registryUrl}/api/v1/auth/nango/status/${connectionId}`);
187
+ if (statusResponse.ok) {
188
+ const result = await statusResponse.json();
189
+ if (result.ready && result.token) {
190
+ return {
191
+ token: result.token,
192
+ username: result.username,
193
+ };
194
+ }
191
195
  }
192
196
  }
193
197
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prpm",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Prompt Package Manager CLI - Install and manage prompt-based files",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -30,13 +30,13 @@
30
30
  ],
31
31
  "repository": {
32
32
  "type": "git",
33
- "url": "git+https://github.com/khaliqgant/prompt-package-manager.git",
33
+ "url": "git+https://github.com/pr-pm/prpm.git",
34
34
  "directory": "packages/cli"
35
35
  },
36
36
  "bugs": {
37
- "url": "https://github.com/khaliqgant/prompt-package-manager/issues"
37
+ "url": "https://github.com/pr-pm/prpm/issues"
38
38
  },
39
- "homepage": "https://github.com/khaliqgant/prompt-package-manager#readme",
39
+ "homepage": "https://github.com/pr-pm/prpm#readme",
40
40
  "author": "khaliqgant",
41
41
  "license": "MIT",
42
42
  "dependencies": {
@@ -65,6 +65,7 @@
65
65
  },
66
66
  "files": [
67
67
  "dist",
68
+ "schemas",
68
69
  "README.md",
69
70
  "LICENSE"
70
71
  ],
@@ -0,0 +1,197 @@
1
+ # PRPM Manifest Schema
2
+
3
+ This directory contains the JSON Schema for validating `prpm.json` manifest files.
4
+
5
+ ## Schema File
6
+
7
+ **Location**: `prpm-manifest.schema.json`
8
+
9
+ **Schema URL**: `https://prpm.dev/schemas/manifest.json`
10
+
11
+ ## Alternative: marketplace.json
12
+
13
+ PRPM also supports Claude's `marketplace.json` format as an alternative to `prpm.json`. If you have a `.claude/marketplace.json` file, PRPM will automatically detect and convert it when you run `prpm publish`.
14
+
15
+ See [marketplace.json documentation](../docs/marketplace-json.md) for details.
16
+
17
+ ## Using the Schema
18
+
19
+ ### In Your Editor (VS Code, etc.)
20
+
21
+ Add this line to the top of your `prpm.json` file to get autocomplete and validation:
22
+
23
+ ```json
24
+ {
25
+ "$schema": "https://prpm.dev/schemas/manifest.json",
26
+ "name": "@username/my-package",
27
+ "version": "1.0.0",
28
+ ...
29
+ }
30
+ ```
31
+
32
+ ### Programmatic Validation
33
+
34
+ The schema is automatically used by `prpm publish` to validate your manifest before publishing.
35
+
36
+ ```typescript
37
+ import { validateManifestSchema } from '@prpm/cli/core/schema-validator';
38
+
39
+ const manifest = {
40
+ name: 'my-package',
41
+ version: '1.0.0',
42
+ description: 'My package description',
43
+ type: 'claude-skill',
44
+ files: ['skill.md']
45
+ };
46
+
47
+ const result = validateManifestSchema(manifest);
48
+ if (!result.valid) {
49
+ console.error('Validation errors:', result.errors);
50
+ }
51
+ ```
52
+
53
+ ### With JSON Schema Validators
54
+
55
+ You can use any JSON Schema validator (like AJV, jsonschema, etc.):
56
+
57
+ ```javascript
58
+ const Ajv = require('ajv');
59
+ const schema = require('./prpm-manifest.schema.json');
60
+
61
+ const ajv = new Ajv();
62
+ const validate = ajv.compile(schema);
63
+
64
+ const valid = validate(manifest);
65
+ if (!valid) {
66
+ console.log(validate.errors);
67
+ }
68
+ ```
69
+
70
+ ## Schema Features
71
+
72
+ ### Required Fields
73
+
74
+ - `name` - Package name (lowercase, alphanumeric, hyphens)
75
+ - `version` - Semver version (e.g., `1.0.0`)
76
+ - `description` - Description (10-500 characters)
77
+ - `type` - Package type (`cursor`, `claude-skill`, `collection`, etc.)
78
+
79
+ ### File Formats
80
+
81
+ The schema supports two formats for the `files` array:
82
+
83
+ #### Simple Format (strings)
84
+ ```json
85
+ {
86
+ "files": ["skill.md", "README.md", "LICENSE"]
87
+ }
88
+ ```
89
+
90
+ #### Enhanced Format (objects with metadata)
91
+ ```json
92
+ {
93
+ "files": [
94
+ {
95
+ "path": ".claude/skills/tdd.md",
96
+ "type": "claude-skill",
97
+ "name": "Test-Driven Development",
98
+ "description": "TDD workflow guide",
99
+ "tags": ["testing", "tdd"]
100
+ }
101
+ ]
102
+ }
103
+ ```
104
+
105
+ ### Validation Rules
106
+
107
+ #### Package Name
108
+ - Pattern: `^(@[a-z0-9-]+\/)?[a-z0-9-]+$`
109
+ - Examples: `react-rules`, `@username/package`
110
+ - No uppercase, spaces, or special characters
111
+
112
+ #### Version
113
+ - Must be valid semver: `MAJOR.MINOR.PATCH`
114
+ - Supports prerelease: `1.0.0-beta.1`
115
+ - Supports build metadata: `1.0.0+20130313144700`
116
+
117
+ #### Description
118
+ - Minimum length: 10 characters
119
+ - Maximum length: 500 characters
120
+
121
+ #### Type
122
+ Valid types:
123
+ - `cursor` - Cursor IDE rules
124
+ - `claude` - Claude AI prompts
125
+ - `claude-skill` - Claude Code skills
126
+ - `claude-agent` - Claude Code agents
127
+ - `claude-slash-command` - Claude Code slash commands
128
+ - `continue` - Continue IDE rules
129
+ - `windsurf` - Windsurf IDE rules
130
+ - `generic` - Generic prompts
131
+ - `collection` - Mixed types (use only when files have multiple distinct types)
132
+
133
+ #### Tags & Keywords
134
+ - `tags`: Maximum 10 items
135
+ - `keywords`: Maximum 20 items
136
+ - Must be unique within array
137
+
138
+ #### URLs
139
+ The following fields must be valid URLs:
140
+ - `repository`
141
+ - `homepage`
142
+ - `documentation`
143
+ - `author.url`
144
+
145
+ #### Email
146
+ `author.email` must be valid email format
147
+
148
+ ## Examples
149
+
150
+ See the `examples/` directory for complete manifest examples:
151
+
152
+ 1. **Simple Package**: `examples/simple-package/prpm.json`
153
+ 2. **Multi-File Same Type**: `examples/multi-file-single-type/prpm.json`
154
+ 3. **Collection Package**: `examples/collection-package/prpm.json`
155
+ 4. **Claude Skills**: `examples/claude-skills-multi-file/prpm.json`
156
+
157
+ ## Schema Updates
158
+
159
+ When updating the schema:
160
+
161
+ 1. **Edit** `prpm-manifest.schema.json`
162
+ 2. **Test** with `npm test -- schema-validator`
163
+ 3. **Update** this README if adding new features
164
+ 4. **Version** the schema (update `$id` if making breaking changes)
165
+ 5. **Document** any new validation rules
166
+
167
+ ## Validation Errors
168
+
169
+ Common validation errors and how to fix them:
170
+
171
+ ### "Missing required field: X"
172
+ Add the required field to your manifest.
173
+
174
+ ### "Pattern mismatch" (name)
175
+ Package names must be lowercase alphanumeric with hyphens only. No spaces or special characters.
176
+
177
+ ### "Pattern mismatch" (version)
178
+ Version must be valid semver (e.g., `1.0.0`, not `1.0` or `v1.0.0`).
179
+
180
+ ### "minLength" (description)
181
+ Description must be at least 10 characters.
182
+
183
+ ### "enum" (type)
184
+ Type must be one of the allowed values. Check for typos.
185
+
186
+ ### "oneOf" (files)
187
+ Files array must be consistently either all strings OR all objects, not mixed.
188
+
189
+ ### "format" (email/uri)
190
+ Email or URL is not in valid format. Check for typos and ensure proper formatting.
191
+
192
+ ## Related Files
193
+
194
+ - **Validator**: `../src/core/schema-validator.ts`
195
+ - **Tests**: `../src/__tests__/schema-validator.test.ts`
196
+ - **Publish Command**: `../src/commands/publish.ts`
197
+ - **Documentation**: `../docs/enhanced-manifest.md`
@@ -0,0 +1,307 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://prpm.dev/schemas/manifest.json",
4
+ "title": "PRPM Package Manifest",
5
+ "description": "Schema for PRPM package manifest (prpm.json)",
6
+ "type": "object",
7
+ "required": ["name", "version", "description", "type"],
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "Package name in format: package-name or @scope/package-name",
12
+ "pattern": "^(@[a-z0-9-]+\\/)?[a-z0-9-]+$",
13
+ "minLength": 1,
14
+ "maxLength": 214,
15
+ "examples": [
16
+ "react-rules",
17
+ "@community/testing-skills",
18
+ "@company/cursor-rules"
19
+ ]
20
+ },
21
+ "version": {
22
+ "type": "string",
23
+ "description": "Semantic version (semver)",
24
+ "pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$",
25
+ "examples": ["1.0.0", "2.1.3", "1.0.0-beta.1"]
26
+ },
27
+ "description": {
28
+ "type": "string",
29
+ "description": "Package description",
30
+ "minLength": 10,
31
+ "maxLength": 500
32
+ },
33
+ "type": {
34
+ "type": "string",
35
+ "description": "Package type. Use 'collection' only if files contain multiple distinct types.",
36
+ "enum": [
37
+ "cursor",
38
+ "claude",
39
+ "claude-skill",
40
+ "claude-agent",
41
+ "claude-slash-command",
42
+ "continue",
43
+ "windsurf",
44
+ "generic",
45
+ "collection"
46
+ ]
47
+ },
48
+ "author": {
49
+ "description": "Package author",
50
+ "oneOf": [
51
+ {
52
+ "type": "string",
53
+ "examples": ["John Doe", "Jane Smith"]
54
+ },
55
+ {
56
+ "type": "object",
57
+ "required": ["name"],
58
+ "properties": {
59
+ "name": {
60
+ "type": "string",
61
+ "description": "Author name"
62
+ },
63
+ "email": {
64
+ "type": "string",
65
+ "format": "email",
66
+ "description": "Author email"
67
+ },
68
+ "url": {
69
+ "type": "string",
70
+ "format": "uri",
71
+ "description": "Author URL"
72
+ }
73
+ }
74
+ }
75
+ ]
76
+ },
77
+ "license": {
78
+ "type": "string",
79
+ "description": "SPDX license identifier",
80
+ "examples": ["MIT", "Apache-2.0", "GPL-3.0", "BSD-3-Clause"]
81
+ },
82
+ "repository": {
83
+ "type": "string",
84
+ "format": "uri",
85
+ "description": "Repository URL",
86
+ "examples": ["https://github.com/username/repo"]
87
+ },
88
+ "homepage": {
89
+ "type": "string",
90
+ "format": "uri",
91
+ "description": "Package homepage URL"
92
+ },
93
+ "documentation": {
94
+ "type": "string",
95
+ "format": "uri",
96
+ "description": "Documentation URL"
97
+ },
98
+ "tags": {
99
+ "type": "array",
100
+ "description": "Package tags for categorization",
101
+ "items": {
102
+ "type": "string"
103
+ },
104
+ "maxItems": 10,
105
+ "uniqueItems": true,
106
+ "examples": [["productivity", "coding"], ["testing", "quality"]]
107
+ },
108
+ "keywords": {
109
+ "type": "array",
110
+ "description": "Search keywords",
111
+ "items": {
112
+ "type": "string"
113
+ },
114
+ "maxItems": 20,
115
+ "uniqueItems": true,
116
+ "examples": [["ai", "prompts", "development"]]
117
+ },
118
+ "category": {
119
+ "type": "string",
120
+ "description": "Package category",
121
+ "examples": ["development", "productivity", "testing"]
122
+ },
123
+ "files": {
124
+ "description": "Files to include in package. Can be simple paths or enhanced file objects with metadata.",
125
+ "oneOf": [
126
+ {
127
+ "type": "array",
128
+ "description": "Simple format: array of file paths",
129
+ "items": {
130
+ "type": "string"
131
+ },
132
+ "minItems": 1,
133
+ "examples": [
134
+ ["skill.md", "README.md"],
135
+ [".cursor/rules/react.mdc", "LICENSE"]
136
+ ]
137
+ },
138
+ {
139
+ "type": "array",
140
+ "description": "Enhanced format: array of file objects with metadata",
141
+ "items": {
142
+ "type": "object",
143
+ "required": ["path", "type"],
144
+ "properties": {
145
+ "path": {
146
+ "type": "string",
147
+ "description": "Relative path to file",
148
+ "examples": [
149
+ ".claude/skills/tdd.md",
150
+ ".cursor/rules/react.mdc",
151
+ ".continue/rules/python.json"
152
+ ]
153
+ },
154
+ "type": {
155
+ "type": "string",
156
+ "description": "File type (determines where it will be installed)",
157
+ "enum": [
158
+ "cursor",
159
+ "claude",
160
+ "claude-skill",
161
+ "claude-agent",
162
+ "claude-slash-command",
163
+ "continue",
164
+ "windsurf",
165
+ "generic"
166
+ ]
167
+ },
168
+ "name": {
169
+ "type": "string",
170
+ "description": "Display name for this file",
171
+ "examples": ["React Rules", "Test-Driven Development"]
172
+ },
173
+ "description": {
174
+ "type": "string",
175
+ "description": "Description of what this file does"
176
+ },
177
+ "tags": {
178
+ "type": "array",
179
+ "description": "File-specific tags",
180
+ "items": {
181
+ "type": "string"
182
+ },
183
+ "uniqueItems": true,
184
+ "examples": [["react", "typescript"], ["testing", "tdd"]]
185
+ }
186
+ },
187
+ "additionalProperties": false
188
+ },
189
+ "minItems": 1
190
+ }
191
+ ]
192
+ },
193
+ "main": {
194
+ "type": "string",
195
+ "description": "Main entry file (for single-file packages)",
196
+ "examples": ["index.md", "skill.md"]
197
+ },
198
+ "dependencies": {
199
+ "type": "object",
200
+ "description": "Package dependencies",
201
+ "patternProperties": {
202
+ "^(@[a-z0-9-]+\\/)?[a-z0-9-]+$": {
203
+ "type": "string",
204
+ "pattern": "^(\\^|~)?\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$"
205
+ }
206
+ },
207
+ "additionalProperties": false,
208
+ "examples": [
209
+ {
210
+ "@pr-pm/utils": "^1.0.0",
211
+ "common-rules": "~2.1.0"
212
+ }
213
+ ]
214
+ },
215
+ "peerDependencies": {
216
+ "type": "object",
217
+ "description": "Peer dependencies (packages that should be installed alongside)",
218
+ "patternProperties": {
219
+ "^(@[a-z0-9-]+\\/)?[a-z0-9-]+$": {
220
+ "type": "string"
221
+ }
222
+ },
223
+ "additionalProperties": false
224
+ },
225
+ "engines": {
226
+ "type": "object",
227
+ "description": "Required engine versions",
228
+ "properties": {
229
+ "prpm": {
230
+ "type": "string",
231
+ "description": "Required PRPM version"
232
+ },
233
+ "node": {
234
+ "type": "string",
235
+ "description": "Required Node.js version"
236
+ }
237
+ },
238
+ "additionalProperties": false,
239
+ "examples": [
240
+ {
241
+ "prpm": ">=1.0.0",
242
+ "node": ">=18.0.0"
243
+ }
244
+ ]
245
+ }
246
+ },
247
+ "additionalProperties": false,
248
+ "examples": [
249
+ {
250
+ "name": "@username/simple-package",
251
+ "version": "1.0.0",
252
+ "description": "A simple package with basic files",
253
+ "type": "claude-skill",
254
+ "author": "Your Name",
255
+ "license": "MIT",
256
+ "files": ["skill.md", "README.md"]
257
+ },
258
+ {
259
+ "name": "@username/cursor-rules",
260
+ "version": "1.0.0",
261
+ "description": "Multiple Cursor rules for different languages",
262
+ "type": "cursor",
263
+ "author": {
264
+ "name": "Your Name",
265
+ "email": "you@example.com"
266
+ },
267
+ "license": "MIT",
268
+ "repository": "https://github.com/username/cursor-rules",
269
+ "tags": ["cursor", "rules", "multi-language"],
270
+ "files": [
271
+ {
272
+ "path": ".cursor/rules/typescript.mdc",
273
+ "type": "cursor",
274
+ "name": "TypeScript Rules",
275
+ "tags": ["typescript", "frontend"]
276
+ },
277
+ {
278
+ "path": ".cursor/rules/python.mdc",
279
+ "type": "cursor",
280
+ "name": "Python Rules",
281
+ "tags": ["python", "backend"]
282
+ }
283
+ ]
284
+ },
285
+ {
286
+ "name": "@community/testing-suite",
287
+ "version": "2.0.0",
288
+ "description": "Complete testing suite with skills and agents",
289
+ "type": "collection",
290
+ "author": "Community",
291
+ "license": "MIT",
292
+ "tags": ["testing", "quality"],
293
+ "files": [
294
+ {
295
+ "path": ".claude/skills/tdd.md",
296
+ "type": "claude-skill",
297
+ "name": "Test-Driven Development"
298
+ },
299
+ {
300
+ "path": ".claude/agents/test-generator.md",
301
+ "type": "claude-agent",
302
+ "name": "Test Generator"
303
+ }
304
+ ]
305
+ }
306
+ ]
307
+ }