New to Claude Skills? Learn how to install them →

ant apply: Managing Claude API Resources as Code

ant apply, added in ant CLI 1.30.0, creates and updates Claude API agents, environments, skills and deployments from files in your repository, with a lockfile and a plan you approve.

September 6, 2026
Get Claude Skills
11 min read

Every earlier way to manage a Claude API agent from the command line was imperative: run ant beta:agents create, note the ID it returns, and remember to pass that ID plus the current version number back into ant beta:agents update the next time the definition changes. It works, and ant CLI scripting and automation covers that pattern in depth, but it puts the bookkeeping on you. ant apply, added in ant CLI version 1.30.0 on 3 September 2026, replaces that bookkeeping with a lockfile and a plan you approve, the same shape as Terraform or Pulumi for infrastructure.

What ant apply actually does

ant apply creates and updates Claude API resources from files: agents, environments, skills, memory stores and deployments. Each resource lives in your repository as a Markdown, YAML or JSON file and goes through the same review as your code. You describe a resource in a file, run ant apply, approve the plan it prints, and commit the claude-lock.json lockfile it writes. The next run then updates the resources the lockfile already tracks instead of creating duplicates.

ant apply requires ant CLI version 1.30.0 or later. If you haven't set up the CLI yet, start with Anthropic's CLI quickstart; our own ant CLI guide covers install and authentication in more detail.

Applying your first agent

Write the agent as a Markdown file under agents/:

---
name: Summarizer
model: claude-opus-5
tools:
  - type: agent_toolset_20260401
---

You are a helpful assistant that writes concise summaries.

The frontmatter holds the agent's configuration, the same fields covered in Define your agent, and the body becomes its system prompt. Apply it:

ant apply agents/summarizer.md

In an interactive terminal, ant apply prints a plan and waits for approval before it changes anything:

First apply  ./claude-lock.json does not exist yet and will be created

± Name                    Plan
+ ./agents/summarizer.md  create

Resources  + 1 to create

Apply these changes? (y)es / (n)o / (d)etails y

Apply  ./claude-lock.json

± Name                    Status
+ ./agents/summarizer.md  created    agent_011CYm1BLqPXpQRk5khsSXrs

Resources  + 1 created

State written to ./claude-lock.json

Answer d first if you want the full field-by-field detail before committing to the change. --dry-run prints that same detailed plan and exits without touching anything, which is the flag to reach for whenever you just want to see what would happen.

Edit the file and run ant apply again, and the plan shows an update rather than a create; the CLI diffs your file against what it last applied and only sends what actually changed.

Committing claude-lock.json

The first run writes claude-lock.json in the directory you ran it from, so run it from your repository root. It records each file's resource ID, its current version, and a hash of what was sent and what the API returned:

{
  "version": 1,
  "origin": {
    "base_url": "https://api.anthropic.com",
    "organization_id": "1b0c2a4d-6c1f-4f0e-9a57-2e8d1c3b4a5f",
    "workspace_id": "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
  },
  "resources": {
    "./agents/summarizer.md": {
      "kind": "agent",
      "id": "agent_011CYm1BLqPXpQRk5khsSXrs",
      "version": "1",
      "hash": "d23251c8d99b3613a64f3f8d87f5fad4",
      "remote_hash": "1b771bee5bdbf600a5ad972fdac32d94"
    }
  }
}

Commit it alongside your resource files. It's how the next run, on your machine or in CI, finds the resource it already created instead of making a second one, and it's where you'd read an agent's ID to start a session without going back to the API response. The two hashes let a later run notice both an edited file and a resource that changed outside these files entirely.

How ant apply figures out a file's kind

Walking a directory, ant apply determines each file's kind from the first of these that matches:

  1. A top-level type field inside the file.
  2. The directory it's directly in: agents/, environments/, memory_stores/, or deployments/.
  3. A filename that starts with the kind, such as environment_staging.md.

Files matching none of these, READMEs, CI configuration and the like, are skipped unless you name them explicitly on the command line. A named Markdown file that matches none of the three rules is treated as an agent; a named YAML or JSON file that matches none is an error rather than a silent guess.

