NPM Deployment Guide โ
Publishing OpenPets packages to the npm registry.
๐ฆ Packages โ
Core Package โ
Name: openpetsLocation: src/core/Version: 1.0.4
Published without @ scope for simplicity.
Pet Packages โ
Scope: @openpets/Location: pets/*/
Published with scope for organization.
Examples:
@openpets/maps(v1.0.7)@openpets/email(v1.0.1)@openpets/jira@openpets/github
๐ Security Best Practices โ
2-Factor Authentication (2FA) โ
- Maintainers: Must have 2FA enabled on their npm accounts.
- Automation: Use Granular Access Tokens with "Publish" permissions restricted to the
@openpetsscope and specific IP ranges if possible. Avoid using legacy tokens.
Namespace Protection โ
Using the @openpets scope prevents "typo-squatting" attacks where malicious actors publish packages with similar names (e.g., openpets-mps vs @openpets/maps). Ensure all new plugins are added to the organization scope.
Pre-Flight Checks โ
The publishing scripts include automated security checks:
- Secret Scanning: Scans
src/for potential API keys or.envfiles before publishing. - Dependency Pinning: Workspace dependencies are resolved to specific versions to prevent supply chain drift.
- File Whitelist: Only explicitly listed files are included (index.ts, src/, commands.json, etc.).
- npmignore Template: Auto-generated
.npmignoreexcludes test files, backups, debug scripts, and sensitive files.
Environment Variable Handling โ
Pets use the standardized loadEnv() function from the openpets core package:
import { loadEnv } from "openpets"
export const MyPlugin = async () => {
const env = loadEnv("my-plugin")
const API_KEY = env.MY_API_KEY
// ...
}How loadEnv works:
- Loads from
.envfile in the project's working directory (not the package cache) - Loads from
.pets/config.jsonif it exists (pet-specific config) - Returns only project-relevant environment variables
This ensures pets never load .env from their installed cache location, and credentials are never bundled with published packages.
๐ Publishing โ
Prerequisites โ
Login to npm:
bashnpm login npm whoami # Should show: raggle_npmVerify organization access: Visit: https://www.npmjs.com/settings/openpets/packages
Publish Core Package โ
cd src/core
npm publish --access publicResult:
+ openpets@1.0.4Publish Individual Pet โ
Use the publish-pet.ts script which handles workspace dependencies, security checks, and version management:
# From repository root
bun scripts/publish-pet.ts <pet-name>
# Examples
bun scripts/publish-pet.ts maps
bun scripts/publish-pet.ts jira
bun scripts/publish-pet.ts gitlab
# Preview mode (dry-run)
bun scripts/publish-pet.ts maps --preview
# Publish to specific channel
bun scripts/publish-pet.ts maps --channel betaWhat the publish script does:
- Ensures
.npmignoreexists with secure defaults - Runs security scan for secrets/credentials
- Replaces
workspace:*dependencies with actual versions - Auto-bumps version if already published
- Applies whitelist file filter (only includes core files)
- Verifies tarball contents before publishing
- Publishes to npm registry
Result:
+ @openpets/maps@1.0.8Publish All Pets โ
# From repository root
npm run publish:petsOr manually with the script:
for pet in maps email jira gitlab slack; do
bun scripts/publish-pet.ts "$pet"
done๐งช Testing Before Publish โ
Dry Run โ
Test without actually publishing:
# Core
cd src/core
npm publish --dry-run --access public
# Pets
cd pets/maps
npm publish --dry-run --access publicPack and Inspect โ
Create a tarball to inspect what will be published:
npm pack
tar -tzf openpets-1.0.4.tgzโ๏ธ Configuration โ
package.json Settings โ
Core package (src/core/package.json):
{
"name": "openpets",
"version": "1.0.4",
"publishConfig": {
"access": "public"
},
"bin": {
"pets": "./cli.ts",
"pets-mcp": "./mcp-server.ts"
},
"files": [
"*.ts",
"*.js",
"*.d.ts",
"ai-client-base/**/*",
"!**/*.test.ts"
]
}Pet package (pets/maps/package.json):
{
"name": "@openpets/maps",
"version": "1.0.7",
"publishConfig": {
"access": "public"
}
}Note: The files array is preserved if already present, or dynamically added by publish-pet.ts during publishing to ensure a consistent whitelist approach:
{
"files": [
"index.ts",
"index.js",
"client.ts",
"client.js",
"*.d.ts",
"lib/**/*",
"src/**/*",
"commands.json",
"public/**/*",
"prompts/**/*",
"README.md"
]
}This whitelist approach ensures only core plugin files are published, automatically excluding test files, backups, and debug scripts.
๐ Files Included โ
Core Package โ
openpets@1.0.4
โโโ cli.ts (pets command)
โโโ mcp-server.ts (pets-mcp command)
โโโ index.ts
โโโ build-pet.ts
โโโ validate-pet.ts
โโโ logger.ts
โโโ ai-client-base/
โโโ ... (23 files total)Pet Package โ
@openpets/maps@1.0.7
โโโ index.ts
โโโ commands.json
โโโ opencode.json
โโโ src/
โ โโโ providers/
โ โโโ google-maps.ts
โ โโโ mapbox.ts
โ โโโ openstreetmap.ts
โโโ ... (8 files total)๐ Version Management โ
Bump Version โ
# From package directory
npm version patch # 1.0.4 -> 1.0.5
npm version minor # 1.0.4 -> 1.1.0
npm version major # 1.0.4 -> 2.0.0Using Bump Script โ
# From repository root
npm run bump๐ After Publishing โ
Verify Publication โ
# Check core package
npm view openpets
# Check pet package
npm view @openpets/maps
# Check all versions
npm view openpets versions
npm view @openpets/maps versionsTest Installation โ
# Global install
npm install -g openpets
pets --version
# Local install
npm install @openpets/mapsUpdate Distribution Files โ
After publishing to npm, update other distribution methods:
./scripts/update-openpets-checksums.shThis updates:
- Homebrew formula checksums
- PKGBUILD checksums
- Distribution templates
๐ท๏ธ NPM Tags โ
Latest (Default) โ
npm publish --access public
# Published with tag: latestBeta Release โ
npm publish --access public --tag betaUsers install with:
npm install openpets@beta
npm install @openpets/maps@betaAlpha Release โ
npm publish --access public --tag alpha๐ Access Control โ
All packages use:
{
"publishConfig": {
"access": "public"
}
}This ensures packages are publicly accessible despite being in an organization.
โ ๏ธ Common Issues โ
"Package already exists" โ
Problem: Version already published
Solution:
npm version patch
npm publish --access public"403 Forbidden" โ
Problem: Not logged in or wrong credentials
Solution:
npm logout
npm login
npm whoami # Verify: raggle_npm"Invalid package name" โ
Problem: Name has invalid characters (slashes without scope)
Solution: Use proper format:
- โ
openpets/maps - โ
@openpets/maps
"ENEEDAUTH" โ
Problem: Authentication token expired
Solution:
npm login๐ NPM Stats โ
View Package Info โ
npm info openpets
npm info @openpets/mapsDownload Stats โ
Visit:
Or use npm-stat:
npx npm-stat openpets
npx npm-stat @openpets/maps๐ Deprecate a Version โ
npm deprecate openpets@1.0.3 "Please upgrade to 1.0.4"
npm deprecate @openpets/maps@1.0.6 "Use 1.0.7 instead"๐๏ธ Unpublish (Use Carefully!) โ
Warning: Can only unpublish within 72 hours, and it affects all users.
# Unpublish specific version
npm unpublish openpets@1.0.4
# Unpublish entire package (dangerous!)
npm unpublish openpets --forceBetter alternative: Use deprecate instead.
๐ Security โ
Pre-Publish Security Scan โ
Always run security scan before publishing:
# Run security check (fails on critical issues)
npm run security:check
# Or scan with verbose output
npm run security:scan:verbose
# Scan specific pet
bun scripts/security-scan.ts --dir pets/mapsThe security scanner automatically detects:
- Sensitive files (
.env, private keys, credentials) - API keys (Google, OpenAI, GitHub, AWS, Stripe)
- Hardcoded passwords
- Database connection strings with credentials
Publishing will fail if critical issues are detected.
NPM Account Security โ
Enable 2FA (Required):
npm profile enable-2fa auth-and-writesCreate Granular Access Token:
npm token create \
--scope=@openpets \
--description="GitHub Actions Publisher" \
--expires=365dSee: Security Guide for comprehensive security documentation.
๐ Publishing Checklist โ
Before publishing:
- [ ] Preview mode passes:
bun scripts/publish-pet.ts <pet> --preview - [ ] Tests pass:
npm test - [ ] Pet uses
loadEnv()from openpets (not local dotenv) - [ ] CHANGELOG.md updated
- [ ] All changes committed
- [ ] No
.envfiles in package - [ ] No hardcoded API keys
- [ ] No test files in tarball
- [ ] 2FA enabled on npm account
- [ ] Using granular access tokens (not classic)
After publishing:
- [ ] Verify on npmjs.com
- [ ] Test installation:
npm install -g openpets - [ ] Update distribution checksums
- [ ] Create git tag
- [ ] Update documentation
- [ ] Announce release
Note: Version bumping is handled automatically by publish-pet.ts if the version already exists.
๐ก๏ธ npmignore Management โ
The ensure-npmignore.ts script maintains consistent .npmignore files across all pets:
# Ensure all pets have .npmignore
bun scripts/ensure-npmignore.ts --all
# Overwrite existing .npmignore files
bun scripts/ensure-npmignore.ts --all --force
# Single pet
bun scripts/ensure-npmignore.ts pets/mapsDefault npmignore template excludes:
- Sensitive files:
.env,*.pem,*.key,credentials*.json - Test files:
test*.ts,*.test.ts,*.spec.ts - Debug files:
debug-*.ts,diagnose-*.ts - Backup files:
*-backup.ts,*.bak - Build artifacts:
tsconfig.tsbuildinfo,*.log