claude-hook-writer
Expert guidance for writing secure, reliable, and performant Claude Code hooks - validates design decisions, enforces best practices, and prevents common pitfalls
pulumi-troubleshooting
Comprehensive guide to troubleshooting Pulumi TypeScript errors, infrastructure issues, and best practices - covers common errors, Outputs handling, AWS Beanstalk deployment, and cost optimization
Full skill instructions
Cause: TypeScript infers a type as never when working with Pulumi Outputs, especially with arrays.
Solution: Wrap the value in pulumi.output() and properly type the callback:
// ❌ Bad - TypeScript can't infer the type
value: pulumi.all(config.vpc.publicSubnets.map((s: any) => s.id))
// ✅ Good - Explicitly wrap and type
value: pulumi.output(config.vpc.publicSubnets).apply((subnets: any[]) =>
pulumi.all(subnets.map((s: any) => s.id)).apply(ids => ids.join(","))
)
Cause: TypeScript doesn't allow export statements inside if blocks.
Solution: Use optional chaining for conditional exports:
// ❌ Bad
if (opensearch) {
export const opensearchEndpoint = opensearch.endpoint;
}
// ✅ Good
export const opensearchEndpoint = opensearch?.endpoint;
Cause: Pulumi.yaml config with namespaced keys (e.g., aws:region) cannot use default attribute.
Solution: Remove the config section or don't set defaults for provider configs:
# ❌ Bad
config:
aws:region:
description: AWS region
default: us-east-1
# ✅ Good - set via workflow/CLI instead
config:
app:domainName:
description: Domain name
Cause: Pulumi stack doesn't exist yet in new environments.
Solution: Use || operator to create if not exists:
pulumi stack select $STACK || pulumi stack init $STACK
Key Concepts:
pulumi.Output<T> is a promise-like wrapper for async values.apply() to transform Output valuespulumi.all([...]) to combine multiple Outputspulumi.output(value) to wrap plain values as OutputsCommon Patterns:
// Transforming a single Output
const url = endpoint.apply(e => `https://${e}`);
// Combining multiple Outputs
const connectionString = pulumi.all([host, port, db]).apply(
([h, p, d]) => `postgres://${h}:${p}/${d}`
);
// Interpolating Outputs
const message = pulumi.interpolate`Server at ${endpoint}:${port}`;
Nested Outputs (Properties that are themselves Outputs):
// ❌ Bad - resource.property might be an Output<string>
const endpoint = instance.apply(i => i.endpoint.split(":")[0]); // ERROR: Property 'split' does not exist
// ✅ Good - unwrap nested Output with pulumi.output()
const endpoint = instance.apply(i =>
pulumi.output(i.endpoint).apply(e => e.split(":")[0])
);
// ✅ Alternative - use pulumi.all to flatten
const endpoint = pulumi.all([instance]).apply(([inst]) =>
pulumi.output(inst.endpoint).apply(e => e.split(":")[0])
);
Issue: Complex objects or arrays need to be serialized.
Solution: Use JSON.stringify for complex values:
{
namespace: "aws:elasticbeanstalk:application:environment",
name: "ALLOWED_ORIGINS",
value: allowedOrigins.apply(origins => JSON.stringify(origins)),
}
Issue: Certificate validation hangs or times out.
Solution: Ensure DNS records are created and wait for validation:
// 1. Create certificate
const cert = new aws.acm.Certificate(...);
// 2. Create DNS validation record
const validationRecord = new aws.route53.Record(..., {
name: cert.domainValidationOptions[0].resourceRecordName,
type: cert.domainValidationOptions[0].resourceRecordType,
records: [cert.domainValidationOptions[0].resourceRecordValue],
});
// 3. Wait for validation to complete
const validation = new aws.acm.CertificateValidation(..., {
certificateArn: cert.arn,
validationRecordFqdns: [validationRecord.fqdn],
});
Best Practices:
- name: Setup Pulumi
uses: pulumi/actions@v5
- name: Configure Stack
run: |
STACK="${{ inputs.stack || 'prod' }}"
pulumi stack select $STACK || pulumi stack init $STACK
pulumi config set aws:region ${{ env.AWS_REGION }}
# Set other non-secret configs here
- name: Pulumi Up
run: pulumi up --yes --non-interactive
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
PULUMI_CONFIG_PASSPHRASE: ${{ secrets.PULUMI_CONFIG_PASSPHRASE }}
Quick checks:
npm run build in the infra package locally.map() calls on potentially undefined arraysBeanstalk vs ECS Fargate:
npm run build locally to catch TypeScript errorspulumi preview before pulumi up// Database
DATABASE_URL: pulumi.interpolate`postgres://${user}:${pass}@${host}:5432/${db}`
// Redis
REDIS_URL: redisEndpoint.apply(e => `redis://${e}:6379`)
// S3
S3_BUCKET: bucketName
S3_REGION: region
// Auth
GITHUB_CLIENT_ID: clientId
GITHUB_CLIENT_SECRET: clientSecret
// App Config
NODE_ENV: "production"
PORT: "8080"
LOG_LEVEL: "info"
Expert guidance for writing secure, reliable, and performant Claude Code hooks - validates design decisions, enforces best practices, and prevents common pitfalls
Use when creating GitHub Copilot instructions - provides repository-wide and path-specific formats, applyTo patterns, excludeAgent options, and natural language markdown style
Use when creating OpenCode agents - provides markdown format with YAML frontmatter, mode/tools/permission configuration, and best practices for specialized AI assistants
This is the meta skill for writing skills themselves.
This is a Claude skill for testing multi-package publishing.
Use when creating, improving, or troubleshooting Claude Code slash commands. Expert guidance on command structure, arguments, frontmatter, tool permissions, and best practices for building effective custom commands.
Use when the user requests a repository review, code assessment, or honest evaluation of their codebase. Provides brutally honest AI-powered reviews with market-aware Karen Scores (0-100) analyzing over-engineering, completion honesty, and practical value. Available as GitHub Action or IDE tool.
Use when creating Windsurf rules - provides plain markdown format with NO frontmatter, 12,000 character limit, and single-file structure requirements
Use when setting up npm publishing with GitHub Actions - provides trusted publishing with OIDC, provenance attestations, and monorepo configuration
Use when creating or improving Claude Code agents. Expert guidance on agent file structure, frontmatter, persona definition, tool access, model selection, and validation against schema.
Write content that sounds natural, conversational, and authentically human - avoiding AI-generated patterns, corporate speak, and generic phrasing
Use when deploying Node.js applications to AWS Elastic Beanstalk or troubleshooting deployment issues - provides dependency installation strategies, monorepo handling, and deployment best practices
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience