Open-source CLI · TypeScript / Node · design notes

A build system for AI-coding harnesses.

A harness is everything that shapes how coding agents behave in a repository: rules, agents, commands, skills, hooks and MCP servers. Craftar addresses two problems with it: keeping one harness consistent across many teams that use different AI coders (P1), and keeping one developer's many workspaces — each on a different team's Git remote — on the same version of it (P2). It does so by treating the harness as source in a Git repository, the Forge, composed per team and emitted in each tool's native format with a lockfile.

Read the model $npm install -g craftar
claude-codekirokimicodexcursorwarpagents-md
~/work/team-a/platform-workspace
$ craftar sync
craftar sync — profile team-a · recipes base → backend-clean-arch → frontend-angular → aws-local → pm-azure-devops · targets claude-code, kiro

  wrote 4, removed 1 orphan(s), skipped 1
  + .claude/rules/frontend-angular.md
  + .claude/agents/frontend-reviewer.md
  + .claude/commands/create-component.md
  + .kiro/steering/frontend-angular.md
  - .kiro/steering/frontend-react.md  (orphan: no longer produced by the Forge)
  ! .kiro/agents/frontend-reviewer.json  hand-edited since last sync — run `craftar diff` and either `--overwrite-drift` or promote the change to the Forge
$ 
Problem statement

Two problems, one root: the harness has no source and no record.

P1

One harness, T teams, K AI coders, A agents each — maintained by hand.

A harness is a roster of agents — a reviewer per architecture, a docs author, an executor — plus the rules they are bound to, the workflow commands, hooks and MCP servers. Across T teams it exists as T copies in K formats (.claude/, .kiro/, AGENTS.md, .cursor/), each holding the same A agents. A change costs T × K manual edits, with no record of what was generated from what.

requiresone source; emission per target; a record per file.

P2

One developer, many workspaces, separate remotes.

One machine, one workspace per team. Each workspace groups that team's repositories on that team's Git host; no repository is common to all of them. The harness in each was copied in by hand at a different time. Nothing on the machine records which version each workspace carries, or whether a file in .claude/ is still the copy or has been edited in place.

requiresa channel that is no team repository's remote; a lock per workspace; a registry.

state before Craftar — the resolved state of each is in Model
Today: one harness copied by hand into four team workspaces, each in a different AI coder format Mechanism: a single harness (about 12 rules, 7 agents, 9 commands, skills, hooks and 4 MCP servers) exists only as a folder on the developer's machine. It is copied and translated by hand into four team workspaces: team A uses Claude Code, team B uses Kimi via AGENTS.md, team C uses Kiro, team D uses Cursor. Because the copies are manual, they diverge: team A's copy is two months old, team B has one stale agent, team C is missing one agent, team D carries version 3 of 5. No edge in this graph is recorded anywhere, so nothing can report which copy is current. harness (yours) rules ×12 agents ×7 commands ×9 skills · hooks mcp ×4 a folder + memory copy translate by hand team A · workspace .claude/ 2 months old team B · workspace AGENTS.md 1 stale team C · workspace .kiro/ 1 missing team D · workspace .cursor/ harness v3 of 5

dashed edges are manual work; no edge records provenance. Each small block is one agent (reviewer, author, executor…). Faded = diverged or absent.

Failure modes

What breaks when the harness is duplicated — observed, not hypothetical.

Two earlier attempts at generating .claude/ from templates were adopted and later removed by the teams using them. Their post-mortems, plus the tech-debt notes of hand-synchronised workspaces, reduce to eight recurring failures — FM-1 to FM-5 stem from P1, FM-6 to FM-8 from maintaining P2 by hand. Each one becomes a design constraint in Invariants.

idFailureRoot cause
FM-1Regeneration deletes hand-written agents and rulesGenerator treats the whole .claude/ folder as its output; anything not produced by a template is collateral.
FM-2Every file reports as hand-edited on every run; team runs permanently on --forceDrift guard hashes raw bytes; Git rewrites LF→CRLF on Windows checkout, so the hash never matches.
FM-3A deleted rule keeps loading into sessionsGenerator only writes; it never removes the outputs of ingredients that left the set. The checker compares present files only, so it still reports "in sync".
FM-4Kiro steering, agent JSON and command mirrors diverge from their source by 4–52 linesOnly rules were generated; agents and commands for the second target were kept as manual mirrors of the first.
FM-5Architecture rule and its reviewer agent contradict each otherRule and reviewer are two files stating the same constraints, edited independently.
FM-6A model pin or MCP version breaks in three places at once; two sessions patch the same line the same dayVolatile values are inlined in a rule, a script and a steering file rather than declared once.
FM-7Language policy "everything in English" contradicted by 18 filesLanguage treated as a property of the workspace instead of each ingredient; re-syncing became a bilingual merge.
FM-8Real package-feed tokens in a staged settings.jsonGenerated settings carried values instead of references to environment variables.
Model

