{"slug": "explain-to-me-in-simple-technical-english", "title": "Explain to me in Simple Technical English", "summary": "A developer found that asking AI coding assistants to explain code in 'Simple Technical English' improved clarity, and traced the phrase to the ASD-STE100 Simplified Technical English standard, a controlled natural language used in aviation maintenance since 1986. Lucian Ghinda, the developer, ran an informal experiment with Claude and Codex on four code samples, comparing outputs with and without the STE-inspired instruction, and published the prompts, code, and results on GitHub.", "body_md": "Last week I read something about a standard for writing technical documentation in plain, unambiguous English. I did not save the link and could not remember the exact name, nor did I have time to search for it.\n\nThis week, I made changes to a part of the codebase I wasn’t very familiar with, so I had to chat with Claude and Codex to understand it better.\n\nI observed something that had been bothering me for a while: Claude keeps reaching for complicated words, abstractions, and slightly fancy descriptions instead of simple domain terms. Thus I half-remembered this idea, and I started saying:\n\nExplain to me in Simple Technical English\n\nI have typed this phrase many times this week, and I felt it worked very well for me, so I have put it in the user memory or in the system instructions for all agents.\n\nLast night I remembered to search for fuzzy thing that I was rememering and found it: **ASD-STE100 Simplified Technical English**.\n\nBut this got me thinking: I wrote “Simple Technical English,” and this standard is called “ASD-STE100 Simplified Technical English”. If so, would my output be better if I had used the proper term?\n\nThus, I did some research about it. You can see the entire experiment I run on Claude and Codex [here](https://github.com/lucianghinda/llm-experiments) where I shared the prompts used, the code that I used for testing and the full results.\n\n[Simplified Technical English](https://www.asd-ste100.org/about_STE.html) is a controlled natural language. It began in the late 1970s as AECMA Simplified English and was first released in 1986. The European airline industry wanted aircraft maintenance manuals that a non-native English speaker could not misread.\n\nIt is maintained by the ASD Simplified Technical English Maintenance Group, and it has two parts:\n\nThe rule I like most is this one: each approved word has **one meaning and one part of speech**. As a non-native English speaker, this feels very good to me in interactions with LLMs.\n\nI also liked the hard limits, such as the requirement that descriptive sentences be no more than 25 words. This is because the official goal is for STE to “make technical texts easier to understand for all readers” and “reduce Human Factor risks.”\n\nIt sounds great to me. If a maintenance manual is ambiguous, an aircraft is repaired incorrectly. The standard exists because vague technical prose has a body count.\n\nLLMs are producing a lot of text, and reading it takes a lot of effort. Because of the fancy language they sometimes use (looking at you, Claude), there is a risk of misunderstanding or, even worse, a kind of understanding fatigue, and the chances of approving or going on with something wrong are increasing.\n\nI chose 4 pieces of code from two of my own projects, and for each one I wanted to test 3 cases:\n\nNothing else was added, removed, or changed in the entire system prompt, harness, or context. All agents got the same prompts in the same context and were running on the same setup I have.\n\nI orchestrated all this via Claude, which ran the agents (including its own): three Claude and three Codex for each piece of code for each experiment. I ran two full sessions so we could we collected more data. I stopped after two sessions because this is not a rigorous study but rather something I intended to check.\n\nThe code that they got was looking like this:\n\n| # | Target | Size | Why this one |\n|---|---|---|---|\n| 1 | A Rails `Idempotency` concern |\n95 lines | Control-flow complexity: callback ordering and a hand-dispatched rescue handler |\n| 2 | A single method, `build_blocks` |\n11 lines | Smallest unit, and dense with domain words already in the code |\n| 3 | A single method, `count_transpositions` |\n12 lines | Same size as #2 but with no domain vocabulary, pure algorithm for similarity |\n| 4 | A whole query object, `DraftQuery` |\n130 lines | Same size as #1, but data shaping instead of control flow |\n\nMy main complaint was that the model was “inventing” or picking abstractions that obscure real understanding, so I wanted to offer a couple of situations that could push the model in that direction.\n\nI will not write about each example run here, as it would become a very long article. But you can read all of [them in the repo that I published at github.com/lucianghinda/llm-experiments](https://github.com/lucianghinda/llm-experiments).\n\nSo allow me share the first one, as it is a simple concern for a controller that implements a idempotent write, and it includes a part that calls something like `rescue_with_handler`\n\nbecause `rescue_from`\n\nruns outside the `around_action`\n\n.\n\nHere is the part that I give to LLMs to explain: why is there a `begin`\n\nblock here:\n\n```\n# `rescue_from` runs at the controller level, *outside* this around_action,\n# so any post-yield code is skipped when the action raises.\nbegin\n  yield\nrescue StandardError => error\n  raise unless rescue_with_handler(error)\nend\n\nwrite_idempotency_entry(cache_key, body_hash) if response.status >= 200 && response.status < 500\n```\n\nI sent this to Claude and Codex with the same instructions for each agent. The prompts are a bit different between agents, but as the purpose was not to compare Claude with Codex but to compare them with themselves in terms of how they behave, I think it is good enough.\n\nHere is Claude with no style instruction:\n\nThe problem is a layering one.\n\n`rescue_from`\n\nhandlers registered by`ErrorResponder`\n\nare installed at the controller level, which is outside this`around_action`\n\n. If the action raises, the exception propagates out of the around block first, and everything after`yield`\n\nis skipped.\n\nHere is Claude asked for Simple Technical English:\n\nThis block looks strange. The comment in the file describes the reason.\n\nRails runs\n\n`rescue_from`\n\nhandlers at the controller level. That level is outside the`around_action`\n\n. If the action raises an error, Rails immediately leaves the wrapper. The code after`yield`\n\nnever runs. The save step is lost.\n\nAnd here is Claude asking for ASD-STE100:\n\nRails keeps the\n\n`rescue_from`\n\nhandlers at the controller level. These handlers operate outside of the`around_action`\n\ncallback. If the action raises an error, Rails goes directly to a handler. Thus, the code after the`yield`\n\ndoes not run.\n\nI think I prefer the second one, but it depends on the person.\n\nI have shared only a small part of the entire response here. You can read all of them here.\n\nI stripped the code fences, tables, and headings from every output and measured only the text; for me,e is the explanation the agent returned.\n\nI have created this table. Each cell holds two separate measurements, run 1 then run 2, so `18.6 / 17.4`\n\nmeans the first run averaged 18.6 words per sentence and the second run 17.4.\n\n```\ntarget                 Claude ctrl    Claude STE    Claude ASD     Codex ctrl\n-----------------------------------------------------------------------------\n01 concern             18.6 / 17.4    8.1 / 8.3     9.7 / 9.8     11.7 / 13.9\n02 method, domain      16.9 / 19.3    9.1 / 8.8    10.2 / 10.3    10.7 / 13.8\n03 method, algorithm   17.5 / 16.3    9.3 / 9.9     9.0 / 10.3    11.9 / 10.5\n04 query object        19.6 / 17.0   10.7 /  9.4   11.0 / 10.6    12.2 / 15.0\n```\n\nMy reading of these results is:\n\nI will also share the results below for Codex, but I included the control here to show that, by default, even in the control experiment, Codex outputs fewer words.\n\nI did not expect the control number to be that stable between the two runs, and maybe I should have run more runs, but that was the time I had. But one thing to notice is that it appears not to be so dependent on the code itself. The averages and median are both very, very close:\n\n| set | values | average | median |\n|---|---|---|---|\n| first run | 18.6, 16.9, 17.5, 19.6 | 18.15 |\n18.05 |\n| second run | 17.4, 19.3, 16.3, 17.0 | 17.50 |\n17.20 |\n| all 8 pooled | — | 17.83 |\n17.45 |\n\nA second observation here is looking at the vocabulary that Claude used in the control group:\n\n```\nexplicit(2) tradeoff fingerprint corrupting degrades snapshot\ndeliberately deterministic contract essentially dispatches\npropagates installed layering subtle reconstruction fingerprints\nnamespaced engages machinery quota consequence deliberate\nconvention encoded\n```\n\nAll of these are English words, and some we might use in day-to-day interactions, but together they create a fog.\n\nTheir usage went from 26 (the control) to 6 with the vague clause and to 1 with the strict one. In the second run, the same experiment gave 14, then 1, then 0.\n\nWhile the numbers vary widely, I can see a trend I like: the use of those foggy words is decreasing.\n\nI run Codex via orchestration with Claude, but I also replicated the results by running them from Codex (a kinda 3rd semi-run - just Codex form inside Codex).\n\n```\n| Target | Codex ctrl | Codex STE | Codex ASD | Claude ctrl |\n|---|---|---|---|---|\n| 01 concern | 11.7 / 13.9 | 10.7 / 11.4 | 9.6 / 8.3 | 18.6 / 17.4 |\n| 02 method, domain | 10.7 / 13.8 | 15.1 / 19.4 | 9.3 / 9.9 | 16.9 / 19.3 |\n| 03 method, algorithm | 11.9 / 10.5 | 13.9 / 11.1 | 8.3 / 8.9 | 17.5 / 16.3 |\n| 04 query object | 12.2 / 15.0 | 11.0 / 11.5 | 8.3 / 8.3 | 19.6 / 17.0 |\n```\n\nLooking at the results, we can see that Codex by default writes succinct statements. “Simple Technical English” does not make it succinct; in some runs, it even made the statements longer than the control.\n\nBy default, Codex is a better fit to explain code than Claude because it is shorter and simpler.\n\n| set | values | average | median |\n|---|---|---|---|\n| left number | 11.7, 10.7, 11.9, 12.2 | 11.63 |\n11.80 |\n| right number | 13.9, 13.8, 10.5, 15.0 | 13.30 |\n13.85 |\n| all 8 pooled | — | 12.46 |\n12.05 |\n\nAnd this makes the entire experiment more about Claude than Codex, as Codex is already brief by default.\n\nYou can see here a comparison of the control run:\n\n| set | Claude ctrl | Codex ctrl |\n|---|---|---|\n| run 1 — values | 18.6, 16.9, 17.5, 19.6 | 11.7, 10.7, 11.9, 12.2 |\n| run 1 — avg / median | 18.15 / 18.05 |\n11.62 / 11.80 |\n| run 2 — values | 17.4, 19.3, 16.3, 17.0 | 13.9, 13.8, 10.5, 15.0 |\n| run 2 — avg / median | 17.50 / 17.20 |\n13.30 / 13.85 |\n| all 8 pooled — avg / median | 17.825 / 17.45 |\n12.45 / 12.05 |\n\nStyle and vocabulary are just one side of using LLMs to understand codebases. The second part is making sure the explanation still tells me what I should know or pay attention to.\n\nThus, I went through each of the four source files and wrote six facts about each. Things like: “there is no lock, so two concurrent first requests both execute” or “`created_at`\n\nis stored but never read”, “this `until`\n\nloop would spin forever if the invariant from `count_matches`\n\never broke”.\n\nFor experiments 2, 3, and 4, I picked those facts from the source before reading a single output. For experiment 1, I had already read the control run, so that row is weaker evidence than the other three.\n\nThen I checked which one of those facts show up in which output and gave it a score.\n\nRun 1:\n\n| Target | Claude ctrl | Claude STE | Claude ASD | Codex ctrl | Codex STE | Codex ASD |\n|---|---|---|---|---|---|---|\n| 01 concern | 6 | 6 | 3 | 4 | 2 | 2 |\n| 02 method, domain | 5 | 6 | 2 | 3 | 1 | 1 |\n| 03 method, algorithm | 6 | 3 | 5 | 4 | 2 | 4 |\n| 04 query object | 6 | 6 | 4 | 6 | 2 | 3 |\ntotal out of 24 |\n23 |\n21 |\n14 |\n17 |\n7 |\n10 |\n\nRun 2:\n\n| Target | Claude ctrl | Claude STE | Claude ASD | Codex ctrl | Codex STE | Codex ASD |\n|---|---|---|---|---|---|---|\n| 01 concern | 6 | 6 | 4 | 3 | 1 | 3 |\n| 02 method, domain | 6 | 6 | 1 | 4 | 1 | 1 |\n| 03 method, algorithm | 6 | 4 | 4 | 4 | 3 | 2 |\n| 04 query object | 6 | 6 | 2 | 2 | 5 | 2 |\ntotal out of 24 |\n24 |\n22 |\n11 |\n13 |\n10 |\n8 |\n\nOr to see this in some other way:\n\nHere I calculated averages and medians of missed facts:\n\n| Comparison | avg missed | median missed | min | max | total lost | relative loss |\n|---|---|---|---|---|---|---|\n| Claude ASD − ctrl | 2.75 |\n2.5 |\n+1 | +5 | 22 of 47 | 46.8% |\n| Codex ASD − ctrl | 1.50 |\n2.0 |\n0 | +3 | 12 of 30 | 40.0% |\n| Claude STE − ctrl | 0.50 |\n0.0 |\n−1 | +3 | 4 of 47 | 8.5% |\n| Codex STE − ctrl | 1.63 |\n2.0 |\n−3 | +4 | 13 of 30 | 43.3% |\n\nA couple of conclusions from this:\n\n`0.50`\n\nand a median of `0.0`\n\nwith even a case where it got an extra fact that the control did not provide.To summarize: For Claude, “Simple Technical English” (shortened to STE in the tables I shared) performs better than “ASD-STE100” for explanations that include code-based facts. While for Codex both “Simple Technical English” and “ASD-STE100” perform worse, and by default Codex responds with fewer facts about code than Claude, but the answer is short.\n\nI thought that the documented algorithm (ASD-STE100) would perform better because it has explicit instructions to follow. But it seems the more blurry instruction “Simple Technical English” performed better.\n\nI also believed that when I asked for “Simple Technical English,” it would also remain brief, but this was not the case in all runs.\n\nI have added this to the Claude user memory:\n\nWhen explaining code or systems to me, use Simple Technical English. Short sentences. One idea per sentence. Use the domain words that already exist in the code instead of inventing abstractions for them.\n\nI am keeping “Simple Technical English” because the experiment showed it performs well when removing “foggy words”.\n\nI added “use domain words that already exist” to instruct it to reuse those concepts we use elsewhere in the codebase. This also could be an experiment on its own when I have time.\n\nI am putting this in the user memory cause I want it for all my interactions with Claude.\n\nI am not making any changes to Codex, as it seems to be already doing so from a “foggy” or “brief” perspective. Do they have a system prompt in the harness about this? I did not have time to dig deeper.\n\nAll 60 raw outputs, the exact prompts used for every run, and the measurement scripts are in the [ experiments/](https://github.com/lucianghinda/llm-experiments) folder next to this article. What the independent Codex arm does and does not control is written up in\n\n`RUN-NATIVE-PROVENANCE.md`", "url": "https://wpnews.pro/news/explain-to-me-in-simple-technical-english", "canonical_source": "https://allaboutcoding.ghinda.com/explain-to-me-in-simple-technical-english/", "published_at": "2026-08-14 06:12:41+00:00", "updated_at": "2026-08-21 20:44:20.144372+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-tools", "natural-language-processing"], "entities": ["Lucian Ghinda", "Claude", "Codex", "ASD-STE100 Simplified Technical English", "GitHub", "AECMA Simplified English", "ASD Simplified Technical English Maintenance Group"], "alternates": {"html": "https://wpnews.pro/news/explain-to-me-in-simple-technical-english", "markdown": "https://wpnews.pro/news/explain-to-me-in-simple-technical-english.md", "text": "https://wpnews.pro/news/explain-to-me-in-simple-technical-english.txt", "jsonld": "https://wpnews.pro/news/explain-to-me-in-simple-technical-english.jsonld"}}