neuron-explorer
Qwen3.5‑4B 전용 조향형 뉴런 탐색기, 모든 MLP 뉴런을 밀어 결과를 보관·탐색
Dart로 클라우드 인프라를 작성·배포하고, Flutter 앱에서 타입이 지정된 Dart로 결과를 읽는다
Write cloud infrastructure as Dart for Google Cloud, AWS, Cloudflare and Appwrite, apply it with one command, and read its outputs in your Flutter app as typed Dart.
개발 도구Dart · JavaScriptGitHub @nozomi-koborinai온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
🎯 Type-safe IaC for Dart.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Type-safe IaC for Dart.
Write your infrastructure and your app in one typed Dart codebase. TerraDart synthesizes Terraform JSON for Google Cloud, AWS, Cloudflare and Appwrite, and hands the values your app needs — topic names, IDs, URLs — to it as typed Dart instead of copied strings. The terradart command plans and applies it with OpenTofu, and you never install Terraform.
Alpha — no SemVer until v1.0.0, but breaking changes land only on minor bumps. Pin ^0.35.0, read MIGRATING.md before minor bumps, and see status on terradart.dev.README 전문 보기 ↗Type-safe IaC for Dart.
Write your infrastructure and your app in one typed Dart codebase. TerraDart synthesizes Terraform JSON for Google Cloud, AWS, Cloudflare, Appwrite and Azure, and hands the values your app needs — topic names, IDs, URLs — to it as typed Dart instead of copied strings. The
terradartcommand plans and applies it with OpenTofu, and you never install Terraform.
Alpha is where TerraDart gets into people's hands and their feedback shapes the API. There is no SemVer until v1.0.0. Breaking changes land only on minor bumps. Pin ^0.35.0, read MIGRATING.md before a minor bump, and see status on terradart.dev.
# pubspec.yaml
name: my_app
environment:
sdk: ^3.10.0
dependencies:
terradart_core: ^0.35.0
terradart_google: ^0.35.0 # or terradart_aws / terradart_azure / terradart_cloudflare / terradart_appwrite
A Stack is one Terraform root module, written as a Dart class. This one runs an API on Cloud Run that publishes to a Pub/Sub topic, and tells the app which topic that is:
// docs:pitch:start
// lib/orders_stack.dart
import 'package:terradart_google/cloud_run.dart';
import 'package:terradart_google/iam.dart';
import 'package:terradart_google/provider.dart';
import 'package:terradart_google/pubsub.dart';
final class OrdersStack extends Stack {
OrdersStack({required String projectId})
: super(
providers: [GoogleProvider(project: projectId, region: 'asia-northeast1')],
appExports: AppExports('lib/generated/orders_stack.app.dart'),
) {
final orders = add(GooglePubsubTopic('orders', name: .literal('orders')));
final apiSa = add(GoogleServiceAccount('api', accountId: .literal('orders-api')));
add(GooglePubsubTopicIamMember(
'api_publishes_orders',
topic: orders.ref, // only a GooglePubsubTopic fits here
role: .literal('roles/pubsub.publisher'),
member: apiSa.principal,
));
// Typed in the app: a constant now, an output after apply.
addConstant('ordersTopic', .ref(orders.name));
addOutput('orders_topic_id', orders.id);
final api = add(GoogleCloudRunV2Service(
'api',
name: .literal('orders-api'),
location: .literal('asia-northeast1'),
ingress: .all, // an enum, not a string
template: CloudRunV2ServiceTemplate(
serviceAccount: apiSa.ref,
containers: [
.new(
image: .literal('us-docker.pkg.dev/my-project/app/orders-api'),
env: [
for (final (:name, :value) in outputEnvironment())
.new(name: .literal(name), source: .value(value)),
],
),
],
),
));
// Pub/Sub pushes as its own service account, which may invoke the API.
final pushSa = add(GoogleServiceAccount('push', accountId: .literal('orders-push')));
add(GoogleCloudRunV2ServiceIamMember(
'push_invokes_api',
service: api.ref, // emits the service's name, location and project
role: .literal('roles/run.invoker'),
member: pushSa.principal,
));
add(GooglePubsubSubscription(
'orders_push',
name: .literal('orders-push'),
topic: orders.ref,
// A sealed choice: push, BigQuery or Cloud Storage — exactly one.
delivery: .pushConfig(.new(
pushEndpoint: api.uri,
oidcToken: .new(serviceAccountEmail: pushSa.ref),
)),
));
}
}
// docs:pitch:end
The app imports the file synth generates. Constants are plain Dart; outputs are read from the environment the Stack gave the service:
// lib/orders_api.dart
import 'dart:io';
import 'generated/orders_stack.app.dart';
/// The topic this service publishes to, passed in as ORDERS_TOPIC_ID.
String ordersTopicId() =>
OrdersStackOutputs.fromEnvironment(Platform.environment).ordersTopicId;
/// Whether a pushed message came from the orders topic.
bool fromOrders(String topicName) => topicName == OrdersStackConstants.ordersTopic;
// bin/infra.dart
import 'package:my_app/orders_stack.dart';
import 'package:terradart_core/terradart_core.dart';
Future<void> main(List<String> args) =>
runStack(args, () => OrdersStack(projectId: 'my-project'));
dart pub get
dart pub global activate terradart_cli
terradart apply
terradart apply runs bin/infra.dart, which writes tf-out/main.tf.json and lib/generated/orders_stack.app.dart, then init and apply in tf-out/ with the tofu or terraform on your PATH — or a checksum-verified OpenTofu it downloads when there is neither. terradart plan, destroy and outputs work the same way; environments are a Dart enum bin/infra.dart hands to runEnvironments (terradart apply --env prod), and a Stack with addDartDefineOutput() gets the define file a Flutter client builds with. See The terradart command, Environments and Outputs in client apps.
Already have tofu or terraform installed, or a pipeline that runs one? terradart uses the engine on your PATH (--engine picks one), and tf-out/ is standard Terraform JSON any of them can apply. The default path is still the terradart command, which needs neither.
What the compiler now checks for you:
ref (topic: orders.ref, serviceAccount: apiSa.ref) and picks the attribute it emits; passing a bucket where a topic belongs does not compile. Every attribute also has a plain getter (orders.name, apiSa.email) that is itself a TfArg, so it passes straight into any argument of its type..all, .pushConfig(...), .value(...). A typo or a second delivery mode is a compile error, not a failed plan.OrdersStackConstants.ordersTopic follows on the next synth; remove the output and ordersTopicId stops compiling. outputEnvironment() passes every output to the service, so no variable name is written twice. A Flutter or web client gets the same variables at build time: addDartDefineOutput() declares the file --dart-define-from-file reads (terradart apply and terradart outputs write it to .terradart/dart_defines.json), and const OrdersStackOutputs.fromDartDefine() reads it — see Outputs in client apps.bin/infra.dart running; terradart only runs it and then the engine.Runnable versions: examples/pubsub_quickstart, examples/flutter_client_quickstart (a Flutter app reading typed outputs after terradart apply --env dev), and the single-project-app cookbook recipe (Cloud Run + Cloud SQL + the app). Full walkthrough: Getting started.
Pick the form by where the value comes from. The argument's type tells you which forms it takes, and a dot shorthand (.literal, .new, .providedAl2023) names the constructor of that type.
| The value is | Write | Example |
|---|---|---|
| known when you synth | .literal(...) | functionName: .literal('hello') |
another resource of this Stack (a RefTo<R> input) | its ref | role: role.ref |
| one attribute of another block | its getter | assumeRolePolicy: trust.json |
a resource outside this Stack (a RefTo<R> input) | .literal(id) | zoneId: .literal('023e105f4ecef8ad9ca31a8372d0c353') |
| one of a fixed set (an enum) | the member | runtime: .providedAl2023 |
| one of several exclusive arguments (a sealed type) | the variant | code: .filename(.literal('build/fn.zip')) |
| a nested block | its helper class; .new(...) inside another block or a variant | environment: LambdaFunctionEnvironment(...) |
| a Terraform variable | the handle variable<T>() returns | memorySize: memory |
a variable in an enum or RefTo<R> input | .arg(handle) | runtime: .arg(runtimeName) |
a secret (a Sensitive<T> input) | a sensitive variable, never a literal | value: .value(dbPassword) |
| a reference inside a literal list or map | the getter's .interpolation | {'ROLE_ARN': role.arn.interpolation} |
| anything else Terraform evaluates | .expression(...) | .expression(r'${file("trust.json")}') |
final memory = variable<num>('memory_mb');
final runtimeName = variable<String>('runtime');
final dbPassword = variable<String>('db_password', sensitive: true);
final trust = add(
DataAwsIamPolicyDocument(
'trust',
statement: [
DataIamPolicyDocumentStatement(
actions: .literal(['sts:AssumeRole']),
principals: [
.new(
type: .literal('Service'),
identifiers: .literal(['lambda.amazonaws.com']),
),
],
),
],
),
);
final role = add(AwsIamRole('hello', assumeRolePolicy: trust.json));
add(
AwsLambdaFunction(
'hello',
functionName: .literal('hello'),
role: role.ref,
runtime: .arg(runtimeName),
code: .filename(.literal('build/fn.zip')),
memorySize: memory,
environment: LambdaFunctionEnvironment(
variables: .literal({'ROLE_ARN': role.arn.interpolation}),
),
),
);
add(
AwsSsmParameter(
'db_password',
name: .literal('/hello/db_password'),
type: .securestring,
value: .value(dbPassword),
),
);
More on each row: Writing arguments.
Each package wraps an official Terraform provider: one generated factory per resource and data source, with the provider's own docs, enums and exclusive groups.
| Package | Terraform provider | Catalog | Pub |
|---|---|---|---|
terradart_google | hashicorp/google | 1380 curated resource factories + 472 data sources (1852 catalog entries) | |
terradart_google_beta | hashicorp/google-beta | the beta-only types (112 resource factories); everything also in GA stays in terradart_google | |
terradart_aws | hashicorp/aws | every resource and data source at the pinned provider version | |
terradart_azure | hashicorp/azurerm | every resource and data source at the pinned provider version | |
All of them build on terradart_core (): Stack, Resource, Data, TfArg, RefTo and synth. One Stack can mix providers — this one puts a Cloudflare zone in front of the Cloud Run service:
// lib/edge_stack.dart
import 'package:terradart_cloudflare/dns.dart';
import 'package:terradart_cloudflare/provider.dart';
import 'package:terradart_cloudflare/zone.dart';
final class EdgeStack extends Stack {
EdgeStack({required String accountId}) : super(providers: [const CloudflareProvider()]) {
final zone = add(CloudflareZone(
'main',
name: .literal('example.com'),
account: ZoneAccount(id: .literal(accountId)),
));
add(CloudflareDnsRecord(
'api',
zoneId: zone.ref,
name: .literal('api.example.com'),
type: .cname,
ttl: .literal(1),
content: .content(.literal('ghs.googlehosted.com')),
proxied: .literal(true),
));
}
}
Credentials never enter the synthesized JSON: each provider authenticates at apply time through its usual environment variables or credential chain. Per-provider guides: Google Cloud, AWS (Lambda, HTTP API + DynamoDB, ECS Express Mode, S3 + CloudFront), Cloudflare, Appwrite and Azure.
terradart migrate turns an existing Terraform source tree into a TerraDart package: one Stack per module directory, a tf-out/ tree mirroring the source, and a leftover sidecar beside each main.tf.json holding, verbatim and with a reason, every block it cannot translate yet. Resource addresses are preserved, so terradart plan against your existing state reports No changes — move one resource at a time, no big-bang rewrite. It reads .tf / .tf.json only: no Terraform run, no state access.
dart pub global activate terradart_cli
terradart migrate --dir infra --out infra_dart
cd infra_dart && dart pub get && terradart plan
terradart migrate --report sizes a tree without writing anything. --merge-envs folds sibling environments into one Stack, and terradart plan --env <name> runs one of them. Guide: Migrating from HCL.
| Package | What it is | Pub |
|---|---|---|
terradart_cli | The terradart command: synth, plan, apply, destroy, outputs, migrate and the client define file, with OpenTofu or Terraform. | |
terradart_migrate | The HCL → Dart migrator library (terradart migrate). | |
terradart_hcl | A pure Dart HCL / *.tf.json parser and Terraform module model — the migrator's input side. | |
terradart_codegen | The maintainer generation CLI (terradart-codegen wrap) that produces the provider packages. |
Coding agents. The factories are generated Dart committed to the provider packages, so an agent can read the exact constructor, its doc comment and a CI-validated example instead of guessing. The TerraDart Agent Skill tells it where to look (each package's lib/src/_catalog.g.dart, examples/, /llms.txt):
terradart skill install # .agents/skills/ and .claude/skills/, the skill of this CLI's release
terradart skill update keeps it in step with the CLI, and terradart skill status --check fails CI when it falls behind. Without the CLI: npx skills add nozomi-koborinai/terradart#v0.35.0 --skill terradart, pinned to the release tag.
Docs: Let an AI agent do it.
addModule(ModuleCall(...)) calls an existing Terraform module by its source, and HCL files beside the generated *.tf.json feed the same apply; TerraDart does not turn modules into Dart.How TerraDart compares with HCL, CDKTF and Pulumi: Why TerraDart.
Alpha (0.35.x) is where TerraDart gets into people's hands and their feedback shapes the API. There is no SemVer until v1.0.0. Breaking changes land only on minor bumps, each with a section in MIGRATING.md. Pin ^0.35.0 and take patch releases freely. Beta starts when the API shape is settled. The beta gates are the path to beta. 1.0.0 follows beta, after two minor releases in a row ship with no breaking changes.
See CONTRIBUTING.md. For security issues, use the GitHub private security advisory flow.
"Terraform" is a registered trademark of HashiCorp, Inc.
Dart™ and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.
TerraDart is an independent open-source project and is not affiliated with, endorsed by, or sponsored by HashiCorp or Google.
Apache-2.0. See LICENSE.
The framing draws on prior work in CDKTF (archived Dec 2025), AWS CDK, and Pulumi.
terradart_cloudflarecloudflare/cloudflare |
| every resource and data source at the pinned provider version |
terradart_appwrite | appwrite/appwrite | every resource and data source at the pinned provider version |
terradart_time | hashicorp/time | TimeSleep, the propagation wait for a stack on any provider |