Catch Power Apps problems before they reach production
Building in public
I built a code quality tool for Power Apps.
Easel reads canvas app source, finds problems before deployment, and brings linting, semantic diffs, dependency analysis, and CI gates to Power Apps development.
Power Apps canvas applications increasingly live in Git, but much of the development workflow still begins and ends in a visual editor. Once an app grows beyond a few screens, reviewing it becomes difficult. A tiny formula change can affect a distant control. An inaccessible button can hide in plain sight. A pull request can show text changes without explaining what they mean.
So I built Easel, a free, open-source command-line tool that treats canvas app source as source code. It reads pa.yaml, parses Power Fx, builds a symbol table and dependency graph, then turns that model into useful feedback for local development and CI.
Power Apps needs a tighter dev loop
Tenant-side checks are useful, but they arrive late in the workflow. I wanted feedback at the moment a maker changes a formula or opens a pull request, using the same unpacked source that the team already commits.
Easel runs locally over a source folder, an .msapp file, or a solution package. It can spot non-delegable queries, N+1 patterns, unused variables and media, heavy App.OnStart logic, missing accessible labels, duplicate formulas, embedded credentials, and other problems that are easy to miss in a visual review.
The goal is simple: make a canvas app reviewable before it becomes a deployment problem.
$ easel lint ./MyApp Src/scrHome.pa.yaml 23:9 warning PA1009 Button 'btnSubmit' has no AccessibleLabel. 27:23 info PA1010 'If' nested 3 deep. Src/App.pa.yaml 3:14 warning PA1003 Variable 'gblUnused' is assigned but never read. 3 findings: 2 warnings, 1 info
| Question | With Easel | Manual review alone |
|---|---|---|
| When feedback arrives | Locally and on every pull request | Often during testing or release |
| What a formula change means | Semantic Power Fx diff | Text-level comparison |
| Where a symbol is used | Definitions, uses, and impact graph | Search across screens and formulas |
| How results integrate | Console, JSON, SARIF, HTML | Notes and screenshots |
| What leaves the machine | Nothing during analysis | Depends on the review process |
One app model, many useful answers
A linter alone would only solve part of the problem. The same parsed app model can answer broader engineering questions: what depends on this variable, which screens are orphaned, which formula became more complex, or whether a renamed control is really a deletion and an addition.
- LoadRead unpacked
pa.yamldirectly, or use the local pac CLI for packaged inputs. - ParseTurn Power Fx formulas into abstract syntax trees instead of treating them as plain text.
- ConnectBuild symbols and dependencies once, then share them across every command.
- AnalyzeRun lint rules, metrics, dead-code checks, impact analysis, secret scanning, and semantic diff.
- ReportReturn readable terminal output or stable machine formats for automation.
This architecture makes the commands consistent with each other. easel analyze --impact gblUser can trace what would be affected by a change. easel diff compares formulas at the syntax-tree level, so whitespace does not become noise and a real change can be described in terms of identifiers and functions.
Make the pull request the review surface
Easel is designed to run before a change reaches a tenant. Its exit codes can gate a build by severity, while SARIF output places findings directly on the affected lines in GitHub code scanning. A semantic diff can also produce Markdown for a pull request comment.
That creates a familiar engineering loop: change the app, commit the unpacked source, open a pull request, and see new quality findings beside the code. Teams adopting Easel on an existing app can write a baseline first, so CI reports new findings without forcing an immediate cleanup of every historical issue.
Validated on real applications.
Easel has parsed more than 2,500 production formulas with zero parse errors in the project validation set.
Deterministic first, AI only by choice
The core analysis does not use AI and makes no network calls. There is no telemetry, no usage counter, and no cloud service behind the linter. That boundary matters because canvas source contains business logic and can also contain the secrets that Easel is trying to find.
Optional explain and fix commands can send one finding and its formula context to an OpenAI-compatible provider. They are dry runs unless --send is passed. The exact prompt is visible first, and a suggested fix is reparsed with Power Fx before it is shown. Easel never applies an AI-generated change automatically.
Read-only unless you ask for a rename
Analysis commands do not modify the input. The preview rename command is the exception: it performs a symbol-aware rename, repacks the app through pac, and verifies the result. Keeping this boundary explicit makes Easel safe to add to an existing development workflow.
Open source is part of the trust model
Easel is available under the MIT license. You can inspect every rule, see how formulas are parsed, verify when network access is possible, add rules for your own standards, or run the self-contained binary entirely offline.
Treat your canvas app like source code.
Install Easel, point it at one app, and get the first report locally. Then add the same deterministic check to your next pull request.
Comments
Post a Comment