Growing one agent into a full project

Every resource kind can be declared the same way. Any resource except a skill can be written as YAML, JSON or Markdown; in Markdown, the frontmatter is the request body and the prose fills whichever text field that kind expects, an agent's system, an environment's or memory store's description, or a deployment's first message.

  • An environment is a YAML file under environments/.
  • A memory store is a YAML file under memory_stores/.
  • A deployment is a Markdown file under deployments/: the frontmatter is the request body and the prose becomes the first message that starts each run.
  • An Agent Skill is a directory with a SKILL.md at its root, conventionally under skills/, uploaded as one bundle.

Resources point at each other with relative paths instead of IDs. Wherever the API expects another resource's ID, write the relative path to its file:

agents/
  reviewer.md
  lead.md
skills/
  pr-summary/
    SKILL.md
environments/
  cloud.yaml
memory_stores/
  review-notes.yaml
deployments/
  nightly.md

reviewer.md lists ../skills/pr-summary under skills, lead.md lists ./reviewer.md in its multiagent roster, and nightly.md names its agent, environment and memory store the same way:

---
name: Nightly review
agent: ../agents/reviewer.md
environment_id: ../environments/cloud.yaml
resources:
  - path: ../memory_stores/review-notes.yaml
    access: read_write
schedule:
  type: cron
  expression: "0 3 * * *"
  timezone: America/Los_Angeles
---

Review any open pull requests. Start with the oldest.

Apply the whole directory at once and ant apply creates every resource in dependency order, filling in the real IDs as it goes:

ant apply .

References pin to the version ant apply just applied, so editing reviewer.md or the skill it references updates everything that points at them in the same run. To reference a resource these files don't manage, write its literal ID (agent_..., skill_...) instead, and anything shaped differently, such as {type: anthropic, skill_id: xlsx}, passes through to the API unchanged.

A skill reference can also be a GitHub URL, https://github.com/<owner>/<repo>/tree/<branch>/<dir>, for instance a directory inside Anthropic's own open-source skills repository. ant apply downloads and uploads that directory, pinned to the resolved commit, until you re-run it with --upgrade. Set GITHUB_TOKEN if the repository is private.

Editing and reapplying

Running ant apply with no arguments reconciles every file the lockfile already tracks. At a terminal, it also lists any resource files under the lockfile's directory that aren't tracked yet and offers to add them. Deleting a field from a file clears it on the resource, if the API allows that field to be cleared; a field you never set, or one the API can't clear, keeps whatever value it currently has.

If a resource was edited, archived or deleted outside these files, in the Console, for example, the plan ends with This plan cannot be applied: and the reason, and the command exits refusing to apply rather than guessing which side should win. Pass --force to overwrite the out-of-band change or create a replacement.

Deleting a file leaves its resource in place with a warning rather than deleting it silently. --prune removes resources the lockfile tracks but no file declares any more, archiving an agent or environment, or deleting a skill outright. Renaming a file therefore declares a new resource and leaves the old one alone until you prune it.

ant apply can't adopt a resource you created in the Console or with the older ant beta:agents create command. It only manages what's already in the lockfile, so applying a file that happens to describe an existing agent creates a second one rather than linking up with the first. The one exception is a Console export: downloading an agent with Export as code includes its own claude-lock.json, so applying that download updates the resource you built in the Console rather than duplicating it.

Running ant apply in CI

Without a terminal to confirm a plan interactively, ant apply prints the plan and stops: cannot ask for confirmation without a terminal; re-run with --yes to apply, or --dry-run to see the plan only. A workable CI setup:

  • Run ant apply --yes . on your default branch after a merge, naming the project directory explicitly. A bare ant apply --yes with no path reconciles only files the lockfile already tracks and skips anything newly added.
  • On pull requests, run ant apply --dry-run . so reviewers see the plan alongside the diff. It's informational only and exits 0 even when the plan itself is blocked.
  • Commit the updated claude-lock.json at the end of the job, even when the apply step failed partway through, because a partial apply still records what it managed to create.
  • Run one apply at a time. Nothing locks the lockfile against concurrent runs.
  • Authenticate with Workload Identity Federation rather than a stored API key, using an identity that resolves to the organisation and workspace already recorded in claude-lock.json. ant apply refuses credentials that resolve to any other organisation or workspace, which is the guardrail that stops a misconfigured pipeline from quietly creating resources in the wrong place.

