The business process automation tool stopped being a .xaml file, and nobody wrote the memo

Every top result for this keyword is a vendor shootout between UiPath, Automation Anywhere, Zapier, Make, Power Automate, Workato and a few workflow designers in between. The comparison is always the same: connectors, triggers, nodes, pricing. Not one of them mentions that on an LLM-driven desktop agent, the automation unit has quietly become a markdown file. This page is the proof, with the Swift installer that copies seventeen of them into your ~/.claude/skills folder using SHA-256 diffing.

M
Matthew Diakonov
11 min read
4.8from 420+
17 bundled skills ship inside the app
SHA-256 checksum diffing on every launch
Markdown + YAML frontmatter only
Signed, notarized, MIT licensed
.xaml (UiPath).atmx (Automation Anywhere)Zapier JSONMake blueprint JSONPower Automate cloud JSONn8n workflow JSONNintex process mapWorkato recipePipedream YAML*.skill.md (Fazm)
17 skills, 1 installer, 0 flow graphs

Seventeen markdown files sit inside the Fazm app bundle right now. On every launch, SkillInstaller.swift walks them, SHA-256s them, and copies only the ones whose digest has changed onto your machine. The install pipeline for your entire automation library is about 170 lines of Swift.

SkillInstaller.swift in the Fazm desktop repo, verified 2026-04-21

What the listicles are still comparing

Pull up any of the top ten pages ranking for this keyword. You will see the same grid every time: connectors, triggers, pre-built templates, pricing tiers, enterprise SSO, RPA readiness. Those are all real, and they all matter. They also all assume the same thing: that an automation is a flow graph stored in a proprietary designer.

That assumption is a holdover. It was true when humans were the only thing reading the tool. Today the runtime is an LLM, and an LLM would rather read a runbook than parse a graph. Once you accept that, the file extension of your "tool" changes. And once the file extension changes, so does the supply chain.

The recorder era's tool

A .xaml or .atmx file produced by a click recorder. Human-unreadable by design. Only editable inside the vendor's Studio. Brittle against any UI refresh. Lives inside an enterprise license.

The iPaaS tool

A JSON document defined inside Zapier, Make, n8n, Workato. Only works when every step exposes an API. Runs in the vendor's cloud. Editable only inside the vendor's canvas.

The LLM-native tool

A *.skill.md file. YAML frontmatter plus prose. Editable in any text editor. Runs wherever your LLM runs. The runtime reads it, then acts on the live macOS accessibility tree. Fazm is the concrete example. ~/.claude/skills/ is the folder.

Where each one still wins

Recorder tools: legacy Windows clients from the 2010s. iPaaS: pure SaaS-to-SaaS hops. Skill files: anything a human could describe in a runbook, including desktop apps, CLIs, native Mac software.

What a Fazm skill actually looks like

Below is a compressed version of travel-planner.skill.md, one of the seventeen files bundled inside the app today. YAML frontmatter tells the LLM what the skill is for. The markdown body is what the LLM reads before acting. There is no designer view, no compiled artifact, no hidden state.

BundledSkills/travel-planner.skill.md
0Skills bundled in the signed Fazm.app today
0-bitCryptoKit SHA digest used to diff each skill
0 LOCTotal size of SkillInstaller.swift
0Flow graphs, node canvases, or recorders involved

The anchor: SkillInstaller.swift

This is what runs on every Fazm launch. Auto-discover bundled skills by filename pattern. Compute a SHA-256 hex digest of the bundled file. Compare it against whatever is currently at ~/.claude/skills/<name>/SKILL.md. Copy only the ones whose digest has changed. That is the update mechanism for your whole automation library. Yes, the full file is this short.

Desktop/Sources/SkillInstaller.swift

How a skill travels from source repo to your Mac to your LLM

*.skill.md
App build
Code signing
SkillInstaller.swift
~/.claude/skills/
LLM context
AX tree of any Mac app

Recording a workflow vs writing a skill

The motion you go through as an operator is almost the opposite in the two worlds. Here is what actually changes when the automation unit becomes a markdown file.

What you do when you build the tool

Open the vendor's Studio. Start a recorder. Click through the target app, watching the designer build a flow graph of imageMatch(), click(x,y), typeInto() nodes. Handle every edge case by adding a conditional branch in the designer. Re-record when the UI refreshes. Pay per bot seat. Save the file as a .xaml or .atmx only that Studio can open.

  • Proprietary file extension, proprietary editor
  • Pixel coordinates baked into the flow
  • Breaks on dark mode / resolution change / UI refresh
  • One license per seat, one runtime per vendor

The automation unit, side by side

The feature grids every listicle uses skip this row. It is the one that changes what you ship.

