# Protocol crafter the tool that writes **🔵 Expert · Lesson 05** THE ONE TOOL THAT WRITES TO DISK. Every surface in this curriculum so far reads: viewers read, crystals read, diffs derive, research records. ProtocolCrafter is the exception, and its own docstring flags that in a heading: "IT WRITES TO DISK - the unusual part: Most of this codebase READS source; this one MODIFIES it." It generates Protocol definitions from a live class or object - turning a concrete type into the structural interface that describes it - and then maintains those definitions inside your interface files. WHY THIS EXISTS Melder resolves by SHAPE (beginner 17: protocols as shapes). So the Protocol is the contract, and hand-writing one for a class you already have is transcription - exactly the work a machine should do, and exactly the work that silently rots when the class changes and the Protocol does not. THE DESIGN DECISION WORTH STEALING: BOUNDED UPDATES. "its updates are BOUNDED: it rewrites a DELIMITED REGION rather than a whole file, so HAND-WRITTEN CODE AROUND THE GENERATED BLOCK SURVIVES REGENERATION." That single choice is what separates a usable code generator from one you run once and then never dare run again. A generator that owns whole files forces you to choose between regenerating and keeping your own edits. A generator that owns a delimited block lets both live in the same file forever. It is the same instinct as the withheld-section probe at advanced 15: be precise about the boundary of your authority, and say where it ends. THE SURFACE, IN TWO GROUPS CRAFT - returns code as a string, touches nothing: craft_protocol_code craft_protocol_module_code_from_source_file craft_joined_protocol_module_code WRITE - puts it on disk: write_protocol_module_from_source_file write_joined_protocol_module add_protocol_to_interface_file remove_protocol_from_interface_file THE SPLIT IS NOT A CLEAN 1:1 PAIRING, and the real shape is better than a pairing would be. Two of the writes DO have craft twins - the ones that generate a whole module from a source file, and the joined variant. The two interface-file writes have no twin at all. That looks like a gap until you read their signatures: add_protocol_to_interface_file(path, PROTOCOL_CODE) The crafted code is the ARGUMENT. You cannot add a protocol you have not crafted, because the crafted string is what you pass in. The preview is not a parallel verb you are trusted to remember to call - it is the input, and there is no route to the file that skips it. AND THE BOUNDED-BLOCK RULES ARE THE REST OF IT. `add` refuses by NAME if that protocol is already present rather than appending a second copy, `remove` deletes one named block and leaves the rest of your file alone, and both RETURN the updated contents so the result is inspectable rather than assumed. ## Before you run Use the [Expert guide](../../expert/index.md) for prerequisite concepts. Run from a checkout with Melder installed and Python 3.14 free-threading selected. The collection download includes the level's local helper modules. ## Run the saved script ```bash python UX_and_AIX_experiences/04_expert/05_protocol_crafter_the_tool_that_writes.py ``` ```powershell py -3.14t UX_and_AIX_experiences/04_expert/05_protocol_crafter_the_tool_that_writes.py ``` {download}`Download this collection <../../downloads/expert-examples.zip>` · [Source on GitHub](https://github.com/Synaptic724/melder/blob/4b364a338debcb1c010d0f6e9dcbbabb62945ba0/UX_and_AIX_experiences/04_expert/05_protocol_crafter_the_tool_that_writes.py) ## Public surface md.ProtocolCrafter.craft_protocol_code (twice, for determinism), add_protocol_to_interface_file including its duplicate refusal, and remove_protocol_from_interface_file - all against a temporary directory that removes itself ## Code ```{literalinclude} ../../downloads/04_expert/05_protocol_crafter_the_tool_that_writes.py :language: python :linenos: ``` ## Check the outcome The script contains its own assertions or demonstrated refusal paths. Run it to evaluate those checks against your installed version. The code above is taken directly from the saved file; no run output is invented here. [More expert examples](index.md) · [Level guide](../../expert/index.md) ## Related guides - [The runtime documents itself](../../expert/self-documents.md) ## API contracts - [ProtocolCrafter](../../reference/api/helpers/protocolcrafter.md)