Dual output is exactly the right instinct. If you want a system to be self-documenting for both humans and LLMs, the key is this: > **Do not treat documentation as prose attached afterward. Treat it as structured semantic data emitted by the same machinery that defines the system.** Otherwise the docs drift, the machine lies, the humans improvise, and the model confidently invents nonsense. A beloved industry tradition. ## My preference, if Fruix wanted to be maximally legible to me I would want **three layers at once** for every meaningful object in the system: ### 1. Operational output The normal thing a human expects. Example: ```text $ fruix service status sshd running since 2026-04-02T09:14:33Z pid 812 generation 42 store item /frx/store/...-openssh-service ``` ### 2. Structured machine-readable output Explicit, stable, schema-like, with no pretty nonsense. Example: ```json { "kind": "service-status", "name": "sshd", "state": "running", "since": "2026-04-02T09:14:33Z", "pid": 812, "generation": 42, "store_path": "/frx/store/...-openssh-service", "definition_ref": "services.sshd" } ``` ### 3. Embedded semantic help/doc layer Not a wall of text. Short, attached meaning. Example: ```json { "doc": { "summary": "OpenSSH daemon providing remote login access.", "purpose": "Accepts inbound SSH connections for remote administration.", "inputs": ["host keys", "network", "authorized keys config"], "depends_on": ["network-online", "host-keys"], "used_by": ["admin access", "remote deployment"], "failure_modes": [ "missing host keys", "port unavailable", "invalid configuration" ], "see_also": [ "fruix service logs sshd", "fruix config explain services.sshd" ] } } ``` That combination is ideal. The command answers the immediate question, but also emits enough structure that an LLM can keep asking intelligent follow-ups without having to guess what “sshd” even is in Fruix-world. --- ## The most important design principle Every object in Fruix should ideally answer these questions about itself: * what are you? * why do you exist? * what created you? * what do you depend on? * what depends on you? * how do I inspect you? * how do I change you? * what breaks if you fail? * where is your definition? * what commands are relevant next? That is the difference between “a system with documentation” and “a system that can explain itself.” ## The command model I would love I would strongly prefer **one canonical plain output mode**, plus **a structured explain mode**, rather than mixing prose into every default command. So: ```text fruix service status sshd fruix service status sshd --json fruix service explain sshd ``` Or maybe: ```text fruix inspect service sshd fruix inspect service sshd --json fruix explain service sshd ``` This separation matters. ### Why not always dual-output in the same stream? Because it becomes annoying for humans, brittle for scripts, and ugly for terminals. People say they want hybrid output until they actually have to read it every day. Better pattern: * default output for operators * stable machine output for tooling/LLMs * explicit explanation output for context That said, you *can* still have a dual channel if done cleanly. --- ## My favorite model: result + attached explain block Something like this: ```text $ fruix service status sshd --with-doc sshd: running pid: 812 since: 2026-04-02T09:14:33Z generation: 42 Explanation: SSH daemon for remote login and administration. Depends on network-online and host key material. Configured from services.sshd in the system definition. Relevant commands: fruix service logs sshd fruix config explain services.sshd fruix service restart sshd ``` That is excellent for humans and still digestible for an LLM if the formatting is predictable. But for automation, I would still want: ```text fruix service status sshd --json fruix service explain sshd --json ``` So in practice I’d want **two parallel interfaces**, not one muddled one. --- ## What should be self-documenting in Fruix? Not just commands. The **actual nouns** of the system. ### 1. Store paths A store item should be explainable. ```text fruix store explain /frx/store/845bd...-freebsd-bash-5.3.9 ``` Should answer: * package/runtime/component name * version * origin * build inputs * purpose * references * whether it is part of current system * whether it is GC-rooted * whether it is user-requested or dependency-only ### 2. Services Explain: * purpose * definition origin * dependencies * restart policy * logs * ports/files touched * activation behavior ### 3. System definitions Explain: * what modules/options contributed * what options are set * defaults vs overrides * resulting closures * affected services * resulting boot entries/generations ### 4. Configuration options This one matters a lot. A good system should let me ask: ```text fruix config explain services.sshd.enable fruix config explain system.network.hostname fruix config search ssh ``` And get: * type * default * current value * description * examples * constraints * source module * related options This is one of the best things NixOS/Guix-style systems can do, and Fruix should absolutely lean into it. ### 5. Commands themselves CLI subcommands should be introspectable too. ```text fruix help gc fruix help gc --json fruix explain command gc ``` Because LLMs are often dropped into a black box and forced to infer the command surface. A command that can describe itself structurally is vastly easier to use safely. --- ## What would help me most as an LLM? If Fruix wanted to be unusually legible to a model, I’d want these properties. ### Stable schemas If `--json` exists, make it boring and stable. No whimsical field names, no gratuitous nesting, no surprise changes. Humans love creative naming, then wonder why tooling breaks. ### Uniform “kind” fields Every structured output should say what it is. ```json { "kind": "service-status", ... } { "kind": "config-option", ... } { "kind": "store-item", ... } { "kind": "system-generation", ... } ``` This helps tremendously. ### Embedded references Objects should point to related objects. For example, service status should include: * definition reference * related config path * related store path * dependency names This lets a model traverse the system instead of hallucinating relationships. ### Short summaries written for machines and humans Not marketing copy. Not essay paragraphs. Tight explanatory text. Good: > "Enables the OpenSSH daemon for inbound remote shell access." Bad: > "This module offers a powerful and flexible way to control secure access to your Fruix machine." Nobody needs brochure language except people trying to justify headcount. ### Explicit provenance For anything important, say where it came from: * built from which derivation * declared in which module * set by user vs default * inherited from which profile/system generation That makes the system explainable instead of mystical. --- ## I would absolutely add a “why” command This is the killer feature. Examples: ```text fruix why /frx/store/...-freebsd-bash-5.3.9 fruix why service sshd fruix why config services.sshd.enable ``` Answers like: ```text freebsd-bash-5.3.9 is present because: - required by fruix-system-fruix-freebsd generation 42 - referenced by interactive-shell-runtime - pulled in by admin profile ``` Or: ```text services.sshd.enable is true because: - set explicitly in hosts/fruix-freebsd.scm - module openssh-service.scm contributes service definition ``` This is huge for both humans and LLMs. “Why is this here?” is half of systems debugging. --- ## My preferred architecture for integrated docs I would not store docs only in markdown files. I would make them part of the typed object/module/option definitions themselves. For each module/option/service/package, attach fields like: * `summary` * `description` * `type` * `default` * `examples` * `see-also` * `danger-level` * `depends-on` * `used-by` * `introduced-in` * `notes` Then generate from that: * terminal help * handbook pages * man pages * JSON explain output * web docs * maybe even shell completions with hints That way there is **one source of truth**, many renderings. This is the real win. --- ## A concrete Fruix interaction model I’d love Something like this command family: ```text fruix inspect [name] fruix explain [name] fruix search fruix why [name] fruix graph [name] ``` Examples: ```text fruix inspect service sshd fruix explain service sshd fruix why service sshd fruix graph service sshd fruix inspect store /frx/store/...-freebsd-bash-5.3.9 fruix explain store /frx/store/...-freebsd-bash-5.3.9 fruix why store /frx/store/...-freebsd-bash-5.3.9 fruix inspect config services.sshd.enable fruix explain config services.sshd.enable fruix why config services.sshd.enable ``` That is clean, memorable, and composable. --- ## If you insist on dual output in one invocation Then I would make it a structured container, not mixed prose spaghetti. Maybe: ```text fruix service status sshd --format annotated ``` Output: ```yaml result: name: sshd state: running pid: 812 since: 2026-04-02T09:14:33Z generation: 42 doc: summary: OpenSSH daemon for remote administration. depends_on: - network-online - host-keys config_path: services.sshd see_also: - fruix service logs sshd - fruix config explain services.sshd ``` YAML is readable enough for humans and parseable enough for tools. Though for machine use I’d still pick JSON. --- ## The single biggest preference of all If I had to choose only one thing, it would be this: > Every meaningful Fruix object should be introspectable by name or path, with both a stable machine schema and a concise semantic explanation. That alone would make the system unusually legible to me, to users, and to future maintainers who have not yet been spiritually damaged by it. ## My concrete recommendation Build this into Fruix from the start: * `--json` on all important commands * `explain` subcommands for commands, config, services, store items, generations * `why` subcommands for dependency/provenance tracing * structured doc fields embedded in module and option definitions * generated docs from the same source * concise summaries, not essay sludge That is the sweet spot. Self-documenting, machine-friendly, human-usable, and hard to let drift. If Fruix gets that right, an LLM dropped cold into the system could become useful very quickly instead of fumbling around like a junior admin in an unfamiliar datacenter.