FeatureClassic BPA / iPaaS toolsFazm (skill.md + AX tree)
File format of the automation unit.xaml, .atmx, proprietary JSON, cloud-only definitionsPlain markdown with YAML frontmatter
Authoring surfaceVendor Studio / canvas / flow designerAny text editor, or the LLM writes the skill for you
Runtime that executes the toolProprietary runtime engine, often a separate serviceThe LLM reads the skill, then drives the UI via AX tree
What happens on a UI refreshPixel or template-matched steps break; re-record requiredWorks if AXRole and label survived, which they usually do
DistributionSeparate management UI, enterprise license, cloud syncShips inside the signed app bundle; SHA-256 checksum diff on launch
Unit of authoringFlow graph across dozens of node instancesOne markdown file = one skill = one tool
Who can edit itSomeone trained on the specific vendor StudioAnyone who can read a runbook

Works on macOS today. If your process is Windows-only and lives inside an app from 2011 with no AX support, you are still in classic RPA territory.

The seventeen skills shipping inside the app today

You can count them yourself: list Desktop/Sources/BundledSkills/ in the repo, or list ~/.claude/skills/ on your own Mac after a launch. These are the entries Fazm auto-discovers by filename pattern and syncs to disk through the SHA-256 loop.

Each one is a single *.skill.md file in the repo

Bundled skill library

ai-browser-profile

Extract identity and saved accounts from real browser storage

canvas-design

Produce HTML/SVG canvas artwork on request

deep-research

Multi-source research with citation pass

doc-coauthoring

Long-form collaborative writing across pages

docx

Read, edit and render .docx files natively

find-skills

Route the model to the right installed skill

frontend-design

Produce Tailwind/React UI from a spec

google-workspace-setup

Walk a user through the Google OAuth one-time setup

pdf

Extract and manipulate PDF content

pptx

Build .pptx slide decks end-to-end

social-autoposter

Post and track across Reddit, X, LinkedIn, Moltbook

social-autoposter-setup

One-time setup flow for the poster

telegram

Send and read Telegram messages via telethon

travel-planner

Full itinerary, budget, packing, cultural notes

video-edit

Scripted video editing for short-form output

web-scraping

Python-based web data extraction

xlsx

Read, edit and render Excel workbooks

Where the 0 comes from, concretely

The SkillInstaller reads Bundle.resourceBundle.resourceURL, appends BundledSkills, and calls FileManager.default.contentsOfDirectory. It then keeps files whose pathExtension == "md" AND whose filename (minus the final extension) ends in .skill. Today that filter matches seventeen entries. Adding an eighteenth is literally dropping a new *.skill.md file into the folder. No registry edit, no code change, no designer build step.

The four steps of shipping a new tool

A classic BPA release cycle is: record a bot in Studio, export, push to orchestrator, assign to seats. A skill-based release is four textual steps, and three of them are git.

1

Write the skill as prose

Create a new *.skill.md in Desktop/Sources/BundledSkills/. YAML header with name and description. Markdown body explaining, in plain English, the workflow, the apps it will touch, and the expected output.

2

Commit and cut a release

Codemagic builds the signed macOS app. The new *.skill.md goes into the signed bundle at Contents/Resources/BundledSkills automatically because SkillInstaller auto-discovers by filename.

3

Sparkle pushes the update

User's existing Fazm.app checks for the next version, Sparkle downloads the new signed bundle, users relaunch.

4

SHA-256 diff installs the skill

On the next launch, SkillInstaller computes a SHA-256 digest of every bundled *.skill.md, compares it against ~/.claude/skills/<name>/SKILL.md, and overwrites only the ones whose digest changed. A toast tells the user which skills were updated.

When a markdown-skill tool beats a flow-graph tool

  • Your process lives on one person's Mac, not across five enterprise teams
  • At least one step touches a native Mac app without an API
  • You want non-engineers to author and maintain the automation
  • You care whether it still works after next macOS update
  • You need the automation in git, reviewable as a diff
  • You would rather pay for an LLM than a per-bot seat

One more practical note: the AX tree is what makes this honest

A markdown skill would not be enough on its own. The LLM still needs a way to see and act on the target app. Fazm solves that through a second binary bundled next to the main app: Contents/MacOS/mcp-server-macos-use, a Swift MCP server that calls AXUIElementCreateApplication(pid) and walks kAXChildrenAttribute down to every interactive element.

Pairing "skill as markdown" with "input as accessibility tree" is what makes the whole thing survive the next Mail redesign. The skill says what to do. The AX tree says where it is, by role and by label. Neither one cares what the pixels look like.

Want one of your workflows turned into a skill file?

Bring the runbook. We will walk through how it becomes a *.skill.md that ships with Fazm.

Book a call

About the skill-as-tool model

What is a business process automation tool in 2026?

The textbook answer is software that moves a repeatable business process off a human's plate, usually by stitching together clicks across apps. That definition was written for the recorder era, when the tool was a .xaml workflow in UiPath or a ScriptRunner macro in Automation Anywhere. The 2026 answer is different on an LLM-driven desktop agent. The tool is whatever the model reads before it acts. For Fazm on macOS, that is a markdown file with a YAML frontmatter header and a few hundred lines of plain English. No canvas, no nodes, no recorded trace.