Source, resolution, emission.

Craftar borrows the shape of a build system. Ingredients are source; recipes and profiles compose them; craftar sync resolves the composition for one workspace and emits target-specific outputs, recording every output in a lockfile. The generated files are committed to the workspace, so a team that only uses Kiro never needs Craftar installed.

With Craftar: one Forge resolved per workspace and emitted to each team's AI coders Mechanism: the Forge is one Git repository containing ingredients (rules, agents, commands, skills, hooks, MCP servers, services), recipes (base, backend-*, frontend-*, aws-local, pm-*) and one profile per team. Running craftar sync in a workspace loads the Forge (a pinned ref is planned), resolves layers, emits files for each of the workspace's targets and writes craftar.lock. Team A emits to .claude/ with 7 agents; team B swaps the frontend recipe and has three workspaces, one AI coder each — .opencode/, .kimi/ and .aider/; team C pins the Forge at tag v2.3, emits .kiro/ and is two commits behind; team D adds Cursor through its local file and has one drifted file. Every edge is generated and recorded in the lock. Forge · git repo ingredients/ rules · agents · commands skills · hooks · mcp · services recipes/ base · backend-* · frontend-* aws-local · pm-* profiles/ team-a · team-b · team-c · team-d single source of truth craftar sync resolve layers emit per target write craftar.lock @ref team Acraftar.yaml · profile: team-a .claude/ 7 agents · 1 target · lock ok team Brecipes: −frontend-angular +frontend-react ws-1.opencode/ ws-2.kimi/ ws-3.aider/ 6 agents · 3 workspaces · lock ok team Cforge pinned @ v2.3 .kiro/ 5 agents · kiro · behind 2 team Dcraftar.local.yaml: +cursor .cursor/ 7 agents · cursor · drift 1

P1 resolved — solid edges are generated and recorded in each workspace's lockfile; status reads the lock to report behind / drift per workspace.

P2 resolved — one Forge, one lock per workspace, one registry

Same machine, same four workspaces, same four remotes. The Forge is a fifth repository that none of the team repositories reference; each workspace's craftar.yaml points to it. What the workspaces now share is the harness: every workspace is generated from the same Forge, so base rules, commands and agents are identical across all of them, and the lockfile in each records exactly which Forge commit produced it. craftar ls will read the registry and report, per workspace, whether it is at the Forge head, behind, or drifted.

One developer machine with four team workspaces, each with its own repositories on separate Git remotes, all generated from a single Forge Mechanism: same developer machine and same four workspaces as the problem statement, workspace-1 to workspace-4, each still cloning its team's repositories from that team's own remote. Now a fifth repository, the Forge, is referenced by each workspace's craftar.yaml and is not a remote of any team repository. Between them sits craftar itself: it reads the Forge and emits each workspace's harness, so nothing flows from the Forge to a workspace except through it. Each workspace carries a generated harness with the same base ingredients and a craftar.lock naming the Forge commit that produced it (7c1e9a2 for three of them, 5b0d3f1 for the pinned one). The registry at ~/.craftar/registry.json lists all four, and craftar ls will report per workspace: up to date, behind, or drift. forge sync → workspaces · recorded in each lock main @ 7c1e9a2 · one git repo craftar syncreads the Forge · emits per targetworkspace-1/up to dateprofile team-alock forge@7c1e9a2targets claude-codeharness · generated · baseremote git.team-a.exampleapi-core/web-app/worker-jobs/workspace-2/up to dateprofile team-block forge@7c1e9a2targets kimiharness · generated · baseremote github.example/team-bcatalog-api/catalog-web/workspace-3/behind 2profile team-clock forge@5b0d3f1 · v2.3targets kiroharness · generated · baseremote azure.example/team-cbilling-api/billing-web/billing-cli/workspace-4/drift 1profile team-dlock forge@7c1e9a2targets cursorharness · generated · baseremote gitlab.team-d.exampleadmin/admin-desktop/ developer machine ~/.craftar/registry.json · 4 workspaces · 10 repositories · 4 remotes · 1 Forge $ craftar ls