For a full GitHub Actions example, see the CI section of the CLI README.

Flags

FlagEffect
--dry-runPrint the plan and exit without applying or writing the lockfile. Exits 0 even when the plan is blocked
--yesApply without asking for confirmation. Required when there's no terminal
--forceApply even where a resource was changed, archived or deleted outside these files
--pruneRemove resources that are in the lockfile but no longer declared in a file
--upgradeRe-resolve skills referenced by GitHub URL, which otherwise stay pinned to the commit recorded in the lockfile
--lock-file <path>Use this lockfile instead of searching upward from the current directory. Keep one per organisation or workspace
--verbose, -vShow unchanged resources and full field values in the plan

How this compares to scripting resources by hand

If you've already set up the imperative pattern from ant CLI scripting and automation, create a resource with ant beta:agents create, track its ID and version yourself, call ant beta:agents update --agent-id <id> --version <n> on every change, ant apply is a declarative front end over the same underlying resources, not a competing system.

Imperative (ant beta:agents create/update)Declarative (ant apply)
What you trackThe ID and version number, by hand or in your own scriptclaude-lock.json, written and updated automatically
Cross-resource referencesYou resolve IDs yourself and pass them as flagsRelative file paths, resolved and pinned automatically
Detecting driftNothing built inPlan flags out-of-band edits and refuses to overwrite them without --force
Multiple resources at onceOne command per resource, in the order you chooseant apply . applies a whole directory in dependency order
Best fitOne-off scripts, ad hoc investigation, piping through --transformA project's agents, skills and deployments living in version control long-term

Both are still ant, and both still talk to the same API resources; a project can use ant apply for what it version-controls and drop into ant beta:agents retrieve or a --transform-piped one-liner for a quick lookup that doesn't belong in a file.

Troubleshooting

ant apply says it can't ask for confirmation. You're running without an attached terminal, in CI or a script. Add --yes to apply without a prompt, or --dry-run to see the plan without applying anything.

The plan says This plan cannot be applied and refuses. A resource your files manage was edited, archived or deleted somewhere else, most often the Console. Check what changed, and pass --force only once you've decided your file should win.

Applying a file creates a duplicate resource instead of updating the one you already have. The resource isn't in claude-lock.json, either because it was created outside ant apply (the Console, ant beta:agents create) or because the lockfile was deleted or is being read from the wrong path. Use --lock-file to point at the right lockfile, or re-adopt a Console-created agent by downloading it with Export as code, which ships its own lockfile.

A GitHub-sourced skill never picks up upstream changes. Skill references by GitHub URL stay pinned to the commit recorded in the lockfile by design, so a later commit on that branch doesn't change anything until you run ant apply --upgrade.

CI fails with a credential or organisation mismatch. ant apply refuses credentials that resolve to a different organisation or workspace than the one recorded in claude-lock.json. Confirm the CI identity, ideally set up through Workload Identity Federation, actually resolves to the workspace the lockfile expects.

Where this fits

ant apply sits on top of the same Managed Agents resources covered elsewhere on this site: multiagent orchestration for how a roster of agents delegates work, scheduled deployments for the cron and run-history model a deployments/ file now targets directly, and session budgets for capping what a run can spend. For the scripting patterns ant apply complements rather than replaces, see ant CLI scripting and automation. Anthropic's own Manage resources as code with ant apply page is the full reference this article draws from. Browse the wider skills catalogue at getclaudeskills.com/skills.

Verified 6 September 2026 directly against Anthropic's ant apply documentation at platform.claude.com/docs/en/cli-sdks-libraries/cli/apply, read in full, and the 3 September 2026 entry on platform.claude.com's release notes confirming ant CLI version 1.30.0.

Frequently asked questions