소스 정보
- 저장소
- marvinrichter/clarc
- 최근 소스 활동
- 2026년 3월 11일 16:57
- 감지된 SKILL.md 언어
- 영어
- 스타
- 14
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
SOC 직업 분류 기준
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/marvinrichter/clarc --skill iac-modern-patterns명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
Interactive installer for clarc — guides users through selecting and installing skills and rules to user-level or project-level directories, verifies paths, and optionally optimizes installed files.
Create zero-dependency, animation-rich HTML presentations from scratch or by converting PowerPoint/PPTX files. Use when the user wants to build a presentation, convert a deck to web, or create slides for a talk/pitch.
Create zero-dependency, animation-rich HTML presentations from scratch or by converting PowerPoint/PPTX files. Use when the user wants to build a presentation, convert a deck to web, or create slides for a talk/pitch.
| Capability | Terraform HCL | Pulumi / CDK |
|---|---|---|
| Real programming language | ❌ | ✅ |
| Loops & conditionals | ⚠️ for_each, count | ✅ Native |
| Unit testing | ❌ | ✅ |
| Type safety | ❌ | ✅ (TypeScript) |
| IDE autocomplete | ❌ | ✅ |
| Reusable abstractions | Modules (limited) | Classes / Components |
| Multi-cloud | ✅ | ✅ (Pulumi) / ❌ (CDK = AWS only) |
| Existing provider ecosystem | ✅ Largest | ✅ (Pulumi) / ⚠️ (CDK) |
When to use Terraform still: large multi-cloud org with existing HCL expertise, team prefers DSL simplicity, need Terraform Cloud governance features.
// index.ts — `pulumi up` diffs desired vs current state, then applies
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const config = new pulumi.Config();
const environment = config.require("environment"); // dev / staging / prod
const dbInstanceClass = config.get("dbInstanceClass")
?? (environment === "prod" ? "db.t3.large" : "db.t3.micro");
const bucket = new aws.s3.Bucket("uploads", {
bucket: `myapp-uploads-${environment}`,
versioning: { enabled: true },
serverSideEncryptionConfiguration: {
rule: { applyServerSideEncryptionByDefault: { sseAlgorithm: "AES256" } },
},
tags: { Environment: environment, ManagedBy: "pulumi" },
});
export const bucketName = bucket.bucket;
export const bucketArn = bucket.arn;
// Async outputs — use pulumi.interpolate / pulumi.all instead of string templates
const url = pulumi.interpolate`https://${bucket.bucketDomainName}/uploads`;
const conn = pulumi.all([db.endpoint, db.name, dbPassword]).apply(
([ep, name, pw]) => `postgresql://app:${pw}@${ep}:5432/${name}`
);
pulumi stack init dev && pulumi stack init prod
pulumi config set environment dev
pulumi config set aws:region eu-west-1
pulumi config set --secret dbPassword "$(openssl rand -base64 32)"
pulumi preview # like terraform plan
pulumi up # deploy
pulumi stack select prod
// components/WebService.ts
export class WebService extends pulumi.ComponentResource {
public readonly url: pulumi.Output<string>;
constructor(name: string, args: { image: string; port: number; desiredCount?: number },
opts?: pulumi.ComponentResourceOptions) {
super("myapp:index:WebService", name, {}, opts);
const cluster = new aws.ecs.Cluster(`${name}-cluster`, {}, { parent: this });
const lb = new awsx.lb.ApplicationLoadBalancer(`${name}-lb`, {}, { parent: this });
const service = new awsx.ecs.FargateService(`${name}-svc`, {
cluster: cluster.arn,
taskDefinitionArgs: {
container: { name, image: args.image, : , : ,
: [{ : args. }] },
},
: args. ?? ,
: [{ : lb..,
: name, : args. }],
}, { : });
. = lb...( );
.({ : . });
}
}
api = (, { : , : });
apiUrl = api.;
import { PolicyPack, validateResourceOfType } from "@pulumi/policy";
import * as aws from "@pulumi/aws";
new PolicyPack("aws-policies", {
policies: [{
name: "s3-no-public-access",
enforcementLevel: "mandatory",
validateResource: validateResourceOfType(aws.s3.Bucket, (bucket, _args, reportViolation) => {
if (bucket.acl === "public-read" || bucket.acl === "public-read-write")
reportViolation("S3 bucket must not be public");
}),
}, {
name: "require-tags",
enforcementLevel: "mandatory",
validateResource: (args, reportViolation) => {
const tags = args.props.tags ?? {};
if (!tags.Environment) reportViolation("Missing tag: Environment");
if (!tags.ManagedBy) reportViolation("Missing tag: ManagedBy");
},
}],
});
App
└── Stack (prod, us-east-1)
├── VpcConstruct (L2 — sensible defaults)
├── EcsServiceConstruct (L3 — your reusable pattern)
└── DatabaseConstruct (L3 — your reusable pattern)
Construct levels: L1 = raw CloudFormation wrappers, L2 = sane defaults + IAM helpers, L3 = your organisation's opinionated patterns.
import * as cdk from "aws-cdk-lib";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns";
import { Construct } from "constructs";
export class AppStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const bucket = new s3.Bucket(this, "Uploads", {
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
removalPolicy: cdk..,
});
vpc = ec2.(, , { : , : });
service = ecs_patterns.(, , {
vpc,
: ,
: ,
: ,
: {
: ecs..(),
: ,
: { : },
},
});
bucket.(service..);
}
}
// constructs/WebService.ts
export interface WebServiceProps {
vpc: ec2.IVpc;
image: string;
port: number;
cpu?: number;
memoryMiB?: number;
desiredCount?: number;
environment?: Record<string, string>;
}
export class WebService extends Construct {
public readonly service: ecs_patterns.ApplicationLoadBalancedFargateService;
public readonly url: string;
constructor(scope: Construct, id: string, props: WebServiceProps) {
super(scope, id);
this.service = new ecs_patterns.ApplicationLoadBalancedFargateService(this, "Service", {
vpc: props.vpc,
cpu: props.cpu ?? 256,
: props. ?? ,
: props. ?? ,
: {
: ecs..(props.),
: props.,
: props.,
},
});
. = ;
}
}
// Enforce encryption on every S3 bucket in the app tree
export class RequireEncryption implements cdk.IAspect {
public visit(node: IConstruct): void {
if (node instanceof s3.CfnBucket && !node.bucketEncryption)
cdk.Annotations.of(node).addError("S3 bucket must have encryption configured");
}
}
cdk.Aspects.of(app).add(new RequireEncryption());
import { Template, Match } from "aws-cdk-lib/assertions";
const template = Template.fromStack(new AppStack(new App(), "Test"));
template.hasResourceProperties("AWS::S3::Bucket", {
VersioningConfiguration: { Status: "Enabled" },
PublicAccessBlockConfiguration: { BlockPublicAcls: true, RestrictPublicBuckets: true },
});
const services = template.findResources("AWS::ECS::Service");
const minCount = Math.min(...Object.values(services).map((s: any) => s.Properties.DesiredCount));
expect(minCount).toBeGreaterThanOrEqual(2);
// main.bicep
param environment string = 'dev'
param location string = resourceGroup().location
var storageAccountName = 'myapp${environment}${uniqueString(resourceGroup().id)}'
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location
sku: {
name: environment == 'prod' ? 'Standard_ZRS' : 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
minimumTlsVersion: 'TLS1_2'
supportsHttpsTrafficOnly: true
allowBlobPublicAccess: false
}
}
output storageAccountName string = storageAccount.name
output storageAccountId string = storageAccount.id
# Deploy Bicep
az deployment group create \
--resource-group myapp-prod \
--template-file main.bicep \
--parameters environment=prod
Use when you need Terraform providers (non-AWS) but want TypeScript/Python instead of HCL.
// main.ts
import { App, TerraformStack, TerraformOutput } from "cdktf";
import { AwsProvider } from "@cdktf/provider-aws/lib/provider";
import { S3Bucket } from "@cdktf/provider-aws/lib/s3-bucket";
class MyStack extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id);
new AwsProvider(this, "AWS", { region: "eu-west-1" });
const bucket = new S3Bucket(this, "uploads", {
bucket: "myapp-uploads-prod",
versioning: { enabled: true },
tags: { Environment: "prod", ManagedBy: "cdktf" },
});
new TerraformOutput(this, "bucket_name", { value: bucket. });
}
}
app = ();
(app, );
app.();
cdktf deploy # terraform apply equivalent
cdktf destroy # terraform destroy equivalent
cdktf synth # generate Terraform JSON config
# dev stack
pulumi config set --stack dev environment dev
pulumi config set --stack dev instanceType t3.micro
pulumi config set --stack dev desiredCount 1
# prod stack
pulumi config set --stack prod environment prod
pulumi config set --stack prod instanceType t3.large
pulumi config set --stack prod desiredCount 3
// index.ts — single program, multiple stack configs
const config = new pulumi.Config();
const environment = config.require("environment");
const instanceType = config.get("instanceType") ?? "t3.micro";
const desiredCount = config.getNumber("desiredCount") ?? 1;
// All resources automatically namespaced by stack
// bin/app.ts
const app = new cdk.App();
new AppStack(app, "Dev", {
env: { account: "111111111", region: "eu-west-1" },
instanceType: "t3.micro",
desiredCount: 1,
});
new AppStack(app, "Prod", {
env: { account: "222222222", region: "eu-west-1" },
instanceType: "t3.large",
desiredCount: 3,
});
# CDK: test generated CloudFormation
cdk synth > /tmp/template.json
conftest test /tmp/template.json --policy policy/
# Pulumi: test generated resources
pulumi preview --json | conftest test - --policy policy/
# policy/s3.rego
package main
deny[msg] {
resource := input.Resources[_]
resource.Type == "AWS::S3::Bucket"
not resource.Properties.BucketEncryption
msg := sprintf("S3 bucket '%v' must have encryption configured", [resource])
}
# Pulumi: detect drift
pulumi refresh --expect-no-changes
# CDK: detect drift (via CloudFormation)
aws cloudformation detect-stack-drift --stack-name MyStack
aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id DETECTION_ID
// .projenrc.ts (using projen)
import { awscdk } from "projen";
const project = new awscdk.AwsCdkConstructLibrary({
author: "Your Name",
authorAddress: "you@example.com",
cdkVersion: "2.0.0",
defaultReleaseBranch: "main",
name: "@myorg/web-service-construct",
repositoryUrl: "https://github.com/myorg/web-service-construct",
// Automatically publishes to npm, PyPI, Maven, NuGet
publishToNpm: true,
publishToPypi: { distName: "myorg.web-service-construct", module: "myorg_web_service_construct" },
});
project.synth();
terraform-patterns — Terraform HCL patterns with cross-reference to when to choose Pulumi/CDKkubernetes-patterns — deploying to Kubernetes with Pulumi/CDK generated manifestsdevsecops-patterns — OPA/Conftest integration into IaC CI pipelineci-cd-patterns — GitHub Actions for IaC deployment pipelines