the Forge is never a remote of any team repository; generated files are committed inside each workspace, so a team's own clone of its repo already contains the harness in its tool's format.

~
$ craftar ls  # planned
WORKSPACE            PROFILE   STACK             TARGETS             FORGE     STATUS
team-a-workspace     team-a    angular · dotnet  claude-code, kiro   7c1e9a2   up to date
team-b-workspace     team-b    react · dotnet    kimi                7c1e9a2   up to date
team-c-workspace     team-c    angular · dotnet  codex               5b0d3f1   behind 2 (pinned v2.3)
team-d-workspace     team-d    angular · dotnet  cursor              7c1e9a2   drift 1  .claude/rules/workflow.md
$ 
Layer resolution

From layers to files — how sync works.

A workspace is the result of layers applied in a fixed order, weakest first. Ingredients with the same name resolve to the strongest layer; stack recipes that declare the same slot are mutually exclusive; {{params}} are substituted from the winning layer. craftar explain <file> prints the layer that decided each output.

Layers, weakest → strongestsource
baserecipe · every workspace
stack recipesbackend-clean-arch · frontend-angular
team profileprofiles/team-a
craftar.yamlthis workspace · committed
craftar.local.yamlone developer · git-ignored

All layers are versioned in the Forge except the last two, which live in the workspace.

Pipelinecraftar sync
$ craftar sync
  1. Read craftar.yaml; load the Forge (a local path today; a pinned git ref is planned).
  2. Resolve layers, exclusive slots and params into the final ingredient set.
  3. Emit open standards verbatim: AGENTS.md, Agent Skills (SKILL.md), mcp.json.
  4. Emit tool-specific formats (inclusion modes, subagents, hooks) through Craftar's own emitters and post-processors; delegating further formats to rulesync is planned.
  5. Diff against craftar.lock; classify each file as new / update / unchanged / adopt / drift / collision / orphan; write, remove orphans, refresh the lock.
