pxml is a structured XML DSL and compiler for AI-driven code generation. Instead of writing free-form prompts, you specify your web application architecture in XML, manage modifications using a Manifest, and allow the AI to perform local self-healing repairs at minimal cost.
Free-form prompt (what you type today):
"Create a Next.js API route at
app/api/posts/route.tsthat uses better-sqlite3, creates a 'posts' table if it doesn't exist, handles POST to insert a new post with title/content, and handles GET to list all posts. Make it dynamic, not cached."
pxml (what you write instead):
<node id="api.posts.create" type="api-route" flow="blog.write">
<meta><path>app/api/posts/route.ts</path></meta>
<input>
<field name="title" type="string" required="true" />
<field name="content" type="string" required="true" />
</input>
<test>
<given>
<body json="true">
<title>Hello</title>
<content>My post</content>
</body>
</given>
<expect><status>200</status></expect>
</test>
</node>Why it matters: The prompt is brittle — one typo, one ambiguous phrase, and the LLM generates broken or diverging code. The XML is a structured spec: the AI can only generate code that fits the declared schema, and the <test> block is automatically compiled into an executable Vitest file that proves the code works.
Free-form (when you discover /api/posts returns 500):
- Copy the error message into a new chat.
- Paste your entire
route.tsfile. - Write: "The POST handler is broken, fix it."
- The LLM regenerates the entire file — possibly breaking other parts.
- No automated re-test; you manually verify in browser.
- Next session: AI forgets this ever happened.
pxml (pxml fix --flow=blog.write):
- Failing test is already recorded in
.pxml/manifest.json. - AI receives only: the failing test name, the current source file, and the
bugs_history.xmlcontext. - AI emits a surgical SEARCH/REPLACE patch changing only the broken lines.
- The test runner automatically re-executes the suite.
- Retries up to 3 times if the fix doesn't pass.
- Root cause is recorded in
bugs_history.xml— future fixes will never reproduce it.
| Feature | Free-form Prompting (ChatGPT, Cursor) | pxml Specification-driven Compilation |
|---|---|---|
| Input format | Paragraphs of natural language | Declarative XML with typed inputs, outputs, constraints |
| Validation | None (you discover mistakes at runtime) | Schema validation before any LLM call (pxml validate) |
| Execution order | AI guesses dependencies (often wrong) | Topological sort from explicit <depends_on> (guaranteed correct) |
| Tests | You write tests separately (or skip them) | <test> blocks auto-compiled to Vitest, run automatically |
| Bug fixing | Re-prompt with full file — regenerates everything, risks regression | Partial SEARCH/REPLACE patch — only broken lines change |
| Regression prevention | None — each chat session starts from scratch | bugs_history.xml permanently attached to every fix prompt |
| Token cost | Unpredictable (entire files in/out each turn) | Measured per-node, printed in dollars after every compile/fix |
| Delivery guarantee | Best-effort (AI may skip constraints) | Test suite must pass before fix is accepted |
The problem with free-form prompts in a team:
- Developer A writes a blog CRUD prompt → gets a working API.
- Developer B writes "blog CRUD" differently → gets a slightly different implementation.
- Developer C wants to review what A and B actually asked the AI → there's no diff, no PR, no audit trail.
- QA finds a bug → nobody knows which prompt version caused it.
- New hire joins → reads 200 chat transcripts to understand the project.
- CTO asks "how much did AI codegen cost this sprint" → zero data.
With pxml in an enterprise:
- Every "prompt" is a file in git → PR reviewable, diffable, revertable.
- Schema (
pxml.xsd) enforces consistent structure across all teams → no more "coding style by who wrote the prompt". bugs_history.xmlserves as a permanent institutional memory → bugs never resurface in any team's work.pxml compileoutputs per-node dollar cost → finance has actual data.- CI/CD pipeline runs
pxml validate && pxml compile --dry-runon every PR → catches spec errors before they reach production. - Onboarding: new dev reads the
.xmlfiles → understands the entire app architecture in 10 minutes, not 2 days of chat archaeology.
Install the compiler globally via npm:
npm install -g @two-tech-dev/pxmlpxml initThis command initializes the folder structure:
project.xml: main config file that imports defined flows and local packages.flows/blog.xml: defines individual nodes (e.g.api.posts.create) containing paths, constraints, and test scenarios.packages/: directory to save local packages (initialized with a sample plugininit-nextjs-project).pxml.json: manifest tracking the pxml version and installed packages.
Via manifest (recommended): add the package URL to pxml.json, then run:
pxml install # or: pxml ipxml.json example:
{
"pxml": "0.4.2",
"packages": {
"ui-ux-components-pxml": "https://github.com/two-tech-dev/ui-ux-components-pxml.git"
}
}This clones each package into packages/<name>/ and binds its editor schema
automatically (skips already-installed ones).
Ad-hoc: install a single package without editing the manifest first:
pxml plugin url-git https://github.com/two-tech-dev/ui-ux-components-pxml.gitBoth commands wire the package's catalog.xml into .vscode/settings.json
so the editor suggests component names, flows and types immediately.
After installation, add an <import> to project.xml and run pxml validate
to generate an alias-aware enriched schema with exact extends autocomplete:
<import package="ui-ux-components-pxml" from="packages/ui-ux-components-pxml" as="uix" />Ensure you set the environment variable ANTHROPIC_API_KEY (or OPENAI_API_KEY if using OpenAI):
export ANTHROPIC_API_KEY="your-api-key"
pxml compile
# Or using OpenAI provider
export OPENAI_API_KEY="your-api-key"
pxml compile --provider openai --model gpt-4o
# Or using Ollama provider locally
pxml compile --provider ollama --model llama3 --baseUrl http://localhost:11434
# Save tokens:
pxml compile --no-autogen-tests # skip AI-generated test files
pxml compile --dry-run # show execution plan without AI callsToken optimization enabled by default:
- Context by dependency — only files from
depends_onnodes are fed to the AI (was: all previously compiled files). - File cap — each file is truncated at ~2000 characters with an elision marker.
- Batch test generation — all test files are generated in a single AI call
(was: one call per node). AI returns marker-separated test files (
### FILE: path). - Single test run — all tests execute in one
vitest run, not one per node. Failures are fixed in dependency order after the batch run. - AI self-verification is opt-in — pass
--verifyto enable it (doubles token cost per node). Default: skip, saving ~2× tokens per node.
pxml testThis compiles the <test> tags into Vitest files and runs them, saving the outcome to .pxml/manifest.json.
If any test fails, instead of regenerating the entire codebase, you can execute a target self-healing fix:
pxml fix --flow=blog.write
# Or using OpenAI provider
pxml fix --flow=blog.write --provider openai --model gpt-4o
# Or using Ollama provider locally
pxml fix --flow=blog.write --provider ollama --model llama3 --baseUrl http://localhost:11434This formulates a minimal context patch prompt and retries local SEARCH/REPLACE edits up to 3 times.
You can document persistent bugs in bugs_history.xml. When you run pxml fix, the compiler automatically aggregates these descriptions and feeds them to the AI to prevent code regressions.
To enable editor validation and autocomplete, link your bugs_history.xml file to the provided bugs.xsd schema:
<bugs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="bugs.xsd">
<bug id="cart.badge" flow="cart.view">
Cart badge count displays 0 despite items being in the shopping cart database. Always fetch active cart status from the backend database route instead of localStorage.
</bug>
</bugs>pxml validateThis validates your XML configuration files. It checks:
- Standard XML schema compliance.
- Nodes defining
<output>fields must contain at least one<test>case (prevents deployment failures due to missing tests; ignoresdb-modelandsetup-commandnodes). - All required inputs declared in
<input>must be supplied in test<given>parameters (either at root, inbody,query, orheaders). - Test
<given>parameters cannot contain extra fields not declared in<input>to prevent spec inconsistencies.
pxml doctorChecks tool environment settings and required environment keys.
pxml migrateUpdates all project XML files (project.xml, flows/*.xml, packages/*/project.xml) to the latest pxml syntax standard:
- Adds
autogen-tests="true" onand` elements - Updates
xsi:noNamespaceSchemaLocationto correct relative paths - Copies latest
pxml.xsdandbugs.xsdschemas to project root
After executing pxml compile or pxml fix, the CLI outputs a comprehensive token usage summary (Input, Output, and Cached tokens) along with an estimated dollar cost based on the active LLM provider rates.
pxml supports non-JS/TS stacks (e.g. python, rust, go) by dynamically adjusting the code generator's prompt guidelines and style directives to match the <project> stack attribute.
When your project imports a package (from git or local packages/),
pxml validate / pxml i automatically overwrites pxml.xsd with an
enriched version that enumerates the exact suggestions your editor should offer:
flowattribute → every flow across all imported packages (auth, ecommerce, marketing, setup, …) plus your project's own flows.typeattribute → all known node types (ui-component, api-route, setup-command, …).extendsattribute → every base component id prefixed with your actual import alias (e.g.uix:auth:login,uix:ecommerce:productGrid). Purexs:enumeration— the editor suggests only valid targets.UiFlowTypeandUiNodeTypeuse a union withxs:string, so custom values still validate without false errors.
No LSP/IDE configuration needed. The enriched schema replaces pxml.xsd
on disk — every editor that reads the file (lemminx, coc-xml, VS Code XML,
IntelliJ) gets the extended type definitions automatically. No OASIS catalog,
no .vscode/settings.json, no LSP init options required.
The original pxml.xsd is backed up to .pxml/schemas/pxml.core.xsd on the
first run. Re-run pxml validate to regenerate (idempotent).
You can control per-project or per-node whether the AI should automatically generate test files. Set autogen-tests="false" on the <project> or <node> element to skip AI test generation (saves token costs). Equivalent CLI flag: --no-autogen-tests.
<project name="my-app" stack="nextjs" version="0.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="pxml.xsd">
...
</project>(Requires VS Code XML extension by Red Hat or equivalent)