Can a markdown file really count as an automation "tool"?

It does when the runtime is an LLM. The LLM reads the skill file into its context window, sees a description plus a quick-start table plus the shell commands and SQL snippets the author included, and then drives the user's Mac through the macOS accessibility tree. The skill file plays the same role a .xaml plays in UiPath: it is the unit of automation you edit, check into git, and ship. But because the runtime is reading prose rather than executing a flow graph, the author writes English instead of wiring nodes. That collapses the build step into writing a runbook.

How many skills ship inside Fazm today, and what are they?

Seventeen. They live at Desktop/Sources/BundledSkills/ in the Fazm desktop repo and get copied into the signed app bundle at build time. The list today: ai-browser-profile, canvas-design, deep-research, doc-coauthoring, docx, find-skills, frontend-design, google-workspace-setup, pdf, pptx, social-autoposter, social-autoposter-setup, telegram, travel-planner, video-edit, web-scraping, xlsx. Each is a single *.skill.md file. There is no separate binary for each one. The LLM reads them on demand.

How does a bundled skill get from the app bundle onto a user's Mac?

On launch, Fazm runs SkillInstaller.swift. The installer scans Bundle.resourceBundle/BundledSkills/ for files whose path extension is "md" and whose filename also ends in ".skill", builds a list of skill names, and for each one reads a SHA-256 hex digest of the bundled file using CryptoKit's SHA256.hash. It compares that digest against the file currently at ~/.claude/skills/<name>/SKILL.md. Same digest, nothing happens. Different digest, the old file is removed and the bundled file is copied in. That is it. The whole update pipeline for all 17 skills is about 170 lines of Swift.

Where can I verify the SHA-256 mechanism?

Open Desktop/Sources/SkillInstaller.swift in the Fazm repo. Line 30 to 40 is the auto-discovery: it filters `contentsOfDirectory` for `pathExtension == "md"` then for `deletingPathExtension().pathExtension == "skill"`. Line 58 to 62 is the digest function: `let digest = SHA256.hash(data: data); return digest.map { String(format: "%02x", $0) }.joined()`. Line 100 to 141 is the install/update loop that compares the two digests and either skips, overwrites, or installs. Line 177 to 178 is the small npm-skill registry for skills that ship outside the bundle (today: social-autoposter).

How is this different from UiPath, Automation Anywhere, Zapier, Make, or Power Automate?

Those tools store the automation unit in a binary or semi-binary artifact that only their own designer can edit. UiPath workflows are XAML. Automation Anywhere bots are .atmx. Zapier zaps are proprietary JSON. Make scenarios are a blueprint JSON. Power Automate flows are a cloud-stored JSON graph. All five require their own editor to author and their own runtime to execute. A Fazm skill is a plain text file that anyone can read in any editor and that runs inside any LLM that loads the file. The author is the LLM user; the runtime is the LLM.

Does this mean anyone can write a Fazm tool?

Yes, and that is the design. A skill file starts with a YAML frontmatter header (`name`, `description`, optional `user_invocable`), followed by a short markdown body that tells the model how to behave. The bundled skills range from 42 lines (frontend-design) to 856 lines (deep-research). The pattern you copy is: describe the intent, list the steps the model should take, include example shell commands or SQL, note the apps it will drive through the accessibility tree. That is also how a junior teammate would write a runbook for a senior one. The skill file and the runbook converge.

What replaces the "record a workflow" step?

Nothing replaces it because nothing is recorded. You describe what you want done. The model reads the skill, queries the live macOS accessibility tree with AXUIElementCreateApplication and kAXChildrenAttribute, and acts on the real structural elements (AXButton, AXTextField, AXMenuItem) rather than the remembered pixel locations of a previous run. When Apple reskins Mail in the next macOS point release, a recorder-era automation breaks. A skill-plus-tree automation keeps working because the roles and labels have not moved, only the chrome.

What happens when I edit an installed skill?

Your edits live at ~/.claude/skills/<name>/SKILL.md. The next time Fazm launches, if the bundled version inside the app has not changed since the last install, your edits survive: the installer's SHA-256 check of the bundled file against its own prior state is a no-op path. If the bundled version has changed (you installed a new Fazm release), your edits are overwritten with the new bundled skill, and a toast fires telling you which skills were updated. This is intentional: skills-in-bundle are treated as first-party code that the app owns. Fork the skill outside the bundled-name list if you want total control.

Is the whole thing open source and verifiable?

The Fazm desktop app is public. The 17 .skill.md files are in Desktop/Sources/BundledSkills/. The installer that picks them up is Desktop/Sources/SkillInstaller.swift. The MCP server it pairs with (the binary that reads the macOS accessibility tree at runtime) is mediar-ai/mcp-server-macos-use. The agent communication bridge that wires LLMs to both is in acp-bridge/src/index.ts in the same repo. Every claim in this guide is a `grep` away.