Targets, native formatgenerated · committed
Claude Code.claude/ · CLAUDE.md
Kiro.kiro/steering · agents/*.json
KimiAGENTS.md · skills
CodexAGENTS.md · [hooks]
Cursor.cursor/rules/*.mdc
Warpworkflows · mcp

Every generated file carries a generated by craftar from forge@sha header where the format allows comments; JSON gets a _craftar field.

In practice — Forge → Workspace by stack

The diagram above shows the logical flow — layers resolving into targets. Below is the physical mapping: how a real Forge for a given stack becomes actual files in the workspace. Select a stack, then a target to see exactly what craftar sync produces.

dotnet-enterprise

A Forge for .NET backend teams following Clean Architecture — see how its ingredients map to each target's workspace structure.

Forge source
forge/
├── ingredients/
│   ├── rules/
│   │   ├── dotnet-clean-architecture/
│   │   ├── dotnet-clean-code/
│   │   ├── dotnet-minimal-api/
│   │   ├── dotnet-entity-framework/
│   │   └── dotnet-security/
│   ├── agents/
│   │   ├── dotnet-arch-reviewer/
│   │   ├── dotnet-api-reviewer/
│   │   ├── dotnet-ef-reviewer/
│   │   └── dotnet-security-reviewer/
│   ├── commands/
│   │   └── create-api-endpoint/
│   ├── docs/
│   │   ├── architecture-template/
│   │   ├── adr-template/
│   │   └── tech-debt-template/
│   └── services/
│       └── localstack-sqs/
├── recipes/
│   └── dotnet-clean-arch.yaml
└── profiles/
    └── team-dotnet/
sync
Workspace generated
workspace/
├── .claude/                    ← generated
│   ├── rules/
│   │   ├── dotnet-clean-architecture.md
│   │   ├── dotnet-clean-code.md
│   │   ├── dotnet-minimal-api.md
│   │   ├── dotnet-entity-framework.md
│   │   └── dotnet-security.md
│   ├── agents/
│   │   ├── dotnet-arch-reviewer.md
│   │   ├── dotnet-api-reviewer.md
│   │   ├── dotnet-ef-reviewer.md
│   │   └── dotnet-security-reviewer.md
│   └── commands/
│       └── create-api-endpoint.md
├── docs/                       ← generated structure
│   ├── architecture/
│   │   └── README.md
│   ├── adr/
│   │   └── README.md
│   └── tech-debt/
│       └── README.md
├── local-stack/               ← generated
│   └── docker-compose.yaml
├── src/                        ← client code (untouched)
├── craftar.yaml
└── craftar.lock
generated by Craftar client-owned (untouched)
What syncs where

Craftar generates files inside the AI coder folder (.claude/, .kiro/, .cursor/) and outside it (docs/, local-stack/, AGENTS.md). Files outside are tool-agnostic — the same docs/architecture/ structure serves Claude Code, Kiro and Cursor users alike. Client-owned folders like src/ or infra/ are never touched by craftar sync.

Forge

forge/ · one Git repo

Repository holding every ingredient, recipe and profile. Versioned; workspaces point at it by local path today — referencing a branch, tag or SHA is planned.

Ingredient

ingredients/rules/frontend-angular/

Smallest reusable unit: a rule, agent, command, skill, hook, MCP server, local service or template. A folder with an ingredient.yaml declaring type, targets, inclusion mode and globs.

Recipe

recipes/frontend-angular.yaml

Named set of ingredients with parameters. Recipes extend others; stack recipes declare a slot so two front-end stacks cannot coexist.

Profile

profiles/team-a/profile.yaml

One team: recipes, repositories, template feeds, PM tool, internal platform, and which AI coders that team uses. Parameters for the whole stack live here.

Workspace

craftar.yaml

Local folder — one repo or a folder of repos — declaring profile, recipe add/remove and targets, plus a git-ignored craftar.local.yaml for per-developer overrides.

Target

claude-code · kiro · kimi · codex · cursor

An AI coder to emit for. Each will declare its coverage in a capabilities.yaml (planned); today the Kiro emitter warns and skips what it cannot express — a fallback is planned.

Lockfile

craftar.lock

Forge SHA, the resolved profile name and a normalized content hash for every generated file. The only authority on what Craftar owns in a workspace.

Registry

~/.craftar/registry.json

Every workspace on the machine: path, profile, last sync, status. Will back craftar ls and the local dashboard — planned.

Capabilities

Twelve capabilities, each tied to the problem it addresses.

Ordered by roadmap phase. working marks what runs today and is covered by tests; a # planned comment in a snippet marks a command that is designed, not built; mvp marks the minimum first release.

F1 workingmvp

Forge → workspace sync

problem · P1 · P2A change to any of A agents or their rules must reach T workspaces in K formats; today that is T × K manual edits with no provenance.

$ craftar sync [--dry-run] [--check] [--overwrite-drift] $ craftar diff # what sync would change, writes nothing $ craftar status # per file: new · update · unchanged · adopt · drift · collision · orphan · orphan-drift $ craftar sync --forge-ref v2.3 --targets kiro · craftar update # planned

One command resolves and emits for every active target and prints what it wrote, removed and skipped, file by file. Following a Forge branch or pinning a tag is planned.

F2 workingmvp

Multi-target emission

problem · P1Each team's AI coder has its own file layout, frontmatter and agent schema. Translating by hand yields FM-4: mirrors that diverge.

$ craftar import --from claude-code # existing .claude/ → ingredients + recipes + profile $ craftar targets # targets and capability coverage — planned

Three layers: open standards emitted verbatim (AGENTS.md, Agent Skills, Agent Plugins mcp.json); tool-specific formats; Craftar post-processors for known gaps, e.g. injecting resources: file://.kiro/steering/*.md into Kiro custom agents. Today Craftar's own emitters cover Claude Code, Kiro and AGENTS.md, and the Kiro emitter reproduces a hand-built workspace byte for byte, including agent JSON and command mirrors. Delegating Codex, Kimi and Cursor formats to rulesync is planned.

F3 resolution working

Layers and stack slots

problem · P1Teams differ in stack. Without composition, a React team inherits Angular reviewers, or every team gets a hand-pruned fork of the harness.

$ craftar add recipe frontend-react · craftar remove recipe frontend-angular # planned $ craftar recipes · craftar ingredients --recipe frontend-angular # planned $ craftar explain .kiro/steering/workflow.md # which layer decided this file

Recipes declaring the same slot are mutually exclusive. The profile sets the team default; the workspace may override; the local file (craftar.local.yaml, git-ignored) overrides the workspace for one developer; its arrays replace the workspace's.

F4

Workspace bootstrap

problem · P2Starting with a new team means reassembling repos, harness, templates and local services from memory.

$ craftar init # planned — Forge → profile → recipes/targets → clone repos? → templates/services? → sync $ craftar init --profile team-a --targets claude-code,kiro --yes # planned

Reads the profile's repos, templates and services; registers the workspace in the registry.

F5

PM tool and internal platform per profile

problem · P1Agents need to read user stories and talk to the team's internal developer platform; each team uses a different tool for both.

integrations.pm.kind ∈ {github, azure-devops, notion, jira} selects the matching MCP ingredient plus a rule describing how stories are located and interpreted for that team. integrations.idp registers the platform's MCP server in every target that supports MCP and adds a rule describing its operations. Tokens are referenced by authEnv, never stored (FM-8).

F6

Local services per workspace

problem · P1Cloud dependencies (queues, buckets) need a local stand-in, and the agent has to know its endpoints and fake credentials.

$ craftar services up | down | status # planned

A service ingredient carries a docker-compose fragment, default variables and a rule for the agent. Fragments merge into .craftar/compose.yaml. First ingredient: LocalStack-style SQS/S3.

F7

Project templates

problem · P1New projects should use the team's own dotnet new (or npm create, nx, cookiecutter) templates; agents need to know which.

$ craftar templates install · /create-project # planned

The profile declares feeds and packages; Craftar installs them and generates a rule mapping archetype → template plus a wrapping command.

F8 detection working

Drift and reverse contribution

problem · P2Generated files get edited in place. Either the edit is lost on the next sync, or the generator is abandoned (FM-2).

$ craftar status # drifted files listed; never overwritten without --overwrite-drift $ craftar drift show <file> · drift discard · drift promote # planned

Normalized hashes from the lock are compared with disk. Planned: promote will convert the edit back into an ingredient via import and open a Forge branch. Sync direction is Forge → workspace; reverse flow is always explicit.

F9 --check working

CI

problem · P2Sync that depends on someone remembering will lag by workspace.

$ craftar sync --check # exit ≠ 0 when behind or drifted

Planned: a GitHub Action and an Azure Pipelines task that open a PR with the change summary when the Forge moves; optional Forge-side dispatch to registered workspaces; a pre-commit hook running --check.

F10

Registry and dashboard

problem · P2With a dozen workspaces there is no view of which is behind, drifted or on which Forge version.

$ craftar ls · craftar ui # planned — today's ls lists the recipes and ingredients resolved for one workspace

Table or local web page: workspace, profile, stack, targets, Forge SHA, status; actions sync / diff / explain; Forge view of recipes, ingredients and who uses what.

F11

Craftar as an MCP server

problem · P1 · P2The agent itself should be able to check status, sync, or add a recipe without leaving the session.

$ craftar mcp # planned

Exposes status, sync, diff, explain, recipes, add recipe, services up. Packaged as a Claude Code plugin, an Agent Plugin, and Warp workflows — thin shells over the CLI.

F12

Diagnostics

problem · P2Sync failures usually come from the environment: missing env vars, wrong Node, no Docker, unreachable Forge.

$ craftar doctor # planned

Checks Node and rulesync versions, Git access to the Forge, every authEnv required by MCP ingredients, Docker when services exist, dotnet when templates exist, and lockfile consistency.

Invariants

Constraints derived from the failure modes.

These are the constraints Craftar is built against, in every command and every emitter — what distinguishes it from a template renderer. The two marked planned are design commitments, not yet enforced by the code.

never

Touch a file not in the lockfile

The lock is the complete list of managed outputs. Unknown files inside .claude/ or .kiro/ are preserved and never removed; one at a path the Forge would write is reported by status as a collision and never touched. Regeneration is per file.

← FM-1

never

Hash raw bytes

Content hashes are computed after normalization: LF line endings, UTF-8, BOM stripped; JSON compared structurally. Claude Code and AGENTS.md outputs keep the EOL and BOM of the file they replace; Kiro output is always CRLF without BOM.

← FM-2

never

Leave an orphan on disk

An output whose ingredient left the resolved set is removed on the next sync and named in the summary, in every target. --check fails on orphans.

← FM-3

never

Require a manual mirror

Everything a second target needs — steering, agent JSON, command copies — is emitted from the same ingredient. If two files must say the same thing, both are generated.

← FM-4

never planned

Split a rule from its reviewer

An architecture rule and the reviewer agent for that architecture are meant to be one ingredient with two outputs, so they cannot disagree. Planned: today the rule and its reviewer are separate ingredients (rule/<name>, agent/<name>-reviewer) grouped by a stack recipe.

← FM-5

never

Inline a volatile value

Model pins, MCP versions, ports and organisation names are declared once in the profile and injected as {{params}} wherever cited.

← FM-6

never

Translate

Language is an attribute of the ingredient. The Forge may hold rules in one language and docs in another; Craftar emits text as written.

← FM-7

never planned

Store a secret

Ingredients are meant to declare authEnv; settings would be emitted as settings.example.json; doctor would verify the variables exist on the machine. Planned: not built yet, though craftar import already refuses ingredients holding secret-like values.

← FM-8

Targets

Capability matrix.

This table is the design target, not current coverage: today only the Claude Code, Kiro and AGENTS.md emitters exist. A per-target capabilities.yaml is planned. Nothing may be dropped silently: today the Kiro emitter warns and skips what it cannot express; closing the remaining gaps is planned.

TargetEmits toRules & inclusion modesCommandsSubagentsHooksSkillsMCP
Claude Code.claude/ · CLAUDE.mdyesyesyesyesyesyes
Kiro.kiro/steering · .kiro/agents/*.jsonalways · fileMatch · manualyescustom agentspartialyesyes
KimiAGENTS.md · SKILL.mdAGENTS.md onlyfallbackas commandsyesyes
CodexAGENTS.md · configAGENTS.md onlyfallback[hooks] blockyesyes
Cursor.cursor/rules/*.mdcglobs · alwaysfallbackAgent Pluginyes
Warpworkflows · mcpAGENTS.mdworkflowspartialyes
AGENTS.mdroot and per-folderplainyesmcp.json
yes — nativepartial / fallback — emitted with a warning— unsupported; reported and skippedKimi and Codex rows pending verification against the tools.
Status

Phase 0 — validated against a hand-built workspace with an oracle test.

Before generating anything new, Craftar has to reproduce what teams already have. The oracle imports a hand-built workspace (Claude Code + Kiro), syncs it, and asserts byte equality of every generated file; a second sync must be a no-op; a Forge edit must reach both targets; a manual edit must surface as drift and survive; a removed ingredient must disappear; an unmanaged file must be untouched.

Phase 0in progress

Foundations

  • Forge schema: ingredients, recipes, profiles
  • Layer resolver with exclusive slots and params
  • sync, diff, status, explain, ls, lockfile
  • import --from claude-code
  • Emitters: Claude Code, Kiro, AGENTS.md
  • Oracle suite against a private hand-built workspace, plus a synthetic suite in CI on Linux and Windows
Phase 1

Team profile

  • Profiles and craftar init
  • Remote Forge (Git URL)
  • PM tool → MCP, platform → MCP
  • doctor, registry
Phase 2

Environment

  • service ingredient
  • Project templates
  • drift show / discard / promote
  • docs validate
Phase 3

Automation

  • GitHub Action, Azure Pipelines task
  • craftar ui
Phase 4

Ecosystem

  • craftar mcp
  • Claude Code plugin, Agent Plugin
  • Warp workflows
  • Kimi, Codex, Cursor emitters
  • Documentation

Stack

TypeScript / Node CLI (commander, zod, yaml) with its own emitters for Claude Code, Kiro and AGENTS.md; rulesync is planned as the conversion dependency for further tool-specific formats; Craftar owns the layer above — Forge, resolution, lockfile, drift, registry.

Open questions

  • Forge as a separate repo (current) vs. monorepo with team repos
  • What Kimi and Codex read beyond AGENTS.md
  • Multiple Forges per workspace (schema reserved, not implemented)

Trying it

Install with npm install -g craftar (Node ≥ 22), or prefix any command with npx. Then, inside an existing Claude Code workspace, run craftar import --from claude-code --forge <dir> --profile <name> --write-config to obtain a Forge and a craftar.yaml, and craftar diff to see what a sync would change. Nothing in .claude/ or .kiro/ is rewritten until sync.

AI llms.txt

This page was written by a language model, from the project's specification and the notes of the workspaces that motivated it, and reviewed by a person. It is also meant to be read by language models: every diagram carries a prose description, the metadata is structured, and a plain-text version lives at llms.txt.