status = "ok" is not one of the five values in the Devicetree Specification v0.4
(okay, disabled, reserved, fail, fail-sss).
dtc has no opinion about it - it is just a string. Zephyr marks the node present only for the exact
value okay, so the sensor quietly leaves the build and you debug the driver instead of the line.
23 rules, 50 snippets. This page runs the same 23 rules the extension runs, in your browser, on nothing you upload.
Everything above is free and needs no key, no account and no network - every one of the 23 rules and all 50 snippets run on the file you have open, for as long as you like. The licence buys scale, a file you can hand over, and repetition:
One-time, $29. A freelance embedded software engineer bills about $103 an hour (contractrates.fyi, 2026); a staff embedded firmware engineer's hour averages $58.66 (ZipRecruiter, June 2026). Works offline; the key is checked once, then every 7 days.
It reads a config file line by line and reports the spellings that parse but do not mean what you
wrote - status = "ok", a compatible with no comma, address-cells
without the #, an unquoted TOML edition. 23 rules over seven languages, plus
50 snippets. No toolchain, no build context, no network.
They highlight and complete, and inside a configured Zephyr or nRF context they resolve bindings -
that part they do better than this pack. They do not grade a bare .overlay pasted out of a
vendor forum, and they say nothing about the TOML, .properties, .ahk,
.rpy or .ink files sitting in the same repo.
Because enabled is the English word and every other config format in the repo uses it.
Devicetree does not: the value that turns a node on is okay and nothing else. It is the exact
shape of mistake that reads correct and builds clean.
Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.
npmMCP server (npx)Docker Hubnpx @readystack/devicetree-config-language-pack <file> npx @readystack/devicetree-config-language-pack --mcp docker run --rm -v "$PWD:/w" getreadystack/devicetree-config-language-pack /w
Team? One key for every ReadyStack linter, 5 seats, $149 once
This page is the working piece. The full pack has everything below.
status = "ok" compiles clean and the node never appears. 23 rules over 7 config languages, on the file you have open.
A freelance embedded software engineer bills about $103/hour (contractrates.fyi, 2026); a staff embedded firmware engineer's hour averages $58.66 in the US (ZipRecruiter, June 2026). One node silently dropped from a build costs an
Buy the full version — $29· ReadyStack
Real numbers from this tool, line by line.

Your board comes up. The console prints. The I2C sensor you added last night is not there.
So you do what everyone does. You check the pull-ups. You scope SDA. You add a print to the driver's init hook and it never fires, so you go and read the driver, and about two hours later you scroll past this:
&i2c1 {
status = "okay";
bme280@76 {
compatible = "bosch,bme280";
reg = <0x76>;
status = "ok";
};
};
status = "ok". Two letters short, and the build never said a word.
status is a string property. dtc will compile any string you put there: "ok", "yes", "banana". The value is not the compiler's business.
It is the binding's business. The Devicetree Specification v0.4 defines exactly five values for status: okay, disabled, reserved, fail and fail-sss. Zephyr's generated headers mark a node as present only for the exact string okay. Anything else, including "ok", "enable" and the very natural-looking "enabled", is simply not okay, so the node is not enabled, the device entry is never emitted, and there is nothing on the bus to talk to.
No error. No warning. A clean build and a missing sensor.
Once you start looking for this shape, a bring-up repo is full of it. Every line below compiles:
compatible = "acme-controller"; /* no comma, so it matches no binding and the driver never probes */
address-cells = <1>; /* no leading #, so the parent supplies no address cell count */
interrupt-parent = <2>; /* a literal where a phandle reference belongs */
phandle = <1>; /* hand-set, and free to collide with a generated value */
sensor@0x40005400 { }; /* a unit address written with 0x, compared as plain hex */
None of these is a syntax error. They are all spelling mistakes in a language where the spelling is the semantics, and every one of them fails somewhere far away from the line that caused it: at probe time, at link time, or on the bench with a scope in your hand.
enabled is the English word for what you are trying to do, and every other config format in the same repository agrees with it:
mp.metrics.enabled=true
# TOML - correct
enabled = true
// devicetree - wrong, and it compiles
status = "enabled";
A model generating an overlay is pattern-matching against a world where enabled is right almost everywhere. Devicetree is the exception, and the exception is not visible in the output. This is the category of mistake that reads correct, reviews correct and builds correct.
The .dts file is rarely alone. The manifest next to it:
[package]
edition = 2021 # rejected - the year is a string
version = 1.0.0 # not a number; TOML has no bare version literal
requires-python = >=3.9 # PEP 621 wants a quoted specifier
The service config next to that:
com.acme.InventoryClient/mp-rest/uri=https://inventory.svc:8443
The MicroProfile Rest Client key is /mp-rest/url. Any other spelling is not an error - it is ignored, and the client silently falls back to the value baked into the annotation. Then there is AutoHotkey v1 syntax in a v2 script, a Ren'Py label with no colon, an Inkling file still declaring inkling "1.0". All of them plain text as far as the editor is concerned.
A VS Code pack with 23 of these rules and 50 snippets, covering devicetree, TOML, MicroProfile .properties, AutoHotkey v2, Ren'Py, Swift and Inkling. Ten of the 23 rules are devicetree; the rest are the files that sit around it.
Run it on the file you have open and you get line numbers and a sentence explaining what the correct spelling is and why. That part is free: all 23 rules, all 50 snippets, no key, no account, no network call and no build context. It works on a bare .overlay you pasted out of a vendor forum, which is exactly where the free devicetree extensions stop, because they want a configured Zephyr or nRF context first.
The licence changes the scale rather than the rules. It runs the same 23 rules over every file in the workspace in one pass, writes the findings into the repo as CSV, JSON or HTML so you can attach them to a review, and re-runs the check on every save instead of when you remember to look.
There is a browser version that runs the same 23 rules on text you paste, with nothing uploaded, if you want to check one file before installing anything.
Two hours of driver debugging is worth more than a config linter. That is the whole argument.
It reads a config file line by line and reports every spelling that parses but does not mean what you wrote: status = "ok", a compatible string with no comma, address-cells without the leading hash, an unquoted TOML edition. Twenty-three rules across seven languages and fifty snippets, with line numbers. No toolchain, no build context, no network.
Firmware and embedded engineers doing Zephyr or embedded Linux board bring-up inside VS Code. It is aimed at the repo where .dts, .dtsi and .overlay files sit beside a Cargo or pyproject TOML, MicroProfile .properties, AutoHotkey v2 bench scripts, Ren'Py or Inkling - the files the editor still renders as plain text.
They highlight and complete, and inside a configured Zephyr or nRF context they resolve bindings better than this pack does. What they do not do is grade a bare .overlay pasted out of a vendor forum, or say anything about the TOML, .properties, .ahk and .rpy files in the same repo. A chatbot will hand you status = "enabled" without blinking.
Free covers the file you have open, completely: all twenty-three rules run, all fifty snippets insert, no key is asked for and nothing expires. The licence changes scale, not rules - every file in the workspace at once, the findings exported as a CSV, JSON or HTML file, and a re-check that fires on every save.
A staff embedded firmware engineer's hour averages $58.66 in the United States (ZipRecruiter, June 2026), and a freelance embedded software engineer bills about $103 (contractrates.fyi, 2026). One sensor missing from a build because of a four-letter status value costs an afternoon at the bench, not half an hour.
One question, answered by the person who built it. Your email only if you want the answer sent.