terradart_cli 0.35.0 copy "terradart_cli: ^0.35.0" to clipboard
terradart_cli: ^0.35.0 copied to clipboard

The terradart command — synth, plan, apply and migrate a TerraDart Stack or an existing Terraform tree, and write outputs as a --dart-define-from-file JSON.

Changelog #

0.35.0 - 2026-10-03 #

  • Every command's --help ends with Examples: (the simplest use first, the --no-input --json form an agent runs last) and See also: topics. terradart help <topic> prints a terminal-sized guide — environments, outputs, backends, engines, migrate, exit-codes, json, agents — and terradart help --list lists them; terradart help migrate is the command's usage followed by the guide.
  • --dry-run on apply and destroy runs synth, init and plan (plan -destroy) and stops: no question, no state change, no define file. On outputs it reads the outputs and prints the define file and its keys without writing it. With --json the result has "dryRun": true and the command to run without the flag in next.
  • Breaking: the exit codes are a fixed table, whichever step fails: 1 internal, 2 plan --detailed-exitcode found changes, 3 an answer is needed, 10 the entry point failed, 11 no engine, 12 the engine failed (it used to pass the engine's own code through), 64 a usage error or missing flag, 65 a wrong terradart: section or unknown --env, 66 no pubspec.yaml. --json prints one object on stdout — schemaVersion, command, ok, exitCode, env and engine with why each is the one, outDir, the plan's add / change / destroy / replace (read from show -json of a saved plan), defineFile and keys (never the values), notices (skill_outdated, skill_newer), error (code, message, flag, choices, engineExitCode) and next — and sends the progress, the entry point's and the engine's output to stderr; it implies --no-input. plan --detailed-exitcode exits 2 when there are changes. See MIGRATING.md.
  • Breaking: terradart asks only on a terminal — stdin and stdout both one — and never when --no-input, TERRADART_NO_INPUT=1, CI, or an AI agent's shell (AI_AGENT, CURSOR_AGENT, CLAUDECODE, GEMINI_CLI, CODEX_SANDBOX, CODEX_THREAD_ID, OPENCODE) says not to. Without an answer, apply and destroy need --auto-approve and otherwise stop before init with exit code 3; state migrate and the engine-switch guard stop with 3 instead of 64; and the engine gets -input=false. On a terminal, a missing --env is a question listing the environments (env: stg (prompt)), not an error. An error that a flag would fix prints up to three lines — the message, Choices: and Next:, the failed command with the flag added (terradart plan --env dev). --quiet (-q) leaves out the values terradart picked by itself (env:, Using OpenTofu ...). See MIGRATING.md.
  • The package bundles the TerraDart Agent Skill (skills/terradart/SKILL.md) of its release. terradart skill install writes it to .agents/skills/terradart/SKILL.md and .claude/skills/terradart/SKILL.md (--agents picks agents, claude, cursor, windsurf, copilot or all); terradart skill update rewrites the installed copies and leaves one with local edits, without a marker or from a newer CLI alone unless --force (exit 5); --dry-run prints the diff. terradart skill status shows each copy as current, marker-only, outdated, newer, edited, missing or foreign, and --check exits 4 on anything but current or marker-only.
  • Each copy records terradart-version and terradart-sha256 (the content without those two lines) under metadata: in its front matter, and so does the source, so npx skills add nozomi-koborinai/terradart#v<version> --skill terradart installs the same bytes.
  • terradart init --agent-skill writes the bundled skill into the new project (--agents picks where, as for skill install); in a terminal it is the last question. Without it, the project's AGENTS.md names terradart skill install and the npx skills add line pinned to the release tag.
  • When the project's skill is older than the CLI, synth, plan, apply, destroy, outputs and engine print one line on stderr naming terradart skill update; TERRADART_NO_SKILL_NOTICE=1 turns it off.

0.34.0 - 2026-10-03 #

  • terradart validate [--env <name>] synthesizes, then runs init -backend=false and validate in the directory the entry point wrote, with the same engine as plan (managed OpenTofu when neither tofu nor terraform is on PATH). It needs no credentials, backend or state, so a CI job can check every environment; arguments after -- go to validate.
  • Without --env, validate, plan, apply, destroy and outputs take the TERRADART_ENV environment variable, else the defaultEnv of runEnvironments, else the only environment, and print which one and why (env: dev (TERRADART_ENV), env: dev (default)). An entry point that calls runStack ignores TERRADART_ENV. apply and destroy ask before running against an environment TERRADART_ENV or defaultEnv chose, and stop without an answer; --auto-approve skips the question.
  • plan, apply and destroy no longer run one engine on a state the other wrote without asking. When .terradart/engines.json has no record for the state (right after a migration, or in a fresh clone), they read it — the local state file before init, a remote backend's state pull after it — and tell the engine that wrote it from its provider addresses (registry.terraform.io / registry.opentofu.org) or a terraform_version older than OpenTofu. An engine terradart picked by itself (PATH or the OpenTofu download) then needs a yes on a terminal, and without one stops with exit code 64 and the --engine flag that decides; an engine --engine or pubspec.yaml chose runs with a warning.
  • A package terradart migrate generates carries terradart: engine: terraform (tofu for a tree run with OpenTofu), so its state stays on the engine it came from.
  • terradart state migrate [--env <name>] moves the state to the backend the Stack configures after its backend changes: it synthesizes, then runs the engine's init -migrate-state in the directory the entry point wrote, with the environment's backendConfig. It names the full source and target configuration (bucket, prefix, and the rest — not only the backend type) and asks first; --auto-approve skips the question and is required without a terminal. Run it before the next plan or apply, which reconfigure onto the new backend without copying. When the environment passes backendConfig, it copies only the state of the environment that last initialized that directory (the record plan and apply write). Another environment, or no record, stops with exit code 64 and tells you to run terradart plan --env <name> first — --auto-approve does not skip that. It replaces "$(terradart engine)" -chdir=tf-out init -migrate-state.
  • terradart init [dir] writes a project that plans as it is — pubspec.yaml (terradart_core and the provider packages at the command's version), lib/env.dart (an Env enum with each environment's values), lib/stack.dart (provider, backend, one resource, one output), bin/infra.dart (runEnvironments), .gitignore, README.md and AGENTS.md (the commands and the TerraDart Agent Skill) — into infra/ by default, then runs dart pub get (--no-pub-get). Flags: --provider google|aws|cloudflare|appwrite, --env <names>, --gcp-project / --aws-region / --aws-account / --cloudflare-account / --appwrite-endpoint / --appwrite-project <env>=<value>, --state-bucket <name>|<env>=<name> (the backend follows the provider: GCS, S3 or Cloudflare R2), --backend local|gcs|s3|r2, --defaults, --[no-]flutter, --dry-run, --force. In a terminal each flag left out is a question — the state one is Do you already have a bucket for Terraform state? — and the run ends with the equivalent command. Without one it never asks and never chooses: --provider, --env and --backend (or --state-bucket) are required, the error names every missing one with a command to edit, and --defaults accepts dev,prd and local state. Inside a Flutter app it points appExports at the app's lib/generated/ and declares addDartDefineOutput(). A directory holding *.tf / *.tf.json files at any depth (past .terraform/, build/, tf-out/, the Flutter platform folders and the like) is named and pointed at terradart migrate (and offered its report in a terminal) unless --force. Existing files are never overwritten without --force.
  • Appwrite runs on Terraform: a Stack whose required_providers names appwrite/appwrite (published to the Terraform registry only, which OpenTofu cannot install from) resolves to the terraform on PATH, and validate, plan, apply, destroy and outputs stop before init with a message naming --engine terraform / terradart.engine: terraform when there is none or --engine tofu, engine: tofu or a tofu engine_path asks for OpenTofu. terradart init --provider appwrite writes terradart: engine: terraform into pubspec.yaml.

0.33.0 - 2026-10-02 #

First release, in lockstep with the workspace.

  • The terradart command: synth runs the entry point (bin/infra.dart, or terradart.entrypoint in pubspec.yaml); plan, apply and destroy synthesize, then run init and the engine in the directory it wrote; outputs writes the define file from the applied state without planning or applying; engine prints the binary it runs.
  • The engine is the first of --engine-path / --engine (or engine_path / engine in pubspec.yaml), the engine .terradart/engines.json records for the state, tofu on PATH, terraform on PATH, and OpenTofu 1.13.1 downloaded from its GitHub release — checked against the SHA-256 the package ships, and cached in the user cache directory — on Linux, macOS and Windows, amd64 and arm64. Running a state with another engine than the one that applied it, or an older one, warns first.
  • Environments come from the entry point: --env <name> names a member of the enum bin/infra.dart passes to runEnvironments, and the Terraform directory, workspace and partial backend configuration are the ones it declares. An unknown name lists the known ones.
  • apply and outputs write the Stack's addDartDefineOutput() to .terradart/dart_defines.json (.terradart/dart_defines.<env>.json with --env; --define-output, --define-file or terradart.dart_defines in pubspec.yaml pick another), gitignore .terradart/, and print the flutter run / flutter build line that reads it.
  • terradart migrate runs the terradart_migrate library (scanModuleTree, migrateTree, migrateModule), including --report, --merge-envs and --lift-workspace. It does not look for a pubspec.yaml, so dart pub global activate terradart_cli migrates a tree before a Dart project exists. --merge-envs writes an Env enum and a bin/infra.dart that calls runEnvironments, and terradart plan --env <name> runs one environment.
1
likes
160
points
102
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

The terradart command — synth, plan, apply and migrate a TerraDart Stack or an existing Terraform tree, and write outputs as a --dart-define-from-file JSON.

Homepage
Repository (GitHub)
View/report issues
Contributing

Topics

#terraform #opentofu #infrastructure #cli

License

Apache-2.0 (license)

Dependencies

args, crypto, path, terradart_hcl, terradart_migrate, yaml

More

Packages that depend on terradart_cli