<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>leodido.dev - Go</title>
    <subtitle>Leo&#x27;s take on security, eBPF, Linux, kernel, and whatever tech he meets</subtitle>
    <link rel="self" type="application/atom+xml" href="https://leodido.dev/tags/go/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://leodido.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-02-13T00:00:00+00:00</updated>
    <id>https://leodido.dev/tags/go/atom.xml</id>
    <entry xml:lang="en">
        <title>kfeatures</title>
        <published>2026-02-13T00:00:00+00:00</published>
        <updated>2026-02-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://leodido.dev/projects/kfeatures/"/>
        <id>https://leodido.dev/projects/kfeatures/</id>
        
        <content type="html" xml:base="https://leodido.dev/projects/kfeatures/">&lt;p&gt;&lt;code&gt;kfeatures&lt;&#x2F;code&gt; is a pure-Go library that answers this question.&lt;&#x2F;p&gt;
&lt;p&gt;It probes kernel capabilities at runtime and returns actionable diagnostics: not just &lt;em&gt;unsupported&lt;&#x2F;em&gt;, but &lt;strong&gt;why&lt;&#x2F;strong&gt; and &lt;strong&gt;how to fix it&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;FeatureBPFLSM&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;FeatureBTF&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fe&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;FeatureError&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; errors&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;As&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;fe&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fatalf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; - &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fe&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Feature&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fe&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Reason&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        &#x2F;&#x2F; Output: BPF LSM - CONFIG_BPF_LSM=y but &amp;#39;bpf&amp;#39; not in active LSM list; add lsm=...,bpf to kernel boot params&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The same answers are available from the CLI for &lt;strong&gt;CI&#x2F;CD gating&lt;&#x2F;strong&gt; (semantic exit codes), and from &lt;code&gt;--mcp&lt;&#x2F;code&gt; mode for &lt;strong&gt;AI agents&lt;&#x2F;strong&gt; (JSON-RPC over stdio, every subcommand exposed as an MCP tool with a discoverable input schema). See &lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;kfeatures&#x2F;#cli&quot;&gt;CLI&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-not-cilium-ebpf-features-or-bpftool&quot;&gt;Why not &lt;code&gt;cilium&#x2F;ebpf&#x2F;features&lt;&#x2F;code&gt; or &lt;code&gt;bpftool&lt;&#x2F;code&gt;?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-not-cilium-ebpf-features-or-bpftool&quot; aria-label=&quot;Anchor link for: why-not-cilium-ebpf-features-or-bpftool&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pkg.go.dev&#x2F;github.com&#x2F;cilium&#x2F;ebpf&#x2F;features&quot;&gt;&lt;code&gt;cilium&#x2F;ebpf&#x2F;features&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; answers: &lt;em&gt;&quot;Does this kernel support program type X?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;man.archlinux.org&#x2F;man&#x2F;bpftool-feature.8.en&quot;&gt;&lt;code&gt;bpftool feature probe&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; answers: &lt;em&gt;&quot;What BPF features does this kernel have?&quot;&lt;&#x2F;em&gt; (CLI only, not embeddable in Go)&lt;&#x2F;p&gt;
&lt;p&gt;Neither tells you whether your tool can &lt;strong&gt;actually run&lt;&#x2F;strong&gt;. For example, BPF LSM requires three things simultaneously: &lt;code&gt;CONFIG_BPF_LSM=y&lt;&#x2F;code&gt; in the kernel config, &lt;code&gt;bpf&lt;&#x2F;code&gt; in the active LSM boot parameter list, and the LSM program type supported by the running kernel. &lt;code&gt;cilium&#x2F;ebpf&#x2F;features&lt;&#x2F;code&gt; can only check the last one. &lt;code&gt;bpftool&lt;&#x2F;code&gt; can check the first and last, but not the second. Neither provides remediation guidance.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Capability&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;&lt;code&gt;cilium&#x2F;ebpf&#x2F;features&lt;&#x2F;code&gt;&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;&lt;code&gt;bpftool feature probe&lt;&#x2F;code&gt;&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;&lt;code&gt;kfeatures&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;BPF program type probes&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;BPF map type &#x2F; helper probes&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓ †&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;BTF availability&lt;&#x2F;strong&gt; (&lt;code&gt;&#x2F;sys&#x2F;kernel&#x2F;btf&#x2F;vmlinux&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗ *&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Kernel config parsing&lt;&#x2F;strong&gt; (any &lt;code&gt;CONFIG_*&lt;&#x2F;code&gt;, =y&#x2F;=m)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Active LSM list&lt;&#x2F;strong&gt; (&lt;code&gt;&#x2F;sys&#x2F;kernel&#x2F;security&#x2F;lsm&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;BPF LSM enabled&lt;&#x2F;strong&gt; (config + boot params + program type)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;IMA detection&lt;&#x2F;strong&gt; (LSM list + securityfs directory)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;IMA active measurement&lt;&#x2F;strong&gt; (runtime policy detection)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Process capabilities&lt;&#x2F;strong&gt; (CAP_BPF, CAP_SYS_ADMIN, CAP_PERFMON)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Unprivileged BPF status&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Mount-state gates&lt;&#x2F;strong&gt; (bpffs&#x2F;tracefs&#x2F;custom paths via superblock magic)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;ELF requirement extraction&lt;&#x2F;strong&gt; (parse &lt;code&gt;.o&lt;&#x2F;code&gt;, derive requirements)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Composite feature validation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Actionable diagnostics&lt;&#x2F;strong&gt; (remediation steps)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Selective probing (minimize overhead)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓ ‡&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗ §&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Pure Go, no CGO&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Usable as a Go library&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✗&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;✓&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;sup&gt;* &lt;code&gt;bpftool&lt;&#x2F;code&gt; checks &lt;code&gt;CONFIG_DEBUG_INFO_BTF&lt;&#x2F;code&gt; in the kernel config but does not verify &lt;code&gt;&#x2F;sys&#x2F;kernel&#x2F;btf&#x2F;vmlinux&lt;&#x2F;code&gt; exists.&lt;&#x2F;sup&gt;
&lt;sup&gt;† Exposed in &lt;code&gt;kfeatures&lt;&#x2F;code&gt; as parameterized requirements (&lt;code&gt;RequireMapType&lt;&#x2F;code&gt;, &lt;code&gt;RequireProgramHelper&lt;&#x2F;code&gt;) consumed by &lt;code&gt;Check(...)&lt;&#x2F;code&gt;.&lt;&#x2F;sup&gt;
&lt;sup&gt;‡ &lt;code&gt;cilium&#x2F;ebpf&#x2F;features&lt;&#x2F;code&gt; is per-function: callers invoke individual probe functions on demand.&lt;&#x2F;sup&gt;
&lt;sup&gt;§ &lt;code&gt;bpftool feature probe&lt;&#x2F;code&gt; runs the full probe set on every invocation.&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Other Go projects (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;aquasecurity&#x2F;libbpfgo&quot;&gt;libbpfgo&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cilium&#x2F;tetragon&quot;&gt;Tetragon&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;falcosecurity&#x2F;libs&quot;&gt;Falco libs&lt;&#x2F;a&gt;) have some feature detection built in, but none is a standalone reusable library. They are either CGO-dependent, tightly coupled to their parent project, or written in C&#x2F;C++.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;a class=&quot;zola-anchor&quot; href=&quot;#installation&quot; aria-label=&quot;Anchor link for: installation&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Library:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;go&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; get github.com&#x2F;leodido&#x2F;kfeatures&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;CLI binary (Linux amd64 &#x2F; arm64):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Replace VERSION (e.g. 0.5.1) and ARCH (amd64 or arm64).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -sSLO&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;kfeatures&#x2F;releases&#x2F;download&#x2F;v${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&#x2F;kfeatures_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}_linux_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ARCH&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}.tar.gz&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;tar&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; xzf &amp;quot;kfeatures_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}_linux_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ARCH&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}.tar.gz&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;.&#x2F;kfeatures&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For supply-chain verification of the binary before extracting, see
&lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;kfeatures&#x2F;#verifying-releases&quot;&gt;Verifying releases&lt;&#x2F;a&gt; below.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;a class=&quot;zola-anchor&quot; href=&quot;#usage&quot; aria-label=&quot;Anchor link for: usage&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;quick-check&quot;&gt;Quick check&lt;a class=&quot;zola-anchor&quot; href=&quot;#quick-check&quot; aria-label=&quot;Anchor link for: quick-check&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Validate that required kernel features are available:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;errors&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;log&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;github.com&#x2F;leodido&#x2F;kfeatures&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;FeatureBPFLSM&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;FeatureBTF&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fe&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;FeatureError&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; errors&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;As&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;fe&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fatalf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;kernel not ready: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; - &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fe&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Feature&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fe&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Reason&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;mixed-requirements&quot;&gt;Mixed requirements&lt;a class=&quot;zola-anchor&quot; href=&quot;#mixed-requirements&quot; aria-label=&quot;Anchor link for: mixed-requirements&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Combine &lt;code&gt;Feature&lt;&#x2F;code&gt; enums with parameterized workload requirements:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;github.com&#x2F;cilium&#x2F;ebpf&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;github.com&#x2F;cilium&#x2F;ebpf&#x2F;asm&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;github.com&#x2F;leodido&#x2F;kfeatures&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;FeatureBTF&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;RequireProgramType&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ebpf&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;XDP&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;RequireMapType&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ebpf&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Hash&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;RequireProgramHelper&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ebpf&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;XDP&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; asm&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;FnMapLookupElem&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;custom-mount-paths-requiremount&quot;&gt;Custom mount paths (&lt;code&gt;RequireMount&lt;&#x2F;code&gt;)&lt;a class=&quot;zola-anchor&quot; href=&quot;#custom-mount-paths-requiremount&quot; aria-label=&quot;Anchor link for: custom-mount-paths-requiremount&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Gate on a filesystem mounted at an arbitrary path with the expected superblock magic. Useful when bpffs lives somewhere other than &lt;code&gt;&#x2F;sys&#x2F;fs&#x2F;bpf&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;github.com&#x2F;leodido&#x2F;kfeatures&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;golang.org&#x2F;x&#x2F;sys&#x2F;unix&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;RequireMount&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&#x2F;run&#x2F;bpf&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; unix&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;BPF_FS_MAGIC&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Magic constants come from &lt;code&gt;golang.org&#x2F;x&#x2F;sys&#x2F;unix&lt;&#x2F;code&gt; (e.g. &lt;code&gt;unix.BPF_FS_MAGIC&lt;&#x2F;code&gt;, &lt;code&gt;unix.TRACEFS_MAGIC&lt;&#x2F;code&gt;, &lt;code&gt;unix.CGROUP2_SUPER_MAGIC&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;reusable-presets-featuregroup&quot;&gt;Reusable presets (&lt;code&gt;FeatureGroup&lt;&#x2F;code&gt;)&lt;a class=&quot;zola-anchor&quot; href=&quot;#reusable-presets-featuregroup&quot; aria-label=&quot;Anchor link for: reusable-presets-featuregroup&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;FeatureGroup&lt;&#x2F;code&gt; packages a set of requirements as a single value you can pass anywhere a &lt;code&gt;Requirement&lt;&#x2F;code&gt; is accepted:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; TracingTool&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;FeatureGroup&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;FeatureBTF&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;FeatureKprobeMulti&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;RequireProgramType&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ebpf&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Kprobe&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;TracingTool&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fatal&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;extract-requirements-from-a-compiled-object-fromelf&quot;&gt;Extract requirements from a compiled object (&lt;code&gt;FromELF&lt;&#x2F;code&gt;)&lt;a class=&quot;zola-anchor&quot; href=&quot;#extract-requirements-from-a-compiled-object-fromelf&quot; aria-label=&quot;Anchor link for: extract-requirements-from-a-compiled-object-fromelf&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Point &lt;code&gt;FromELF&lt;&#x2F;code&gt; at an eBPF &lt;code&gt;.o&lt;&#x2F;code&gt; and get back a &lt;code&gt;FeatureGroup&lt;&#x2F;code&gt; describing its program types, map types, and helper-per-program requirements (directly consumable by &lt;code&gt;Check&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;reqs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;FromELF&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;.&#x2F;bpf&#x2F;probe.o&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fatal&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;reqs&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fatalf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;kernel cannot run probe.o: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%v&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output is deterministic (deduplicated, stably ordered). Unknown ELF kinds fail closed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;render-remediation-diagnose&quot;&gt;Render remediation (&lt;code&gt;Diagnose&lt;&#x2F;code&gt;)&lt;a class=&quot;zola-anchor&quot; href=&quot;#render-remediation-diagnose&quot; aria-label=&quot;Anchor link for: render-remediation-diagnose&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;Check&lt;&#x2F;code&gt; returns the diagnosis for the first failing feature. To inspect any feature against a single probe snapshot, call &lt;code&gt;Diagnose&lt;&#x2F;code&gt; directly:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;sf&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Probe&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;sf&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;BPFLSMEnabled&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Supported&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;sf&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Diagnose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;FeatureBPFLSM&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F; CONFIG_BPF_LSM=y but &amp;#39;bpf&amp;#39; not in active LSM list; add lsm=...,bpf to kernel boot params&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;full-probe&quot;&gt;Full probe&lt;a class=&quot;zola-anchor&quot; href=&quot;#full-probe&quot; aria-label=&quot;Anchor link for: full-probe&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Probe all features for diagnostics and reporting:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;sf&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Probe&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fatal&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;sf&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Sample output (truncated):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Kernel: 6.1.0-generic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Program Types:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  LSM: yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  kprobe: yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  kprobe.multi: yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Core:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  BTF: yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Security Subsystems:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  BPF LSM enabled: yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  IMA enabled: no&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  IMA directory: yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Active LSMs: lockdown, capability, yama, apparmor, bpf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Filesystems:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  tracefs: yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  bpffs: yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Individual fields are typed and inspectable programmatically (see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pkg.go.dev&#x2F;github.com&#x2F;leodido&#x2F;kfeatures#SystemFeatures&quot;&gt;&lt;code&gt;SystemFeatures&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;selective-probing&quot;&gt;Selective probing&lt;a class=&quot;zola-anchor&quot; href=&quot;#selective-probing&quot; aria-label=&quot;Anchor link for: selective-probing&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Probe only what you need:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;sf&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ProbeWith&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithProgramTypes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ebpf&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;LSM&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; ebpf&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Kprobe&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithSecuritySubsystems&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    kfeatures&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithCapabilities&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;WithX&lt;&#x2F;code&gt; options select probe scope. They do not define requirements; use &lt;code&gt;Check(...)&lt;&#x2F;code&gt; for gating.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cli&quot;&gt;CLI&lt;a class=&quot;zola-anchor&quot; href=&quot;#cli&quot; aria-label=&quot;Anchor link for: cli&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;A CLI is included for operator diagnostics, CI&#x2F;CD gating, and AI-agent integration:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;go&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install github.com&#x2F;leodido&#x2F;kfeatures&#x2F;cmd&#x2F;kfeatures@latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kfeatures&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; probe&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;                                    # probe all features&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kfeatures&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; check&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --require&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bpf-lsm,btf,cap-bpf&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;      # exit 0 if met, 1 otherwise&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kfeatures&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; probe&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --json&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;                             # JSON output&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kfeatures&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;                                   # display kernel config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;ci-cd-gating-semantic-exit-codes&quot;&gt;CI&#x2F;CD gating (semantic exit codes)&lt;a class=&quot;zola-anchor&quot; href=&quot;#ci-cd-gating-semantic-exit-codes&quot; aria-label=&quot;Anchor link for: ci-cd-gating-semantic-exit-codes&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;kfeatures check&lt;&#x2F;code&gt; exits &lt;strong&gt;0&lt;&#x2F;strong&gt; when all requirements are met and &lt;strong&gt;1&lt;&#x2F;strong&gt; when any are missing. Drop it into a Helm chart pre-install hook, an init container, or a CI job. With &lt;code&gt;--json&lt;&#x2F;code&gt; the verdict is a parse-friendly object on stdout:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kfeatures check&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --require&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bpf-lsm,btf&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;  &amp;quot;ok&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;  &amp;quot;feature&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;bpf-lsm&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;  &amp;quot;reason&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;CONFIG_BPF_LSM=y but &amp;#39;bpf&amp;#39; not in active LSM list; add lsm=...,bpf to kernel boot params&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; $?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Invocation errors (missing required flag, unknown flag, invalid value, unknown subcommand) emit a structured JSON envelope on stderr and exit with a &lt;strong&gt;semantic&lt;&#x2F;strong&gt; code so wrappers can distinguish &quot;the user invoked us wrong&quot; from &quot;the kernel is missing a feature&quot;:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Exit code&lt;&#x2F;th&gt;&lt;th&gt;Category&lt;&#x2F;th&gt;&lt;th&gt;Example&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;OK&lt;&#x2F;td&gt;&lt;td&gt;check passed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Runtime&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FeatureError&lt;&#x2F;code&gt;, probe failure, missing kernel config&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;10&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Input&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;missing_required_flag&lt;&#x2F;code&gt;: required flag not provided&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;11&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Input&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;invalid_flag_value&lt;&#x2F;code&gt;: wrong type or unknown enum&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;12&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Input&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;unknown_flag&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;14&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Input&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;unknown_command&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kfeatures check&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --require&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bogus&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;&amp;quot;error&amp;quot;:&amp;quot;invalid_flag_value&amp;quot;,&amp;quot;exit_code&amp;quot;:11,&amp;quot;flag&amp;quot;:&amp;quot;require&amp;quot;,&amp;quot;got&amp;quot;:&amp;quot;bogus&amp;quot;,&amp;quot;expected&amp;quot;:&amp;quot;feature&amp;quot;,&amp;quot;command&amp;quot;:&amp;quot;kfeatures check&amp;quot;,&amp;quot;message&amp;quot;:&amp;quot;invalid argument &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;bogus&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; for &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;-r, --require&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; flag: unknown feature: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;bogus&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; (available: …)&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; $?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;11&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Codes follow the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pkg.go.dev&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;exitcode&quot;&gt;structcli&#x2F;exitcode&lt;&#x2F;a&gt; categories: input errors &lt;code&gt;10&lt;&#x2F;code&gt;–&lt;code&gt;19&lt;&#x2F;code&gt; are agent-fixable, runtime errors &lt;code&gt;1&lt;&#x2F;code&gt;–&lt;code&gt;9&lt;&#x2F;code&gt; are operator-fixable.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ai-agents-jsonschema-mcp&quot;&gt;AI agents (&lt;code&gt;--jsonschema&lt;&#x2F;code&gt;, &lt;code&gt;--mcp&lt;&#x2F;code&gt;)&lt;a class=&quot;zola-anchor&quot; href=&quot;#ai-agents-jsonschema-mcp&quot; aria-label=&quot;Anchor link for: ai-agents-jsonschema-mcp&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;kfeatures&lt;&#x2F;code&gt; is built to be driven by LLM agents and code-generation tooling without &lt;code&gt;--help&lt;&#x2F;code&gt; scraping.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--jsonschema&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; dumps a JSON Schema describing a command&#x27;s flags. Use &lt;code&gt;=tree&lt;&#x2F;code&gt; to walk the entire subtree:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kfeatures check&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --jsonschema&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; jq&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;.title, .properties | keys&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;&amp;quot;kfeatures check&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;json&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;require&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kfeatures&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --jsonschema=tree&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; jq&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;map(.title) | map(select(test(&amp;quot;^kfeatures( probe| check| config| version)?$&amp;quot;)))&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;kfeatures&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;kfeatures check&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;kfeatures config&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;kfeatures probe&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;kfeatures version&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(&lt;code&gt;--jsonschema=tree&lt;&#x2F;code&gt; walks every node, including cobra-generated &lt;code&gt;help&lt;&#x2F;code&gt; and &lt;code&gt;completion&lt;&#x2F;code&gt; leaves; filter with &lt;code&gt;jq&lt;&#x2F;code&gt; to the ones you care about.)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--mcp&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; turns &lt;code&gt;kfeatures&lt;&#x2F;code&gt; into a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;modelcontextprotocol.io&quot;&gt;Model Context Protocol&lt;&#x2F;a&gt; server over stdio. Each runnable leaf command becomes an MCP tool whose input schema mirrors the cobra flag set; agents introspect via &lt;code&gt;tools&#x2F;list&lt;&#x2F;code&gt; and invoke via &lt;code&gt;tools&#x2F;call&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;jsonc&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; Claude Desktop &#x2F; any MCP-aware client config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  &amp;quot;mcpServers&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    &amp;quot;kfeatures&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;      &amp;quot;command&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;kfeatures&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;      &amp;quot;args&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;--mcp&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tools exposed: &lt;code&gt;probe&lt;&#x2F;code&gt;, &lt;code&gt;check&lt;&#x2F;code&gt;, &lt;code&gt;config&lt;&#x2F;code&gt;. The server stays alive across business-outcome errors (a failing &lt;code&gt;check&lt;&#x2F;code&gt; does not terminate the session), and invocation errors flow through the same structured envelope as the CLI. Pure stdlib JSON-RPC inside &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;mcp&quot;&gt;structcli&lt;&#x2F;a&gt;; no extra heavy SDK dependency.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-it-detects&quot;&gt;What it detects&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-it-detects&quot; aria-label=&quot;Anchor link for: what-it-detects&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Category&lt;&#x2F;th&gt;&lt;th&gt;Features&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Program types&lt;&#x2F;td&gt;&lt;td&gt;LSM, kprobe, kprobe.multi, tracepoint, fentry&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Core&lt;&#x2F;td&gt;&lt;td&gt;BTF availability (CO-RE)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Security&lt;&#x2F;td&gt;&lt;td&gt;BPF LSM enabled, IMA enabled, IMA active measurement, active LSM list&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Capabilities and runtime gates&lt;&#x2F;td&gt;&lt;td&gt;CAP_BPF, CAP_SYS_ADMIN, CAP_PERFMON, unprivileged BPF disabled, BPF stats enabled&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Syscalls&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;bpf()&lt;&#x2F;code&gt;, &lt;code&gt;perf_event_open()&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;JIT&lt;&#x2F;td&gt;&lt;td&gt;enabled, hardened, kallsyms, memory limit, &lt;code&gt;CONFIG_BPF_JIT_ALWAYS_ON&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Filesystems&lt;&#x2F;td&gt;&lt;td&gt;tracefs, debugfs, securityfs, bpffs (gated &lt;code&gt;tracefs&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;bpffs&lt;&#x2F;code&gt; checks verify the filesystem is mounted with the expected superblock magic)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Custom mount gates&lt;&#x2F;td&gt;&lt;td&gt;any path + superblock magic via &lt;code&gt;RequireMount&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Namespaces&lt;&#x2F;td&gt;&lt;td&gt;initial user namespace, initial PID namespace&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Parameterized workload requirements&lt;&#x2F;td&gt;&lt;td&gt;program type, map type, helper-per-program-type via requirement items&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;ELF-derived requirements&lt;&#x2F;td&gt;&lt;td&gt;program&#x2F;map types and helper-per-program requirements via &lt;code&gt;FromELF&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Mitigation context&lt;&#x2F;td&gt;&lt;td&gt;Spectre v1&#x2F;v2 vulnerability status&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Kernel config&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;CONFIG_BPF_LSM&lt;&#x2F;code&gt;, &lt;code&gt;CONFIG_IMA&lt;&#x2F;code&gt;, &lt;code&gt;CONFIG_DEBUG_INFO_BTF&lt;&#x2F;code&gt;, &lt;code&gt;CONFIG_FPROBE&lt;&#x2F;code&gt;, any &lt;code&gt;CONFIG_*&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;stability&quot;&gt;Stability&lt;a class=&quot;zola-anchor&quot; href=&quot;#stability&quot; aria-label=&quot;Anchor link for: stability&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Pre-1.0. The public API may change between minor versions; breaking changes are
called out explicitly in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;kfeatures&#x2F;tree&#x2F;main&#x2F;CHANGELOG.md&quot;&gt;CHANGELOG.md&lt;&#x2F;a&gt;. The &lt;code&gt;FromELF&lt;&#x2F;code&gt; contract
(signature, determinism, fail-closed semantics) is frozen; see
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;kfeatures&#x2F;tree&#x2F;main&#x2F;CONTRIBUTING.md#fromelf-contract&quot;&gt;CONTRIBUTING.md&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;requirements&quot;&gt;Requirements&lt;a class=&quot;zola-anchor&quot; href=&quot;#requirements&quot; aria-label=&quot;Anchor link for: requirements&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Linux for runtime probing&#x2F;checking (uses Linux-specific syscalls and sysfs).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FromELF&lt;&#x2F;code&gt; is parser-only and works on any platform.&lt;&#x2F;li&gt;
&lt;li&gt;Some probes require &lt;code&gt;CAP_BPF&lt;&#x2F;code&gt; or &lt;code&gt;CAP_SYS_ADMIN&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;verifying-releases&quot;&gt;Verifying releases&lt;a class=&quot;zola-anchor&quot; href=&quot;#verifying-releases&quot; aria-label=&quot;Anchor link for: verifying-releases&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Every release artifact (each platform tarball and the &lt;code&gt;checksums.txt&lt;&#x2F;code&gt;) is
signed with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sigstore&#x2F;cosign&quot;&gt;cosign&lt;&#x2F;a&gt; keyless signing
backed by GitHub&#x27;s OIDC token. Each artifact has a sibling
&lt;code&gt;&amp;lt;artifact&amp;gt;.sigstore.json&lt;&#x2F;code&gt; bundle containing the signature, the signing
certificate (with the workflow identity baked in), and the Rekor
transparency-log inclusion proof.&lt;&#x2F;p&gt;
&lt;p&gt;To verify before extracting (replace &lt;code&gt;VERSION&lt;&#x2F;code&gt; and &lt;code&gt;ARCH&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -sSLO&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;kfeatures&#x2F;releases&#x2F;download&#x2F;v${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&#x2F;kfeatures_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}_linux_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ARCH&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}.tar.gz&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -sSLO&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;kfeatures&#x2F;releases&#x2F;download&#x2F;v${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&#x2F;kfeatures_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}_linux_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ARCH&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}.tar.gz.sigstore.json&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cosign&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; verify-blob&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;  --bundle&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;kfeatures_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}_linux_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ARCH&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}.tar.gz.sigstore.json&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;  --certificate-identity&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;kfeatures&#x2F;.github&#x2F;workflows&#x2F;release.yaml@refs&#x2F;tags&#x2F;v${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;  --certificate-oidc-issuer&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;https:&#x2F;&#x2F;token.actions.githubusercontent.com&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;kfeatures_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}_linux_${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ARCH&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}.tar.gz&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A successful verification proves that the artifact was produced by the
&lt;code&gt;release.yaml&lt;&#x2F;code&gt; workflow at the tagged revision, signed by GitHub&#x27;s OIDC
issuer, and is recorded on the public Rekor transparency log. Requires
cosign v2.0+.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;contributing&quot;&gt;Contributing&lt;a class=&quot;zola-anchor&quot; href=&quot;#contributing&quot; aria-label=&quot;Anchor link for: contributing&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;See &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;kfeatures&#x2F;tree&#x2F;main&#x2F;CONTRIBUTING.md&quot;&gt;CONTRIBUTING.md&lt;&#x2F;a&gt; for the API model, the
feature-addition checklist, and the development workflow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;license&quot;&gt;License&lt;a class=&quot;zola-anchor&quot; href=&quot;#license&quot; aria-label=&quot;Anchor link for: license&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;kfeatures&#x2F;tree&#x2F;main&#x2F;LICENSE&quot;&gt;Apache License 2.0&lt;&#x2F;a&gt;. Project attribution in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;kfeatures&#x2F;tree&#x2F;main&#x2F;NOTICE&quot;&gt;NOTICE&lt;&#x2F;a&gt;, per Apache 2.0 §4(d).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-apache-2-0&quot;&gt;Why Apache 2.0&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-apache-2-0&quot; aria-label=&quot;Anchor link for: why-apache-2-0&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;kfeatures&lt;&#x2F;code&gt; is pure-Go userspace. No kernel source embedded, no cgo, no GPL&#x2F;LGPL deps. Kernel interaction is uABI only: reads from &lt;code&gt;&#x2F;proc&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;sys&lt;&#x2F;code&gt;, syscalls and constants via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pkg.go.dev&#x2F;golang.org&#x2F;x&#x2F;sys&#x2F;unix&quot;&gt;&lt;code&gt;golang.org&#x2F;x&#x2F;sys&#x2F;unix&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (BSD-3-Clause), ELF parsing via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pkg.go.dev&#x2F;github.com&#x2F;cilium&#x2F;ebpf&quot;&gt;&lt;code&gt;github.com&#x2F;cilium&#x2F;ebpf&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (MIT; never calls &lt;code&gt;BPF_PROG_LOAD&lt;&#x2F;code&gt;). The kernel&#x27;s &lt;code&gt;COPYING&lt;&#x2F;code&gt; carves &quot;user programs that use kernel services by normal system calls&quot; out of GPL: the carve-out &lt;code&gt;ps&lt;&#x2F;code&gt;, &lt;code&gt;ls&lt;&#x2F;code&gt;, and &lt;code&gt;mount&lt;&#x2F;code&gt; rely on.&lt;&#x2F;p&gt;
&lt;p&gt;Apache 2.0 over MIT:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Patent grant (§3). Probing eBPF, LSM, IMA, namespaces, and Spectre mitigations is patent-adjacent. Apache 2.0 grants an irrevocable patent license with defensive termination. MIT has none.&lt;&#x2F;li&gt;
&lt;li&gt;Adopter alignment. Cilium, Tetragon, Tracee, Falco, Pixie, and Inspektor Gadget are Apache 2.0. No compatibility review needed.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>structcli</title>
        <published>2024-02-12T00:00:00+00:00</published>
        <updated>2024-02-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://leodido.dev/projects/structcli/"/>
        <id>https://leodido.dev/projects/structcli/</id>
        
        <content type="html" xml:base="https://leodido.dev/projects/structcli/">&lt;p&gt;Declare your CLI contract once in Go structs. &lt;code&gt;structcli&lt;&#x2F;code&gt; turns it into flags, env vars, config-file loading, validation, organized help, and machine-readable contracts for agents.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Less Cobra&#x2F;Viper boilerplate&lt;&#x2F;li&gt;
&lt;li&gt;Better CLIs for humans&lt;&#x2F;li&gt;
&lt;li&gt;Better contracts for automation and LLMs&lt;&#x2F;li&gt;
&lt;li&gt;Compiles to WASM out of the box&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Stop writing plumbing. Start shipping commands.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zap-quick-start&quot;&gt;⚡ Quick Start&lt;a class=&quot;zola-anchor&quot; href=&quot;#zap-quick-start&quot; aria-label=&quot;Anchor link for: zap-quick-start&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Start with a plain Go struct:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;fmt&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;github.com&#x2F;leodido&#x2F;structcli&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;github.com&#x2F;spf13&#x2F;cobra&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;go.uber.org&#x2F;zap&#x2F;zapcore&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Options&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	LogLevel&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; zapcore&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Level&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Port&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-numeric z-go&quot;&gt;     int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Options&lt;&#x2F;span&gt;&lt;span&gt;{}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	cli&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;cobra&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Command&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		Use&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;myapp&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		RunE&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;cobra&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;			fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;opts&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; already populated&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;			return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;cli&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; opts&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ExecuteOrExit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;cli&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;Bind&lt;&#x2F;code&gt; creates flags and env vars from your struct and registers it for auto-unmarshal. &lt;code&gt;ExecuteOrExit&lt;&#x2F;code&gt; hydrates the struct from flags, env vars, config, and defaults before your &lt;code&gt;RunE&lt;&#x2F;code&gt; fires.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; go run examples&#x2F;minimal&#x2F;main.go&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Usage:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   myapp [flags]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   -h, --help                     help for myapp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --loglevel zapcore.Level    {debug,info,warn,error,dpanic,panic,fatal} (default info)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --port int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Add tags when you want aliases, env vars, shorthand, defaults, and descriptions:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Options&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	LogLevel&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; zapcore&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Level&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;level&amp;quot; flagdescr:&amp;quot;Set logging level&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Port&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-numeric z-go&quot;&gt;     int&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;           `flagshort:&amp;quot;p&amp;quot; flagdescr:&amp;quot;Server port&amp;quot; flagenv:&amp;quot;true&amp;quot; default:&amp;quot;3000&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; go run examples&#x2F;simple&#x2F;main.go&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# A simple CLI example&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Usage:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   myapp [flags]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   -h, --help                  help for myapp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --level zapcore.Level   Set logging level {debug,info,warn,error,dpanic,panic,fatal} (default info)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   -p, --port int              Server port (default 3000)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Global Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --jsonschema string[=&amp;quot;true&amp;quot;]   output JSON Schema and exit (bare: this command, =tree: full subtree)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --mcp                          serve MCP over stdio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; MYAPP_LOGLEVEL=debug go run examples&#x2F;simple&#x2F;main.go&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# &amp;amp;{debug 3000}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; MYAPP_LOGLEVEL=error MYAPP_PORT=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;9000&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; go run examples&#x2F;simple&#x2F;main.go&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --level&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dpanic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# &amp;amp;{dpanic 9000}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Built-in types like &lt;code&gt;zapcore.Level&lt;&#x2F;code&gt; are validated automatically too.&lt;&#x2F;p&gt;
&lt;p&gt;Out of the box, your CLI supports:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;📝 Command-line flags (&lt;code&gt;--level info&lt;&#x2F;code&gt;, &lt;code&gt;-p 8080&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;🌍 Environment variables (&lt;code&gt;MYAPP_PORT=8080&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;💦 Options precedence (flags &amp;gt; env vars &amp;gt; config file &amp;gt; defaults)&lt;&#x2F;li&gt;
&lt;li&gt;✅ Automatic validation and type conversion&lt;&#x2F;li&gt;
&lt;li&gt;📚 Beautiful help output with proper grouping&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Add the AI-native wiring below and it also gains machine-readable JSON Schema, structured JSON errors, semantic exit codes, and optional MCP tool-server mode for agents.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;build-ai-native-clis&quot;&gt;Build AI-Native CLIs&lt;a class=&quot;zola-anchor&quot; href=&quot;#build-ai-native-clis&quot; aria-label=&quot;Anchor link for: build-ai-native-clis&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;structcli&lt;&#x2F;code&gt; does not just generate flags for humans. It can make your CLI legible to agents too.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of scraping &lt;code&gt;--help&lt;&#x2F;code&gt; and guessing, an agent can discover the contract, call the command correctly, and recover from structured failures.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Setup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rootCmd&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithJSONSchema&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithHelpTopics&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;helptopics&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Options&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ReferenceSection&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;}),&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F; &amp;quot;mycli env-vars&amp;quot; and &amp;quot;mycli config-keys&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithFlagErrors&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F; Optional, but recommended for typed flag-parse errors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithMCP&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;         &#x2F;&#x2F; Optional, exposes the CLI as an MCP server over stdio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ExecuteOrExit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rootCmd&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With that wiring:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--jsonschema&lt;&#x2F;code&gt; exposes flags, defaults, required inputs, enums, and env bindings for the current command; &lt;code&gt;--jsonschema=tree&lt;&#x2F;code&gt; dumps the entire subtree in one call&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;mycli env-vars&lt;&#x2F;code&gt; and &lt;code&gt;mycli config-keys&lt;&#x2F;code&gt; list every environment variable binding and config file key across the command tree&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;HandleError&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;ExecuteOrExit&lt;&#x2F;code&gt; emit structured JSON errors instead of forcing callers to parse human-oriented output&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--mcp&lt;&#x2F;code&gt; exposes the same command tree as MCP tools over stdio, with typed inputs and structured tool-call failures&lt;&#x2F;li&gt;
&lt;li&gt;semantic exit codes tell the caller whether it should fix input, fix config, retry, or escalate to a human&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The same contract spans flags, env vars, config, validation, and enum constraints.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mycli srv&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --jsonschema&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;  &amp;quot;properties&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;    &amp;quot;port&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;      &amp;quot;type&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;integer&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;      &amp;quot;default&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 3000,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;      &amp;quot;x-structcli-env-vars&amp;quot;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;MYCLI_SRV_PORT&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;    &amp;quot;secret-key&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;      &amp;quot;type&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;string&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;      &amp;quot;x-structcli-env-vars&amp;quot;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;MYCLI_SRV_SECRET_KEY&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;      &amp;quot;x-structcli-env-only&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-support z-function&quot;&gt;  &amp;quot;x-structcli-config-flag&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;config&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Use &lt;code&gt;--jsonschema=tree&lt;&#x2F;code&gt; to dump the entire command subtree in a single call: no need to invoke each subcommand separately:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mycli&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --jsonschema=tree&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;   # JSON array of schemas for all commands&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mycli srv&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --jsonschema=tree&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;  # schemas for srv + its subcommands&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No &lt;code&gt;--help&lt;&#x2F;code&gt; parsing. No guessing what failed. Just a CLI that can explain itself and fail in machine-actionable ways.&lt;&#x2F;p&gt;
&lt;p&gt;Use &lt;code&gt;exitcode.Category(code)&lt;&#x2F;code&gt; and &lt;code&gt;exitcode.IsRetryable(code)&lt;&#x2F;code&gt; to decide what to do next. See &lt;code&gt;jsonschema.WithEnumInDescription()&lt;&#x2F;code&gt; for schema customization, and pass schema options through &lt;code&gt;WithJSONSchema&lt;&#x2F;code&gt; with &lt;code&gt;jsonschema.Options{SchemaOpts: ...}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For CLIs that capture output streams during command construction, configure &lt;code&gt;mcp.Options.CommandFactory&lt;&#x2F;code&gt; so each MCP tool call builds a fresh command with the tool-call stdout and stderr writers. This keeps MCP protocol output separate from command output while preserving the existing command tree schema. If the command constructor requires stdin, the factory can wire a non-interactive reader such as &lt;code&gt;strings.NewReader(&quot;&quot;)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For build-time discovery, &lt;code&gt;generate.WriteAll&lt;&#x2F;code&gt; produces SKILL.md, llms.txt, and AGENTS.md from the same struct definitions: wire it into &lt;code&gt;&#x2F;&#x2F;go:generate&lt;&#x2F;code&gt; and the files stay in sync automatically.&lt;&#x2F;p&gt;
&lt;p&gt;Read the full &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;docs&#x2F;ai-native.md&quot;&gt;AI-native guide&lt;&#x2F;a&gt; or walk through the runnable &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;structerr&#x2F;README.md&quot;&gt;structured error example&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;v-install&quot;&gt;⬇️ Install&lt;a class=&quot;zola-anchor&quot; href=&quot;#v-install&quot; aria-label=&quot;Anchor link for: v-install&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;go&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; get github.com&#x2F;leodido&#x2F;structcli&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;package-key-features&quot;&gt;📦 Key Features&lt;a class=&quot;zola-anchor&quot; href=&quot;#package-key-features&quot; aria-label=&quot;Anchor link for: package-key-features&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;jigsaw-declarative-flags-definition&quot;&gt;🧩 Declarative Flags Definition&lt;a class=&quot;zola-anchor&quot; href=&quot;#jigsaw-declarative-flags-definition&quot; aria-label=&quot;Anchor link for: jigsaw-declarative-flags-definition&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Define flags once using Go struct tags.&lt;&#x2F;p&gt;
&lt;p&gt;No more boilerplate for &lt;code&gt;Flags().StringVarP&lt;&#x2F;code&gt;, &lt;code&gt;Flags().IntVar&lt;&#x2F;code&gt;, &lt;code&gt;viper.BindPFlag&lt;&#x2F;code&gt;, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, you can &lt;em&gt;nest&lt;&#x2F;em&gt; structs too.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; ServerOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Basic flags&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Host&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;host&amp;quot; flagdescr:&amp;quot;Server host&amp;quot; default:&amp;quot;localhost&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Port&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-numeric z-go&quot;&gt; int&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    `flagshort:&amp;quot;p&amp;quot; flagdescr:&amp;quot;Server port&amp;quot; flagrequired:&amp;quot;true&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Environment variable binding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	APIKey&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flagenv:&amp;quot;true&amp;quot; flagdescr:&amp;quot;API authentication key&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Network contracts using net families&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	BindIP&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        net&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;IP&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     `flag:&amp;quot;bind-ip&amp;quot; flaggroup:&amp;quot;Network&amp;quot; flagdescr:&amp;quot;Bind interface IP&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	BindMask&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;      net&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;IPMask&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;bind-mask&amp;quot; flaggroup:&amp;quot;Network&amp;quot; flagdescr:&amp;quot;Bind interface mask&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	AdvertiseCIDR&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; net&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;IPNet&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  `flag:&amp;quot;advertise-cidr&amp;quot; flaggroup:&amp;quot;Network&amp;quot; flagdescr:&amp;quot;Advertised service subnet (CIDR)&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	TrustedPeers&lt;&#x2F;span&gt;&lt;span&gt;  []&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;net&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;IP&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   `flag:&amp;quot;trusted-peers&amp;quot; flaggroup:&amp;quot;Network&amp;quot; flagdescr:&amp;quot;Trusted peer IPs (comma separated)&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Flag grouping for organized help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	LogLevel&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; zapcore&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Level&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;log-level&amp;quot; flaggroup:&amp;quot;Logging&amp;quot; flagdescr:&amp;quot;Set log level&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	LogFile&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;  string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        `flag:&amp;quot;log-file&amp;quot; flaggroup:&amp;quot;Logging&amp;quot; flagdescr:&amp;quot;Log file path&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Nested structs for organization&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Database&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; DatabaseConfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flaggroup:&amp;quot;Database&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Enum type (registered via RegisterEnum)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	TargetEnv&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;target-env&amp;quot; flagdescr:&amp;quot;Set the target environment&amp;quot; default:&amp;quot;dev&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; DatabaseConfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	URL&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;      string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;db-url&amp;quot; flagdescr:&amp;quot;Database connection URL&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	MaxConns&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-numeric z-go&quot;&gt; int&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    `flagdescr:&amp;quot;Max database connections&amp;quot; default:&amp;quot;10&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;See &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;full&#x2F;cli&#x2F;cli.go&quot;&gt;full example&lt;&#x2F;a&gt; for more details.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tools-automatic-environment-variable-binding&quot;&gt;🛠️ Automatic Environment Variable Binding&lt;a class=&quot;zola-anchor&quot; href=&quot;#tools-automatic-environment-variable-binding&quot; aria-label=&quot;Anchor link for: tools-automatic-environment-variable-binding&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Automatically generate environment variables binding them to configuration files (YAML, JSON, TOML, etc.) and flags.&lt;&#x2F;p&gt;
&lt;p&gt;From the previous options struct, you get the following env vars automatically:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FULL_SRV_PORT&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FULL_SRV_APIKEY&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FULL_SRV_BIND_IP&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FULL_SRV_BIND_MASK&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FULL_SRV_ADVERTISE_CIDR&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FULL_SRV_TRUSTED_PEERS&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FULL_SRV_DATABASE_MAXCONNS&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FULL_SRV_LOGFILE&lt;&#x2F;code&gt;, &lt;code&gt;FULL_SRV_LOG_FILE&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Every struct field with the &lt;code&gt;flagenv:&quot;true&quot;&lt;&#x2F;code&gt; tag gets an environment variable (two if the struct field also has the &lt;code&gt;flag:&quot;...&quot;&lt;&#x2F;code&gt; tag, see struct field &lt;code&gt;LogFile&lt;&#x2F;code&gt;).
Use &lt;code&gt;flagenv:&quot;only&quot;&lt;&#x2F;code&gt; for fields that should be settable exclusively via environment variable or config file: CLI usage (&lt;code&gt;--flag=value&lt;&#x2F;code&gt;) is rejected at runtime.&lt;&#x2F;p&gt;
&lt;p&gt;The prefix of the environment variable name is the CLI name plus the command name to which those options are attached to.&lt;&#x2F;p&gt;
&lt;p&gt;Environment variables are command-scoped for command-local options.
For example, if &lt;code&gt;Port&lt;&#x2F;code&gt; is attached to the &lt;code&gt;srv&lt;&#x2F;code&gt; command, &lt;code&gt;FULL_SRV_PORT&lt;&#x2F;code&gt; is used (not &lt;code&gt;FULL_PORT&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gear-configuration-file-support&quot;&gt;⚙️ Configuration File Support&lt;a class=&quot;zola-anchor&quot; href=&quot;#gear-configuration-file-support&quot; aria-label=&quot;Anchor link for: gear-configuration-file-support&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Set up configuration file discovery (flag, environment variable, and fallback paths) via &lt;code&gt;Setup&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Setup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rootCmd&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithAppName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;full&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithConfig&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Options&lt;&#x2F;span&gt;&lt;span&gt;{}),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Enable strict config-key validation with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Setup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rootCmd&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithAppName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;full&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithConfig&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Options&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ValidateKeys&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;}),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When enabled, &lt;code&gt;Unmarshal&lt;&#x2F;code&gt; fails if command-relevant config contains unknown keys.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;WithAppName&lt;&#x2F;code&gt; sets the env prefix. &lt;code&gt;WithConfig&lt;&#x2F;code&gt; registers the &lt;code&gt;--config&lt;&#x2F;code&gt; flag and defers config loading to &lt;code&gt;ExecuteC&lt;&#x2F;code&gt;&#x27;s bind pipeline (before auto-unmarshal). Ordering between &lt;code&gt;Setup&lt;&#x2F;code&gt; and &lt;code&gt;Bind&lt;&#x2F;code&gt; does not matter: &lt;code&gt;WithAppName&lt;&#x2F;code&gt; retroactively patches env annotations on already-defined flags.&lt;&#x2F;p&gt;
&lt;p&gt;Individual &lt;code&gt;SetupConfig&lt;&#x2F;code&gt;, &lt;code&gt;SetupDebug&lt;&#x2F;code&gt;, etc. remain available for power users who need fine-grained control.&lt;&#x2F;p&gt;
&lt;p&gt;The line above:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;creates &lt;code&gt;--config&lt;&#x2F;code&gt; global flag&lt;&#x2F;li&gt;
&lt;li&gt;creates &lt;code&gt;FULL_CONFIG&lt;&#x2F;code&gt; env var&lt;&#x2F;li&gt;
&lt;li&gt;sets &lt;code&gt;&#x2F;etc&#x2F;full&#x2F;&lt;&#x2F;code&gt;, &lt;code&gt;$HOME&#x2F;.full&#x2F;&lt;&#x2F;code&gt;, &lt;code&gt;$PWD&#x2F;.full&#x2F;&lt;&#x2F;code&gt; as fallback paths for &lt;code&gt;config.yaml&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Magic, isn&#x27;t it?&lt;&#x2F;p&gt;
&lt;p&gt;What&#x27;s left? Tell your CLI to load the configuration file (if any).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;rootC&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;PersistentPreRunE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;cobra&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	_&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; configMessage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; configErr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;UseConfigSimple&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; configErr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; configErr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; configMessage&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		c&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;configMessage&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;UseConfigSimple(c)&lt;&#x2F;code&gt; loads config into the root config scope and merges only the relevant section into &lt;code&gt;c&lt;&#x2F;code&gt;&#x27;s effective scope.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;brain-viper-model-scopes&quot;&gt;🧠 Viper Model Scopes&lt;a class=&quot;zola-anchor&quot; href=&quot;#brain-viper-model-scopes&quot; aria-label=&quot;Anchor link for: brain-viper-model-scopes&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;code&gt;structcli&lt;&#x2F;code&gt; uses two different viper scopes on purpose:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;structcli.GetConfigViper(rootOrLeafCmd)&lt;&#x2F;code&gt; -&amp;gt; root-scoped &lt;strong&gt;config source&lt;&#x2F;strong&gt; (config file data tree)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;structcli.GetViper(cmd)&lt;&#x2F;code&gt; -&amp;gt; command-scoped &lt;strong&gt;effective values&lt;&#x2F;strong&gt; (flags&#x2F;env&#x2F;defaults + command-relevant config)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This separation keeps config-file loading isolated from runtime command state.&lt;&#x2F;p&gt;
&lt;p&gt;If you need imperative values in tests or application code, write to the right scope:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; 1) Effective override for one command context&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;GetViper&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;timeout&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; 2) Config-tree style injection (top-level + command section)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;GetConfigViper&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rootCmd&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;srv&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;any&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;port&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8443&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Global &lt;code&gt;viper.Set(...)&lt;&#x2F;code&gt; is not used by &lt;code&gt;structcli.Unmarshal(...)&lt;&#x2F;code&gt; resolution.
Use &lt;code&gt;GetViper&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;GetConfigViper&lt;&#x2F;code&gt; instead.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;scroll-configuration-is-first-class-citizen&quot;&gt;📜 Configuration Is First-Class Citizen&lt;a class=&quot;zola-anchor&quot; href=&quot;#scroll-configuration-is-first-class-citizen&quot; aria-label=&quot;Anchor link for: scroll-configuration-is-first-class-citizen&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Configuration can mirror your command hierarchy.&lt;&#x2F;p&gt;
&lt;p&gt;Settings can be global (at the top level) or specific to a command or subcommand. The most specific section always takes precedence.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Global settings apply to all commands unless overridden by a specific section.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# `dryrun` matches the `DryRun` struct field name.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;dryrun&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;verbose&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; # A default verbosity level for all commands.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Config for the `srv` command (`full srv`)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;srv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # `port` matches the `Port` field name.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  port&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8433&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # Network options&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  bind-ip&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;10.20.0.10&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  bind-mask&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;ffffff00&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  advertise-cidr&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;10.20.0.0&#x2F;24&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  trusted-peers&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;10.20.0.11,10.20.0.12&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # `log-level` matches the `flag:&amp;quot;log-level&amp;quot;` tag.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  log-level&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;warn&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # `logfile` matches the `LogFile` field name.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  logfile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;var&#x2F;log&#x2F;mysrv.log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # Flattened keys can set options in nested structs.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # `db-url` (from `flag:&amp;quot;db-url&amp;quot;` tag) maps to ServerOptions.Database.URL.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  db-url&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;postgres:&#x2F;&#x2F;user:pass@db&#x2F;prod&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # Nested keys are also supported.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  database&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    # Struct field key style&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    url&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;postgres:&#x2F;&#x2F;user:pass@db&#x2F;prod&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    # Alias key style (from `flag:&amp;quot;db-url&amp;quot;`)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    db-url&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;postgres:&#x2F;&#x2F;user:pass@db&#x2F;prod&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Config for the `usr` command group.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;usr&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # This nested section matches the `usr add` command (`full usr add`).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # Its settings are ONLY applied to &amp;#39;usr add&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  add&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;Config User&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    email&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;config.user@example.com&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    age&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 42&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    # Command specific override&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    dry&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# NOTE: Per the library&amp;#39;s design, there is no other fallback other than from the top-level.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# A command like &amp;#39;usr delete&amp;#39; would ONLY use the global keys above (if those keys&#x2F;flags are attached to it),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# as an exact &amp;#39;usr.delete&amp;#39; section is not defined.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This configuration system supports:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hierarchical Structure&lt;&#x2F;strong&gt;: Nest keys to match your command path (e.g., &lt;code&gt;usr: { add: { ... } }&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Strict Precedence&lt;&#x2F;strong&gt;: Only settings from the global scope and the exact command path section are merged. There is no automatic fallback to parent command sections.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Flexible Keys&lt;&#x2F;strong&gt;: You can use struct field names and aliases (&lt;code&gt;flag:&quot;...&quot;&lt;&#x2F;code&gt;) in both flattened and nested forms.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Supported Forms for Nested Fields&lt;&#x2F;strong&gt;: &lt;code&gt;db-url&lt;&#x2F;code&gt;, &lt;code&gt;database.url&lt;&#x2F;code&gt;, &lt;code&gt;database: { url: ... }&lt;&#x2F;code&gt;, and &lt;code&gt;database: { db-url: ... }&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;white-check-mark-built-in-validation-transformation&quot;&gt;✅ Built-in Validation &amp;amp; Transformation&lt;a class=&quot;zola-anchor&quot; href=&quot;#white-check-mark-built-in-validation-transformation&quot; aria-label=&quot;Anchor link for: white-check-mark-built-in-validation-transformation&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Supports validation, transformation, and custom flag type definitions through simple interfaces.&lt;&#x2F;p&gt;
&lt;p&gt;Your struct must implement &lt;code&gt;Options&lt;&#x2F;code&gt; (via &lt;code&gt;Attach&lt;&#x2F;code&gt;) and can optionally implement &lt;code&gt;ValidatableOptions&lt;&#x2F;code&gt; and &lt;code&gt;TransformableOptions&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; UserConfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Email&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;email&amp;quot; flagdescr:&amp;quot;User email&amp;quot; validate:&amp;quot;email&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Age&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-numeric z-go&quot;&gt;   int&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    `flag:&amp;quot;age&amp;quot; flagdescr:&amp;quot;User age&amp;quot; validate:&amp;quot;min=18,max=120&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Name&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;  string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;name&amp;quot; flagdescr:&amp;quot;User name&amp;quot; mod:&amp;quot;trim,title&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;o &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;ServerOptions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Validate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;) []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F; Automatic validation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;o &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;ServerOptions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Transform&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F; Automatic transformation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;See a full working example &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;full&#x2F;cli&#x2F;cli.go&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;construction-automatic-debugging-support&quot;&gt;🚧 Automatic Debugging Support&lt;a class=&quot;zola-anchor&quot; href=&quot;#construction-automatic-debugging-support&quot; aria-label=&quot;Anchor link for: construction-automatic-debugging-support&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Create a &lt;code&gt;--debug-options&lt;&#x2F;code&gt; flag (plus a matching env var) for troubleshooting config&#x2F;env&#x2F;flags resolution.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Setup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rootCmd&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithDebug&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;debug&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Options&lt;&#x2F;span&gt;&lt;span&gt;{}))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or standalone: &lt;code&gt;structcli.SetupDebug(rootCmd, debug.Options{})&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The flag accepts &lt;code&gt;text&lt;&#x2F;code&gt; (default when used bare) or &lt;code&gt;json&lt;&#x2F;code&gt; for machine-readable output. Truthy values like &lt;code&gt;true&lt;&#x2F;code&gt;, &lt;code&gt;1&lt;&#x2F;code&gt;, &lt;code&gt;yes&lt;&#x2F;code&gt; are treated as &lt;code&gt;text&lt;&#x2F;code&gt; for backward compatibility.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Text output&lt;&#x2F;strong&gt;: an aligned table showing each flag&#x27;s resolved value and where it came from:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; go run examples&#x2F;full&#x2F;main.go srv&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --debug-options --config&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; examples&#x2F;full&#x2F;config.yaml&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3333&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Command: full srv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --apikey                 secret-api-key                       (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --config                 examples&#x2F;full&#x2F;config.yaml            (flag)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --database.maxconns      3                                    (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --db-url                 postgres:&#x2F;&#x2F;user:pass@localhost&#x2F;mydb  (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --debug-options          text                                 (flag)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --host                   production-server                    (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --log-file               &#x2F;var&#x2F;log&#x2F;mysrv.log                   (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --log-level              debug                                (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --port                   3333                                 (flag)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   --target-env             dev                                  (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Values:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   apikey: secret-api-key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   host: production-server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   log-level: debug&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   port: 3333&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;JSON output&lt;&#x2F;strong&gt;: structured data for AI agents and tooling:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; go run examples&#x2F;full&#x2F;main.go srv&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --debug-options=json --config&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; examples&#x2F;full&#x2F;config.yaml&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3333&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   &amp;quot;command&amp;quot;: &amp;quot;full srv&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   &amp;quot;flags&amp;quot;: [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#     ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#     {&amp;quot;name&amp;quot;: &amp;quot;config&amp;quot;, &amp;quot;value&amp;quot;: &amp;quot;examples&#x2F;full&#x2F;config.yaml&amp;quot;, &amp;quot;default&amp;quot;: &amp;quot;&amp;quot;, &amp;quot;changed&amp;quot;: true, &amp;quot;source&amp;quot;: &amp;quot;flag&amp;quot;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#     {&amp;quot;name&amp;quot;: &amp;quot;db-url&amp;quot;, &amp;quot;value&amp;quot;: &amp;quot;postgres:&#x2F;&#x2F;user:pass@localhost&#x2F;mydb&amp;quot;, &amp;quot;default&amp;quot;: &amp;quot;&amp;quot;, &amp;quot;changed&amp;quot;: false, &amp;quot;source&amp;quot;: &amp;quot;default&amp;quot;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#     {&amp;quot;name&amp;quot;: &amp;quot;log-level&amp;quot;, &amp;quot;value&amp;quot;: &amp;quot;debug&amp;quot;, &amp;quot;default&amp;quot;: &amp;quot;info&amp;quot;, &amp;quot;changed&amp;quot;: false, &amp;quot;source&amp;quot;: &amp;quot;default&amp;quot;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#     {&amp;quot;name&amp;quot;: &amp;quot;port&amp;quot;, &amp;quot;value&amp;quot;: &amp;quot;3333&amp;quot;, &amp;quot;default&amp;quot;: &amp;quot;0&amp;quot;, &amp;quot;changed&amp;quot;: true, &amp;quot;source&amp;quot;: &amp;quot;flag&amp;quot;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#     ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   ],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   &amp;quot;values&amp;quot;: {&amp;quot;apikey&amp;quot;: &amp;quot;secret-api-key&amp;quot;, &amp;quot;host&amp;quot;: &amp;quot;production-server&amp;quot;, &amp;quot;log-level&amp;quot;: &amp;quot;debug&amp;quot;, &amp;quot;port&amp;quot;: 3333, ...}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Source attribution resolves each flag to &lt;code&gt;flag&lt;&#x2F;code&gt; (CLI), &lt;code&gt;env&lt;&#x2F;code&gt;, &lt;code&gt;config&lt;&#x2F;code&gt;, or &lt;code&gt;default&lt;&#x2F;code&gt;. For env-sourced flags, the text output includes the variable name (e.g., &lt;code&gt;(env: MYAPP_LOG_LEVEL)&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;The flag can also be activated via environment variable: &lt;code&gt;FULL_DEBUG_OPTIONS=json&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;clipboard-self-documenting-help-topics&quot;&gt;📋 Self-Documenting Help Topics&lt;a class=&quot;zola-anchor&quot; href=&quot;#clipboard-self-documenting-help-topics&quot; aria-label=&quot;Anchor link for: clipboard-self-documenting-help-topics&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;WithHelpTopics&lt;&#x2F;code&gt; (or standalone &lt;code&gt;SetupHelpTopics&lt;&#x2F;code&gt;) adds two help topic commands that list every environment variable binding and every valid configuration file key across the command tree.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Setup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rootCmd&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithHelpTopics&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;helptopics&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Options&lt;&#x2F;span&gt;&lt;span&gt;{}))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Call this after all subcommands and flags are defined (typically right before &lt;code&gt;ExecuteOrExit&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;By default the commands appear as regular subcommands under &quot;Available Commands:&quot;. Set &lt;code&gt;ReferenceSection: true&lt;&#x2F;code&gt; to move them into a dedicated &quot;Reference:&quot; section instead.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Environment variable listing&lt;&#x2F;strong&gt;: &lt;code&gt;mycli env-vars&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Environment Variables&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  mycli (global):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    MYCLI_VERBOSE  --verbose  bool           false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  mycli serve:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    MYCLI_SERVE_HOST  --host  string         localhost&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    MYCLI_SERVE_PORT  --port  int            8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Configuration key listing&lt;&#x2F;strong&gt;: &lt;code&gt;mycli config-keys&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Configuration Keys&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Config flag: --config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Supported formats: yaml, json, toml. Searches: $HOME&#x2F;.mycli, &#x2F;etc&#x2F;mycli&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  mycli (global):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    output   --output   string         text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    verbose  --verbose  bool           false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  mycli serve:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    host      --host      string         localhost&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    port      --port      int            8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tls-cert  --tls-cert  string         &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Keys can be nested under the command name in the config file.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With &lt;code&gt;ReferenceSection: true&lt;&#x2F;code&gt;, both topics appear under &quot;Reference:&quot; in &lt;code&gt;--help&lt;&#x2F;code&gt; output instead of &quot;Available Commands:&quot;. Flags marked &lt;code&gt;flagenv:&quot;only&quot;&lt;&#x2F;code&gt; show an &lt;code&gt;(env-only)&lt;&#x2F;code&gt; suffix in the env-vars listing and are excluded from config-keys (since they are hidden). Config keys derived from embedded struct field paths appear as aliases (e.g., &lt;code&gt;database.maxconns&lt;&#x2F;code&gt; → &lt;code&gt;alias for --database.maxconns&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;For machine-readable cross-tree data, use &lt;code&gt;--jsonschema=tree&lt;&#x2F;code&gt; instead: it provides the same information in structured JSON.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sharing-options-between-commands&quot;&gt;↪️ Sharing Options Between Commands&lt;a class=&quot;zola-anchor&quot; href=&quot;#sharing-options-between-commands&quot; aria-label=&quot;Anchor link for: sharing-options-between-commands&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;In complex CLIs, multiple commands often need access to the same global configuration and shared resources (like a logger or a database connection). &lt;code&gt;structcli&lt;&#x2F;code&gt; provides a pattern using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;contract.go&quot;&gt;&lt;code&gt;ContextInjector&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; interface to achieve this without resorting to global variables, by propagating a single &quot;source of truth&quot; through the command context.&lt;&#x2F;p&gt;
&lt;p&gt;The pattern allows you to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Populate a shared options struct once from flags, environment variables, or a config file.&lt;&#x2F;li&gt;
&lt;li&gt;Initialize &quot;computed state&quot; (like a logger) based on those options.&lt;&#x2F;li&gt;
&lt;li&gt;Share this single, fully-prepared &quot;source of truth&quot; with any subcommand that needs it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;doughnut-in-a-nutshell&quot;&gt;🍩 In a Nutshell&lt;a class=&quot;zola-anchor&quot; href=&quot;#doughnut-in-a-nutshell&quot; aria-label=&quot;Anchor link for: doughnut-in-a-nutshell&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Create a shared struct that implements the &lt;code&gt;ContextInjector&lt;&#x2F;code&gt; interface. This struct will hold both the configuration flags and the computed state (e.g., the logger).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; This struct holds our shared state.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; CommonOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    LogLevel&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; zapcore&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Level&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;loglevel&amp;quot; flagdescr:&amp;quot;Logging level&amp;quot; default:&amp;quot;info&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;   *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;zap&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   `flagignore:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; This field is computed, not a flag.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; Context injects the struct into the command context during auto-unmarshal.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;o &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;CommonOptions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Context&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;* ... *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; FromContext retrieves the struct from context (user-side, not interface-enforced).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;o &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;CommonOptions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; FromContext&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;* ... *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; Initialize is a custom method to create the computed state.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;o &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;CommonOptions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Initialize&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;* ... *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Bind the shared struct to the root command. &lt;code&gt;Bind&lt;&#x2F;code&gt; registers it for auto-unmarshal: the bind pipeline populates it and calls &lt;code&gt;Context()&lt;&#x2F;code&gt; to inject it before any &lt;code&gt;PreRunE&lt;&#x2F;code&gt; or &lt;code&gt;RunE&lt;&#x2F;code&gt; fires.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rootC&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; commonOpts&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;&#x2F;strong&gt; &lt;code&gt;Bind&lt;&#x2F;code&gt; on root creates &lt;strong&gt;local&lt;&#x2F;strong&gt; flags on the root command. By default, Cobra rejects unknown flags before finding the subcommand, so &lt;code&gt;app --loglevel info sub&lt;&#x2F;code&gt; would fail. Set &lt;code&gt;rootC.TraverseChildren = true&lt;&#x2F;code&gt; so root parses its own flags first, then resolves the subcommand. Alternatively, bind the shared struct on each leaf command that needs the flags.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If you need to initialize computed state (like a logger) after unmarshal, use a &lt;code&gt;PersistentPreRunE&lt;&#x2F;code&gt; hook: by the time it fires, &lt;code&gt;commonOpts&lt;&#x2F;code&gt; is already populated:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;rootC&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;PersistentPreRunE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;cobra&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; commonOpts is already populated by the bind pipeline.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; commonOpts&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Initialize&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Retrieve the state in subcommands. In your subcommand&#x27;s &lt;code&gt;RunE&lt;&#x2F;code&gt;, call &lt;code&gt;.FromContext()&lt;&#x2F;code&gt; to retrieve the shared, initialized object.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;cobra&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    config&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;CommonOptions&lt;&#x2F;span&gt;&lt;span&gt;{}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;FromContext&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Executing subcommand...&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This pattern ensures that subcommands remain decoupled while having access to a consistent, centrally-managed state.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; The deprecated &lt;code&gt;ContextOptions&lt;&#x2F;code&gt; interface (which embeds &lt;code&gt;Options&lt;&#x2F;code&gt; and requires &lt;code&gt;Attach&lt;&#x2F;code&gt;) still works for backward compatibility. New code should use &lt;code&gt;ContextInjector&lt;&#x2F;code&gt; instead.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;For a complete, runnable implementation of this pattern, see the loginsvc example located in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;loginsvc&#x2F;&quot;&gt;&#x2F;examples&#x2F;loginsvc&lt;&#x2F;a&gt; directory.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dart-enum-registration&quot;&gt;🎯 Enum Registration&lt;a class=&quot;zola-anchor&quot; href=&quot;#dart-enum-registration&quot; aria-label=&quot;Anchor link for: dart-enum-registration&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Register string or integer enum types once in &lt;code&gt;init()&lt;&#x2F;code&gt; and use them as plain struct fields. structcli handles flag creation, help text with allowed values, shell completion, validation, and config&#x2F;env decoding automatically.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;string-enums-registerenum&quot;&gt;String enums (&lt;code&gt;RegisterEnum&lt;&#x2F;code&gt;)&lt;a class=&quot;zola-anchor&quot; href=&quot;#string-enums-registerenum&quot; aria-label=&quot;Anchor link for: string-enums-registerenum&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-storage z-type z-string z-go&quot;&gt; Environment string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt;	EnvDev&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;  Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;dev&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt;	EnvProd&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;prod&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; init&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;RegisterEnum&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span&gt;][]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		EnvDev&lt;&#x2F;span&gt;&lt;span&gt;:  {&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;dev&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;development&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;   &#x2F;&#x2F; first string is canonical, rest are aliases&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		EnvProd&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;prod&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;production&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; DeployOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	TargetEnv&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;target-env&amp;quot; flagdescr:&amp;quot;Target environment&amp;quot; default:&amp;quot;dev&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This produces &lt;code&gt;--target-env&lt;&#x2F;code&gt; with help text showing &lt;code&gt;{dev,prod}&lt;&#x2F;code&gt;, shell completion for all values including aliases, and case-insensitive parsing that accepts both &lt;code&gt;prod&lt;&#x2F;code&gt; and &lt;code&gt;production&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;integer-enums-registerintenum&quot;&gt;Integer enums (&lt;code&gt;RegisterIntEnum&lt;&#x2F;code&gt;)&lt;a class=&quot;zola-anchor&quot; href=&quot;#integer-enums-registerintenum&quot; aria-label=&quot;Anchor link for: integer-enums-registerintenum&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-storage z-type z-numeric z-go&quot;&gt; Priority int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt;	PriorityLow&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Priority&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt;	PriorityMedium&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Priority&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt;	PriorityHigh&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;   Priority&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; init&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;RegisterIntEnum&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Priority&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Priority&lt;&#x2F;span&gt;&lt;span&gt;][]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		PriorityLow&lt;&#x2F;span&gt;&lt;span&gt;:    {&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;low&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		PriorityMedium&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;medium&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;med&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		PriorityHigh&lt;&#x2F;span&gt;&lt;span&gt;:   {&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;high&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;hi&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both functions panic on duplicate registration or empty values. Call them in &lt;code&gt;init()&lt;&#x2F;code&gt; before any &lt;code&gt;Define()&lt;&#x2F;code&gt; calls.&lt;&#x2F;p&gt;
&lt;p&gt;See &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;full&#x2F;cli&#x2F;cli.go&quot;&gt;full example&lt;&#x2F;a&gt; for enum registration in a complete CLI.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;boomerang-custom-type-handlers&quot;&gt;🪃 Custom Type Handlers&lt;a class=&quot;zola-anchor&quot; href=&quot;#boomerang-custom-type-handlers&quot; aria-label=&quot;Anchor link for: boomerang-custom-type-handlers&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;For types that need custom parsing logic beyond what enum registration provides, structcli offers two mechanisms: &lt;strong&gt;per-type registration&lt;&#x2F;strong&gt; and &lt;strong&gt;per-field hooks&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;per-type-registertype-t&quot;&gt;Per-type: &lt;code&gt;RegisterType[T]&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#per-type-registertype-t&quot; aria-label=&quot;Anchor link for: per-type-registertype-t&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Register custom hooks for a type once in &lt;code&gt;init()&lt;&#x2F;code&gt;. Every struct field of type &lt;code&gt;T&lt;&#x2F;code&gt; uses them automatically: no special tags needed. &lt;code&gt;RegisterType&lt;&#x2F;code&gt; panics on nil hooks or duplicate registration: call it in &lt;code&gt;init()&lt;&#x2F;code&gt; before any &lt;code&gt;Define&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Bind&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;github.com&#x2F;leodido&#x2F;structcli&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;github.com&#x2F;leodido&#x2F;structcli&#x2F;values&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; ListenAddress&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    Host&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    Port&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-numeric z-go&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    raw&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;  string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; init&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;RegisterType&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;ListenAddress&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;TypeHooks&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;ListenAddress&lt;&#x2F;span&gt;&lt;span&gt;]{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        Define&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; descr&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; sf&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; reflect&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;StructField&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fv&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; reflect&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Value&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;pflag&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            ptr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Addr&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Interface&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().(*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;ListenAddress&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; ListenAddress&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Host&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;localhost&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; Port&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; raw&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;localhost:8080&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; values&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewString&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;raw&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; descr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot; (host:port)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        Decode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; any&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;any&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; ParseListenAddress&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;.(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; ServerOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    ListenAddr&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; ListenAddress&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;listen&amp;quot; flagdescr:&amp;quot;Listen address&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both &lt;code&gt;Define&lt;&#x2F;code&gt; and &lt;code&gt;Decode&lt;&#x2F;code&gt; are required. Panics on duplicate registration or nil hooks. Call in &lt;code&gt;init()&lt;&#x2F;code&gt; before any &lt;code&gt;Define&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Bind&lt;&#x2F;code&gt; calls.&lt;&#x2F;p&gt;
&lt;p&gt;For enum types, prefer &lt;code&gt;RegisterEnum&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;RegisterIntEnum&lt;&#x2F;code&gt;: they wrap &lt;code&gt;RegisterType&lt;&#x2F;code&gt; with less boilerplate.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;per-field-fieldhookprovider-and-fieldcompleter&quot;&gt;Per-field: &lt;code&gt;FieldHookProvider&lt;&#x2F;code&gt; and &lt;code&gt;FieldCompleter&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#per-field-fieldhookprovider-and-fieldcompleter&quot; aria-label=&quot;Anchor link for: per-field-fieldhookprovider-and-fieldcompleter&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;When the same type needs different behavior in different fields, or when a standard type needs custom handling for a specific field, implement &lt;code&gt;FieldHookProvider&lt;&#x2F;code&gt; on your options struct. Map keys are struct field names.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; ServerOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    ListenAddr&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;listen&amp;quot; flagdescr:&amp;quot;Listen address&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    Mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;       string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;mode&amp;quot; flagdescr:&amp;quot;Server mode&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;o &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;ServerOptions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; FieldHooks&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;FieldHook&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;FieldHook&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;ListenAddr&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            Define&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; descr&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; sf&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; reflect&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;StructField&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fv&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; reflect&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Value&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;pflag&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                ptr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Addr&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Interface&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().(*&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;localhost:8080&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; values&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewString&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; descr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot; (host:port)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            Decode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; any&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;any&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; input&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For shell completion, implement &lt;code&gt;FieldCompleter&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;o &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;ServerOptions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; CompletionHooks&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;CompleteHookFunc&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;CompleteHookFunc&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;ListenAddr&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;cobra&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; toComplete&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;) ([]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; cobra&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;ShellCompDirective&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;localhost:8080&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;0.0.0.0:8080&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;0.0.0.0:443&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; cobra&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ShellCompDirectiveNoFileComp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;FieldCompleter&lt;&#x2F;code&gt; works for any field that becomes a flag, not only fields with &lt;code&gt;FieldHookProvider&lt;&#x2F;code&gt; hooks.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;precedence&quot;&gt;Precedence&lt;a class=&quot;zola-anchor&quot; href=&quot;#precedence&quot; aria-label=&quot;Anchor link for: precedence&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Hook resolution follows this order (highest to lowest):&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;FieldHookProvider&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: per-field hooks on the options struct&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;RegisterType&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; &#x2F; &lt;strong&gt;&lt;code&gt;RegisterEnum&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: per-type hooks in the global registry&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Built-in registry&lt;&#x2F;strong&gt;: &lt;code&gt;time.Duration&lt;&#x2F;code&gt;, &lt;code&gt;zapcore.Level&lt;&#x2F;code&gt;, &lt;code&gt;slog.Level&lt;&#x2F;code&gt;, etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Completion precedence:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If a completion function is already registered on a flag before &lt;code&gt;Define&lt;&#x2F;code&gt;, structcli preserves it.&lt;&#x2F;li&gt;
&lt;li&gt;If &lt;code&gt;Define&lt;&#x2F;code&gt; auto-registers a &lt;code&gt;FieldCompleter&lt;&#x2F;code&gt; hook, a later manual &lt;code&gt;RegisterFlagCompletionFunc&lt;&#x2F;code&gt; on the same flag returns Cobra&#x27;s &lt;code&gt;already registered&lt;&#x2F;code&gt; error.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;values&#x2F;values.go&quot;&gt;values&lt;&#x2F;a&gt; we provide &lt;code&gt;pflag.Value&lt;&#x2F;code&gt; implementations for standard types.&lt;&#x2F;p&gt;
&lt;p&gt;See the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;customtypes&#x2F;main.go&quot;&gt;custom types example&lt;&#x2F;a&gt; for a runnable demo of all three mechanisms, or the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;full&#x2F;cli&#x2F;cli.go&quot;&gt;full example&lt;&#x2F;a&gt; for a complete CLI.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bricks-built-in-custom-types&quot;&gt;🧱 Built-in Custom Types&lt;a class=&quot;zola-anchor&quot; href=&quot;#bricks-built-in-custom-types&quot; aria-label=&quot;Anchor link for: bricks-built-in-custom-types&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Description&lt;&#x2F;th&gt;&lt;th&gt;Example Values&lt;&#x2F;th&gt;&lt;th&gt;Special Features&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;zapcore.Level&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Zap logging levels&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;debug&lt;&#x2F;code&gt;, &lt;code&gt;info&lt;&#x2F;code&gt;, &lt;code&gt;warn&lt;&#x2F;code&gt;, &lt;code&gt;error&lt;&#x2F;code&gt;, &lt;code&gt;dpanic&lt;&#x2F;code&gt;, &lt;code&gt;panic&lt;&#x2F;code&gt;, &lt;code&gt;fatal&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Enum validation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;slog.Level&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Standard library logging levels&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;debug&lt;&#x2F;code&gt;, &lt;code&gt;info&lt;&#x2F;code&gt;, &lt;code&gt;warn&lt;&#x2F;code&gt;, &lt;code&gt;error&lt;&#x2F;code&gt;, &lt;code&gt;error+2&lt;&#x2F;code&gt;, ...&lt;&#x2F;td&gt;&lt;td&gt;Level offsets: &lt;code&gt;ERROR+2&lt;&#x2F;code&gt;, &lt;code&gt;INFO-4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;time.Duration&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Time durations&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;30s&lt;&#x2F;code&gt;, &lt;code&gt;5m&lt;&#x2F;code&gt;, &lt;code&gt;2h&lt;&#x2F;code&gt;, &lt;code&gt;1h30m&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Go duration parsing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;[]time.Duration&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Duration slices&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;30s,5m&lt;&#x2F;code&gt;, &lt;code&gt;1s,2m30s&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Comma-separated &#x2F; repeated flags&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;[]bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Boolean slices&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;true,false,true&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Comma-separated &#x2F; repeated flags&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;[]uint&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Unsigned integer slices&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;1,2,3,42&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Comma-separated &#x2F; repeated flags&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;[]byte&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Raw textual bytes&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;hello&lt;&#x2F;code&gt;, &lt;code&gt;abc123&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Raw textual input&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;structcli.Hex&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Hex-decoded textual input&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;68656c6c6f&lt;&#x2F;code&gt;, &lt;code&gt;48656c6c6f&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Hex decoding&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;structcli.Base64&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Base64-decoded textual input&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;aGVsbG8=&lt;&#x2F;code&gt;, &lt;code&gt;YWJjMTIz&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Base64 decoding&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;net.IP&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;IP address&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;127.0.0.1&lt;&#x2F;code&gt;, &lt;code&gt;10.42.0.10&lt;&#x2F;code&gt;, &lt;code&gt;2001:db8::1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;IP parsing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;net.IPMask&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;IPv4 mask&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;255.255.255.0&lt;&#x2F;code&gt;, &lt;code&gt;ffffff00&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Dotted or hex mask parsing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;net.IPNet&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;CIDR subnet&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;10.42.0.0&#x2F;24&lt;&#x2F;code&gt;, &lt;code&gt;2001:db8::&#x2F;64&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;CIDR parsing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;[]net.IP&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;IP slices&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;10.0.0.1,10.0.0.2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Comma-separated &#x2F; repeated flags&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;[]string&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;String slices&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;item1,item2,item3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Comma-separated&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;[]int&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Integer slices&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;1,2,3,42&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Comma-separated&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;map[string]string&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;String maps&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;env=prod,team=platform&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;key=value&lt;&#x2F;code&gt; pairs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;map[string]int&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Integer maps&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;cpu=2,memory=4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;key=value&lt;&#x2F;code&gt; pairs with int parsing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;map[string]int64&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;64-bit integer maps&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;ok=1,fail=2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;key=value&lt;&#x2F;code&gt; pairs with int64 parsing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Note on JSON output: &lt;code&gt;net.IPMask&lt;&#x2F;code&gt; is a byte slice under the hood, so Go&#x27;s &lt;code&gt;encoding&#x2F;json&lt;&#x2F;code&gt;
renders it as base64 (for example &lt;code&gt;255.255.255.0&lt;&#x2F;code&gt; appears as &lt;code&gt;&#x2F;&#x2F;&#x2F;&#x2F;AA==&lt;&#x2F;code&gt;). This is expected.&lt;&#x2F;p&gt;
&lt;p&gt;All built-in types support:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Command-line flags with validation and help text&lt;&#x2F;li&gt;
&lt;li&gt;Environment variables with automatic binding&lt;&#x2F;li&gt;
&lt;li&gt;Configuration files (YAML, JSON, TOML)&lt;&#x2F;li&gt;
&lt;li&gt;Type validation with helpful error messages&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Slices and maps use the same contract across flags, env vars, and config.&lt;&#x2F;p&gt;
&lt;p&gt;See &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;collections&#x2F;main.go&quot;&gt;examples&#x2F;collections&#x2F;main.go&lt;&#x2F;a&gt; for a runnable version of this example.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; AdvancedOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Retries&lt;&#x2F;span&gt;&lt;span&gt;   []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-numeric z-go&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;          `flag:&amp;quot;retries&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Backoffs&lt;&#x2F;span&gt;&lt;span&gt;  []&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;backoffs&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	FeatureOn&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-boolean z-go&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;          `flag:&amp;quot;feature-on&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Labels&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;    map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;labels&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Limits&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;    map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-numeric z-go&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    `flag:&amp;quot;limits&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	Counts&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;    map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-numeric z-go&quot;&gt;int64&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  `flag:&amp;quot;counts&amp;quot; flagenv:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myapp&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --retries&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1,2,3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --backoffs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1s,5s&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option z-constant z-language&quot;&gt; --feature-on true&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-constant z-other z-option&quot;&gt;false --labels&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; env=prod,team=platform&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --limits&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cpu=8,memory=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --counts&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ok=10,fail=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; MYAPP_RETRIES=1,2,3 MYAPP_BACKOFFS=1s,5s MYAPP_FEATURE_ON=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;false&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; MYAPP_LABELS=env=prod,team=platform MYAPP_LIMITS=cpu=8,memory=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; MYAPP_COUNTS=ok=10,fail=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myapp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; go run examples&#x2F;collections&#x2F;main.go&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --config&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; examples&#x2F;collections&#x2F;config.yaml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;retries&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;1,2,3&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;backoffs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 5s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;feature-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;true,false&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  env&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; prod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  team&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; platform&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;limits&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  cpu&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  memory&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 16&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;counts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;ok=10,fail=3&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;toolbox-reusable-flag-kits&quot;&gt;🧰 Reusable Flag Kits&lt;a class=&quot;zola-anchor&quot; href=&quot;#toolbox-reusable-flag-kits&quot; aria-label=&quot;Anchor link for: toolbox-reusable-flag-kits&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;flagkit&lt;&#x2F;code&gt; package provides pre-built, embeddable flag structs that standardize common CLI flag declarations. Each type encapsulates one flag with an opinionated name, type, and default matching industry conventions. This gives AI agents and scripts a consistent vocabulary across CLIs built with structcli.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;github.com&#x2F;leodido&#x2F;structcli&#x2F;flagkit&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; LogsOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    flagkit&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Follow&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;                                                    &#x2F;&#x2F; --follow&#x2F;-f (default: false)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `flag:&amp;quot;service&amp;quot; flagshort:&amp;quot;s&amp;quot; flagdescr:&amp;quot;Service name&amp;quot; flagrequired:&amp;quot;true&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;o &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;LogsOptions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Attach&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;cobra&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Command&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; structcli&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; o&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    flagkit&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;AnnotateCommand&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; marks flagkit-owned flags for doc generation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;Attach&lt;&#x2F;code&gt; is needed here because of the custom &lt;code&gt;flagkit.AnnotateCommand&lt;&#x2F;code&gt; call. For structs without custom define-time logic, use &lt;code&gt;structcli.Bind(cmd, opts)&lt;&#x2F;code&gt; instead: it handles both plain structs and &lt;code&gt;Options&lt;&#x2F;code&gt; implementors.&lt;&#x2F;p&gt;
&lt;p&gt;Available types:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Flag&lt;&#x2F;th&gt;&lt;th&gt;Default&lt;&#x2F;th&gt;&lt;th&gt;Description&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Follow&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--follow&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;-f&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;false&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Opt-in streaming (agents won&#x27;t hang)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;LogLevel&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--log-level&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;info&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Log level via zapcore (alias for &lt;code&gt;ZapLogLevel&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;ZapLogLevel&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--log-level&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;info&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Log level backed by &lt;code&gt;zapcore.Level&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SlogLogLevel&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--log-level&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;info&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Log level backed by &lt;code&gt;slog.Level&lt;&#x2F;code&gt; (stdlib)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Output&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--output&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;-o&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;text&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Output format (string enum, user-registered)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Verbose&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--verbose&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;-v&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Verbosity count (&lt;code&gt;-v&lt;&#x2F;code&gt;, &lt;code&gt;-vv&lt;&#x2F;code&gt;, &lt;code&gt;-vvv&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;DryRun&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--dry-run&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;false&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Preview without making changes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Timeout&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--timeout&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;30s&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Operation timeout (&lt;code&gt;time.Duration&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Quiet&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--quiet&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;-q&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;false&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Suppress non-essential output&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;When the &lt;code&gt;generate&lt;&#x2F;code&gt; package detects flagkit annotations, it emits a &quot;Development Notes&quot; section in AGENTS.md guiding AI coding agents to prefer flagkit types over ad-hoc flag declarations.&lt;&#x2F;p&gt;
&lt;p&gt;See &lt;code&gt;go doc github.com&#x2F;leodido&#x2F;structcli&#x2F;flagkit&lt;&#x2F;code&gt; for the full taxonomy and composition examples.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;art-beautiful-organized-help-output&quot;&gt;🎨 Beautiful, Organized Help Output&lt;a class=&quot;zola-anchor&quot; href=&quot;#art-beautiful-organized-help-output&quot; aria-label=&quot;Anchor link for: art-beautiful-organized-help-output&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Organize your &lt;code&gt;--help&lt;&#x2F;code&gt; output into logical groups for better readability.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; go run examples&#x2F;full&#x2F;main.go&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# A demonstration of the structcli library with beautiful CLI features&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Usage:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   full [flags]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   full [command]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Available Commands:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   completion  Generate the autocompletion script for the specified shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   help        Help about any command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   logs        Show service logs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   preset      Demonstrate flag presets with validation and transformation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   srv         Start the server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   usr         User management&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   -h, --help   help for full&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Utility Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --dry             &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   -v, --verbose count&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Global Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --config string                   config file (fallbacks to: {&#x2F;etc&#x2F;full,{executable_dir}&#x2F;.full,$HOME&#x2F;.full,...}&#x2F;config.{yaml,json,toml})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --debug-options string[=&amp;quot;text&amp;quot;]   debug output format (text, json)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --jsonschema string[=&amp;quot;true&amp;quot;]      output JSON Schema and exit (bare: this command, =tree: full subtree)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --mcp                             serve MCP over stdio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Reference:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   config-keys List all configuration file keys&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   env-vars    List all environment variable bindings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; go run examples&#x2F;full&#x2F;main.go srv&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Start the server with the specified configuration&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Usage:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   full srv [flags]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   full srv [command]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Available Commands:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   version     Print version information&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --apikey string                  API authentication key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --deep-setting string             (default &amp;quot;default-deep-setting&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --deep.deeper.nodefault string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --deeper-setting string           (default &amp;quot;default-deeper-setting&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   -h, --help                           help for srv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --host string                    Server host (default &amp;quot;localhost&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#   -p, --port int                       Server port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --target-env string              Set the target environment {dev,prod,staging} (default &amp;quot;dev&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Database Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --database.maxconns int   Max database connections (default 10)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --db-url string           Database connection URL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Logging Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --log-file string           Log file path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --log-level zapcore.Level   Set log level {debug,info,warn,error,dpanic,panic,fatal} (default info)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Network Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --advertise-cidr ipNet    Advertised service subnet (CIDR) (default 127.0.0.0&#x2F;24)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --bind-ip ip              Bind interface IP (default 127.0.0.1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --bind-mask ipMask        Bind interface mask (default ffffff00)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --trusted-peers ipSlice   Trusted peer IPs (comma separated) (default 127.0.0.2,127.0.0.3)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Security Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --token-base64 bytesBase64   Token bytes encoded as base64 (default aGVsbG8=)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --token-hex bytesHex         Token bytes encoded as hex (default 68656c6c6f)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Global Flags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --config string                   config file (fallbacks to: {&#x2F;etc&#x2F;full,{executable_dir}&#x2F;.full,$HOME&#x2F;.full,...}&#x2F;config.{yaml,json,toml})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --debug-options string[=&amp;quot;text&amp;quot;]   debug output format (text, json)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --jsonschema string[=&amp;quot;true&amp;quot;]      output JSON Schema and exit (bare: this command, =tree: full subtree)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#       --mcp                             serve MCP over stdio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Use &amp;quot;full srv [command] --help&amp;quot; for more information about a command.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;globe-with-meridians-webassembly-wasm&quot;&gt;🌐 WebAssembly (WASM)&lt;a class=&quot;zola-anchor&quot; href=&quot;#globe-with-meridians-webassembly-wasm&quot; aria-label=&quot;Anchor link for: globe-with-meridians-webassembly-wasm&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;structcli avoids &lt;code&gt;reflect.Value.MethodByName&lt;&#x2F;code&gt; and &lt;code&gt;reflect.Value.Call&lt;&#x2F;code&gt;, so the Go compiler&#x27;s dead-code elimination (DCE) works correctly and WASM binaries stay lean. All features work under &lt;code&gt;GOOS=wasip1 GOARCH=wasm&lt;&#x2F;code&gt; with the standard Go compiler, including custom type hooks (&lt;code&gt;RegisterType[T]&lt;&#x2F;code&gt;, &lt;code&gt;FieldHookProvider&lt;&#x2F;code&gt;), JSON Schema generation, structured errors, and debug output.&lt;&#x2F;p&gt;
&lt;p&gt;Build and run any structcli program as WASM:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;GOOS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;wasip1&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; GOARCH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;wasm&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; go&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myapp.wasm .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;wasmtime&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --dir=&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myapp.wasm serve&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --port&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This means structcli CLIs can run in sandboxed WASM runtimes, edge functions, and browser-based environments. Combined with &lt;code&gt;--jsonschema&lt;&#x2F;code&gt; and &lt;code&gt;--mcp&lt;&#x2F;code&gt;, an agent can discover the CLI contract, call it in a sandboxed WASM runtime, and handle structured failures without ever touching the host OS.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;label-available-struct-tags&quot;&gt;🏷️ Available Struct Tags&lt;a class=&quot;zola-anchor&quot; href=&quot;#label-available-struct-tags&quot; aria-label=&quot;Anchor link for: label-available-struct-tags&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Use these tags in your struct fields to control the behavior:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Tag&lt;&#x2F;th&gt;&lt;th&gt;Description&lt;&#x2F;th&gt;&lt;th&gt;Example&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flag&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Sets a custom name for the flag (otherwise, generated from the field name)&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flag:&quot;log-level&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flagpreset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Defines CLI-only preset aliases for this field&#x27;s flag. Each preset is &lt;code&gt;&amp;lt;alias-flag-name&amp;gt;=&amp;lt;value-for-this-field-flag&amp;gt;&lt;&#x2F;code&gt;. No env&#x2F;config keys are created.&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flagpreset:&quot;logeverything=5;logquiet=0&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flagshort&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Sets a single-character shorthand for the flag&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flagshort:&quot;l&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flagdescr&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Provides the help text for the flag&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flagdescr:&quot;Logging level&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;default&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Sets the default value for the flag&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;default:&quot;info&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flagenv&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Enables binding to an environment variable (&lt;code&gt;&quot;true&quot;&lt;&#x2F;code&gt;, &lt;code&gt;&quot;false&quot;&lt;&#x2F;code&gt;, or &lt;code&gt;&quot;only&quot;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flagenv:&quot;true&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flagrequired&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Marks the flag as required (&lt;code&gt;&quot;true&quot;&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;&quot;false&quot;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flagrequired:&quot;true&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flaghidden&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Hides the flag from help&#x2F;usage output and machine-readable schemas while keeping it fully functional (&lt;code&gt;&quot;true&quot;&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;&quot;false&quot;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flaghidden:&quot;true&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flaggroup&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Assigns the flag to a group in the help message&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flaggroup:&quot;Database&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flagignore&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Skips creating a flag for this field (&lt;code&gt;&quot;true&quot;&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;&quot;false&quot;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flagignore:&quot;true&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flagtype&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Specifies a special flag type. Currently supports &lt;code&gt;count&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;flagtype:&quot;count&quot;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;code&gt;flagpreset&lt;&#x2F;code&gt; is syntactic sugar: it creates alias flags that set the canonical flag value.
Format: &lt;code&gt;&amp;lt;alias&amp;gt;=&amp;lt;value&amp;gt;&lt;&#x2F;code&gt;; multiple entries can be separated by &lt;code&gt;;&lt;&#x2F;code&gt; or &lt;code&gt;,&lt;&#x2F;code&gt;.
Example: &lt;code&gt;flagpreset:&quot;logeverything=5;logquiet=0&quot;&lt;&#x2F;code&gt; makes &lt;code&gt;--logeverything&lt;&#x2F;code&gt; behave like &lt;code&gt;--loglevel=5&lt;&#x2F;code&gt;.
If both alias and canonical flags are passed, the last assignment in argv wins.
It does not bypass transform&#x2F;validate flow.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;flaghidden:&quot;true&quot; + flagenv:&quot;true&quot;&lt;&#x2F;code&gt; vs &lt;code&gt;flagenv:&quot;only&quot;&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;flaghidden:&quot;true&quot; + flagenv:&quot;true&quot;&lt;&#x2F;code&gt;: hidden from help, but &lt;strong&gt;accepts CLI input&lt;&#x2F;strong&gt; via &lt;code&gt;--flag=value&lt;&#x2F;code&gt;. Use for flags that should be discoverable only by advanced users or scripts.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;flagenv:&quot;only&quot;&lt;&#x2F;code&gt;: hidden from help, &lt;strong&gt;rejects CLI input&lt;&#x2F;strong&gt; at runtime. The field is settable only via environment variable or config file. Use for secrets and deployment-time configuration that should never appear on a command line.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;flagenv:&quot;only&quot;&lt;&#x2F;code&gt; is incompatible with &lt;code&gt;flagshort&lt;&#x2F;code&gt;, &lt;code&gt;flagpreset&lt;&#x2F;code&gt;, and &lt;code&gt;flagtype&lt;&#x2F;code&gt; (these are CLI-only concepts). It supports &lt;code&gt;flagdescr&lt;&#x2F;code&gt;, &lt;code&gt;flaggroup&lt;&#x2F;code&gt;, &lt;code&gt;flagrequired&lt;&#x2F;code&gt;, and &lt;code&gt;default&lt;&#x2F;code&gt;. &lt;code&gt;FieldHookProvider&lt;&#x2F;code&gt; Define&#x2F;Decode hooks work normally on &lt;code&gt;flagenv:&quot;only&quot;&lt;&#x2F;code&gt; fields (the flag is created then hidden). &lt;code&gt;FieldCompleter&lt;&#x2F;code&gt; hooks are skipped since hidden flags have no CLI completion.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;book-documentation&quot;&gt;📖 Documentation&lt;a class=&quot;zola-anchor&quot; href=&quot;#book-documentation&quot; aria-label=&quot;Anchor link for: book-documentation&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;For comprehensive documentation and advanced usage patterns, visit the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pkg.go.dev&#x2F;github.com&#x2F;leodido&#x2F;structcli&quot;&gt;documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Start here for repo-local guides:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;docs&#x2F;ai-native.md&quot;&gt;AI-Native CLIs guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;structerr&#x2F;README.md&quot;&gt;Structured error example walkthrough&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;structcli&#x2F;tree&#x2F;main&#x2F;examples&#x2F;&quot;&gt;Examples directory&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;handshake-contributing&quot;&gt;🤝 Contributing&lt;a class=&quot;zola-anchor&quot; href=&quot;#handshake-contributing&quot; aria-label=&quot;Anchor link for: handshake-contributing&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Contributions are welcome!&lt;&#x2F;p&gt;
&lt;p&gt;Please feel free to submit a Pull Request.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>go-conventionalcommits</title>
        <published>2020-11-18T00:00:00+00:00</published>
        <updated>2020-11-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://leodido.dev/projects/go-conventionalcommits/"/>
        <id>https://leodido.dev/projects/go-conventionalcommits/</id>
        
        <content type="html" xml:base="https://leodido.dev/projects/go-conventionalcommits/">&lt;p&gt;This repository provides a library to parse your commit messages according to the Conventional Commits v1.0 specification.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;a class=&quot;zola-anchor&quot; href=&quot;#installation&quot; aria-label=&quot;Anchor link for: installation&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;go&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; get github.com&#x2F;leodido&#x2F;go-conventionalcommits&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;docs&quot;&gt;Docs&lt;a class=&quot;zola-anchor&quot; href=&quot;#docs&quot; aria-label=&quot;Anchor link for: docs&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-conventionalcommits&#x2F;tree&#x2F;develop&#x2F;parser&#x2F;docs&#x2F;&quot;&gt;parser&#x2F;docs&lt;&#x2F;a&gt; directory contains &lt;code&gt;.dot&lt;&#x2F;code&gt; and &lt;code&gt;.png&lt;&#x2F;code&gt; files representing the finite-state machines (FSMs) implementing the parser.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;a class=&quot;zola-anchor&quot; href=&quot;#usage&quot; aria-label=&quot;Anchor link for: usage&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;parse&quot;&gt;Parse&lt;a class=&quot;zola-anchor&quot; href=&quot;#parse&quot; aria-label=&quot;Anchor link for: parse&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Your code base uses only single line commit messages like this one?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;feat:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; awesomeness&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No problem at all since the body and the footer parts are not mandatory:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;([]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`feat: awesomeness`&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;full-conventional-commit-messages&quot;&gt;Full conventional commit messages&lt;a class=&quot;zola-anchor&quot; href=&quot;#full-conventional-commit-messages&quot; aria-label=&quot;Anchor link for: full-conventional-commit-messages&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Imagine you have a commit message like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;docs:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; correct minor typos&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;see&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the issue for details&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;on&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; docs edits.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Reviewed-by:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Refs&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; #133&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Go with this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := []&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;conventionalcommits&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;MachineOption&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    WithTypes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;conventionalcommits&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;TypesConventional&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;...).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or, more simpler:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithTypes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;conventionalcommits&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;TypesConventional&lt;&#x2F;span&gt;&lt;span&gt;)).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;types&quot;&gt;Types&lt;a class=&quot;zola-anchor&quot; href=&quot;#types&quot; aria-label=&quot;Anchor link for: types&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;This library provides support for different types sets:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;minimal&lt;&#x2F;strong&gt;: fix, feat&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;conventional&lt;&#x2F;strong&gt;: build, ci, chore, docs, feat, fix, perf, refactor, revert, style, test&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;falco&lt;&#x2F;strong&gt;: build, ci, chore, docs, feat, fix, perf, new, revert, update, test, rule&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;At the moment, those types are at build time. Which means users can&#x27;t configure them at runtime.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, there&#x27;s also a &lt;strong&gt;free-form&lt;&#x2F;strong&gt; types set that accepts any combination of printable characters (before the separator after which the commit description starts) as a valid type.&lt;&#x2F;p&gt;
&lt;p&gt;You can choose the type set passing the &lt;code&gt;WithTypes(conventionalcommits.TypesConventional)&lt;&#x2F;code&gt; option as shown above.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;options&quot;&gt;Options&lt;a class=&quot;zola-anchor&quot; href=&quot;#options&quot; aria-label=&quot;Anchor link for: options&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;A parser behaviour is configurable by using options.&lt;&#x2F;p&gt;
&lt;p&gt;You can set them calling a function on the parser machine.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithBestEffort&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or you can provide options to &lt;code&gt;NewMachine(...)&lt;&#x2F;code&gt; directly.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithBestEffort&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;best-effort&quot;&gt;Best effort&lt;a class=&quot;zola-anchor&quot; href=&quot;#best-effort&quot; aria-label=&quot;Anchor link for: best-effort&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The best effort mode will make the parser return what it found until the point it errored out,
if it found (at least) a valid type and a valid description.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s make an example.&lt;&#x2F;p&gt;
&lt;p&gt;Suppose this input commit message:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fix:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; description&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; blank line is mandatory to start the body part of the commit message!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The input does not respect the Conventional Commits v1 specification because it lacks a blank line after the description (before the body).&lt;&#x2F;p&gt;
&lt;p&gt;Anyways, if the parser you&#x27;re using has the best effort mode enabled, you can still obtain some structured data since at least a valid type and description have been found!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithBestEffort&lt;&#x2F;span&gt;&lt;span&gt;()).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The result will contain a &lt;code&gt;ConventionalCommit&lt;&#x2F;code&gt; struct instance with the &lt;code&gt;Type&lt;&#x2F;code&gt; and the &lt;code&gt;Description&lt;&#x2F;code&gt; fields populated and ignore the rest after the error column.&lt;&#x2F;p&gt;
&lt;p&gt;The parser will still return the error (with the position information), so that you can eventually use it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;trailer-parsing&quot;&gt;Trailer parsing&lt;a class=&quot;zola-anchor&quot; href=&quot;#trailer-parsing&quot; aria-label=&quot;Anchor link for: trailer-parsing&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The parser implements &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.conventionalcommits.org&#x2F;en&#x2F;v1.0.0&#x2F;#specification&quot;&gt;Conventional Commits v1.0 clauses 8 to 10&lt;&#x2F;a&gt; for trailers (also called footers). A few behaviors are worth calling out.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;trailer-shaped-lines-in-the-body-stay-in-the-body&quot;&gt;Trailer-shaped lines in the body stay in the body&lt;a class=&quot;zola-anchor&quot; href=&quot;#trailer-shaped-lines-in-the-body-stay-in-the-body&quot; aria-label=&quot;Anchor link for: trailer-shaped-lines-in-the-body-stay-in-the-body&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;A line in the body that looks like a trailer (say, &lt;code&gt;Fixes #123&lt;&#x2F;code&gt;) is not picked up as one. The trailer block is only the run of trailer lines at the end of the message, with a blank line between it and the body.&lt;&#x2F;p&gt;
&lt;p&gt;Given this commit message:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fix:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;This&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; paragraph mentions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fixes&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; #123 in passing.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Reviewed-by:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; X&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;in&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;fix: x&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;This paragraph mentions&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Fixes #123 in passing.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Reviewed-by: X&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithTypes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;conventionalcommits&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;TypesFreeForm&lt;&#x2F;span&gt;&lt;span&gt;)).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; m.Body    == &amp;quot;This paragraph mentions\nFixes #123 in passing.&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; m.Footers == map[reviewed-by:[X]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A message whose body ends with a trailer-shaped line but has no real trailer block keeps the line as body content:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fix:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;This&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; paragraph mentions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fixes&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; #123 in passing.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;in&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;fix: x&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;This paragraph mentions&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Fixes #123 in passing.&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithTypes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;conventionalcommits&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;TypesFreeForm&lt;&#x2F;span&gt;&lt;span&gt;)).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; m.Body    == &amp;quot;This paragraph mentions\nFixes #123 in passing.&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; m.Footers == map[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;multi-line-trailer-values&quot;&gt;Multi-line trailer values&lt;a class=&quot;zola-anchor&quot; href=&quot;#multi-line-trailer-values&quot; aria-label=&quot;Anchor link for: multi-line-trailer-values&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Clause 10 says a trailer&#x27;s value can contain spaces and newlines. The value keeps going until the parser sees the next trailer (a &lt;code&gt;Token: value&lt;&#x2F;code&gt; line) or a blank line.&lt;&#x2F;p&gt;
&lt;p&gt;Given this commit message:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fix:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;BREAKING&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; CHANGE: this is a long&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  explanation&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; that wraps&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  across&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; several lines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Reviewed-by:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; X&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;in&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;fix: x&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;BREAKING CHANGE: this is a long&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  explanation that wraps&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  across several lines&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Reviewed-by: X&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithTypes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;conventionalcommits&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;TypesFreeForm&lt;&#x2F;span&gt;&lt;span&gt;)).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; m.Footers == map[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   breaking-change: [&amp;quot;this is a long\n  explanation that wraps\n  across several lines&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   reviewed-by:     [&amp;quot;X&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;blank-separated-trailers&quot;&gt;Blank-separated trailers&lt;a class=&quot;zola-anchor&quot; href=&quot;#blank-separated-trailers&quot; aria-label=&quot;Anchor link for: blank-separated-trailers&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Clause 8 lets you put a blank line between trailers. Both layouts parse the same way.&lt;&#x2F;p&gt;
&lt;p&gt;Blank-separated:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;feat:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fixes&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; #1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Reviewed-by:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; X&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Adjacent:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;feat:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fixes&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; #1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Reviewed-by:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; X&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(...).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;([]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;feat: x&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Fixes #1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Reviewed-by: X&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(...).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;([]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;feat: x&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Fixes #1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Reviewed-by: X&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; Both yield: footers == map[fixes:[1] reviewed-by:[X]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;what-parse-returns&quot;&gt;What &lt;code&gt;Parse&lt;&#x2F;code&gt; returns&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-parse-returns&quot; aria-label=&quot;Anchor link for: what-parse-returns&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;In strict mode (best-effort off), &lt;code&gt;Parse&lt;&#x2F;code&gt; returns one of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;(*ConventionalCommit, nil)&lt;&#x2F;code&gt; on success&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;(nil, error)&lt;&#x2F;code&gt; on failure&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It never returns &lt;code&gt;(nil, nil)&lt;&#x2F;code&gt;, so a &lt;code&gt;nil&lt;&#x2F;code&gt; first value always means the second value is the real error.&lt;&#x2F;p&gt;
&lt;p&gt;In best-effort mode you can also get &lt;code&gt;(*ConventionalCommit, error)&lt;&#x2F;code&gt;: a partial commit recovered before the parser ran into the problem, plus the error telling you where it stopped.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performances&quot;&gt;Performances&lt;a class=&quot;zola-anchor&quot; href=&quot;#performances&quot; aria-label=&quot;Anchor link for: performances&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;To run the benchmark suite execute the following command.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;make&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bench&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All the parsers have the best effort mode on.&lt;&#x2F;p&gt;
&lt;p&gt;On my machine&lt;sup&gt;&lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;go-conventionalcommits&#x2F;#mymachine&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, these are the results for the &lt;code&gt;slim&lt;&#x2F;code&gt; parser with the default - ie., &lt;code&gt;minimal&lt;&#x2F;code&gt;, commit message types.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal______________________________________-12          4876018       242 ns&#x2F;op     147 B&#x2F;op       5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal_with_scope___________________________-12          4258562       284 ns&#x2F;op     163 B&#x2F;op       6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal_breaking_with_scope__________________-12          4176747       288 ns&#x2F;op     163 B&#x2F;op       6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_full_with_50_characters_long_description_____-12          1661618       700 ns&#x2F;op     288 B&#x2F;op      10 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_empty________________________________________-12          4059327       292 ns&#x2F;op     112 B&#x2F;op       3 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_type_but_missing_colon_______________________-12          2701904       444 ns&#x2F;op     200 B&#x2F;op       6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_type_but_missing_description_________________-12          2207985       539 ns&#x2F;op     288 B&#x2F;op       8 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_type_and_scope_but_missing_description_______-12          1969390       605 ns&#x2F;op     312 B&#x2F;op      10 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_breaking_with_type_and_scope_but_missing_desc-12          1978302       606 ns&#x2F;op     312 B&#x2F;op      10 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[~~]_newline_in_description_______________________-12          2115649       563 ns&#x2F;op     232 B&#x2F;op      11 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_missing_whitespace_in_description____________-12          1997863       595 ns&#x2F;op     312 B&#x2F;op      10 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using another set of commit message types, for example the &lt;code&gt;conventional&lt;&#x2F;code&gt; one, does not have any noticeable impact on performances, as you can see below.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal______________________________________-12          5297486       228 ns&#x2F;op     147 B&#x2F;op       5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal_with_scope___________________________-12          4498694       267 ns&#x2F;op     163 B&#x2F;op       6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal_breaking_with_scope__________________-12          4431040       273 ns&#x2F;op     163 B&#x2F;op       6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_full_with_50_characters_long_description_____-12          1750111       692 ns&#x2F;op     288 B&#x2F;op      10 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_empty________________________________________-12          3996532       294 ns&#x2F;op     112 B&#x2F;op       3 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_type_but_missing_colon_______________________-12          2657913       451 ns&#x2F;op     200 B&#x2F;op       6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_type_but_missing_description_________________-12          2172524       553 ns&#x2F;op     288 B&#x2F;op       8 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_type_and_scope_but_missing_description_______-12          1880526       637 ns&#x2F;op     312 B&#x2F;op      10 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_breaking_with_type_and_scope_but_missing_desc-12          1879779       635 ns&#x2F;op     312 B&#x2F;op      10 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[~~]_newline_in_description_______________________-12          2023514       592 ns&#x2F;op     232 B&#x2F;op      11 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_missing_whitespace_in_description____________-12          1883124       623 ns&#x2F;op     312 B&#x2F;op      10 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you may notice, this library is very fast at what it does.&lt;&#x2F;p&gt;
&lt;p&gt;Parsing a commit goes from taking about the same amount of time (~299ns) the half-life of polonium-212 takes&lt;sup&gt;&lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;go-conventionalcommits&#x2F;#nanosecondwiki&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; to less than a microsecond.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;build&quot;&gt;Build&lt;a class=&quot;zola-anchor&quot; href=&quot;#build&quot; aria-label=&quot;Anchor link for: build&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;To build this Go library locally just run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;make&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;d need Ragel 6.10 to be present into your machine.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a name=&quot;mymachine&quot;&gt;[1]&lt;&#x2F;a&gt;: Intel Core i7-8850H CPU @ 2.60GHz&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a name=&quot;nanosecondwiki&quot;&gt;[2]&lt;&#x2F;a&gt;: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;nanosecond&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;nanosecond&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>kubectl-trace</title>
        <published>2018-11-21T00:00:00+00:00</published>
        <updated>2018-11-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://leodido.dev/projects/kubectl-trace/"/>
        <id>https://leodido.dev/projects/kubectl-trace/</id>
        
        <content type="html" xml:base="https://leodido.dev/projects/kubectl-trace/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;master&#x2F;docs&#x2F;logo&#x2F;logo-sm.png&quot; alt=&quot;Kubectl trace Logo&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;kubectl trace&lt;&#x2F;code&gt; is a kubectl plugin that allows you to schedule the execution
of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iovisor&#x2F;bpftrace&quot;&gt;bpftrace&lt;&#x2F;a&gt; programs in your Kubernetes cluster.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;master&#x2F;docs&#x2F;img&#x2F;intro.png&quot; alt=&quot;Screenshot showing the read.bt program for kubectl-trace&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installing&quot;&gt;Installing&lt;a class=&quot;zola-anchor&quot; href=&quot;#installing&quot; aria-label=&quot;Anchor link for: installing&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;krew&quot;&gt;Krew&lt;a class=&quot;zola-anchor&quot; href=&quot;#krew&quot; aria-label=&quot;Anchor link for: krew&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;You can install &lt;code&gt;kubectl trace&lt;&#x2F;code&gt; using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes-sigs&#x2F;krew&quot;&gt;Krew&lt;&#x2F;a&gt;, the package manager for kubectl plugins.&lt;&#x2F;p&gt;
&lt;p&gt;Once you have &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;krew.sigs.k8s.io&#x2F;docs&#x2F;user-guide&#x2F;setup&#x2F;install&#x2F;&quot;&gt;Krew installed&lt;&#x2F;a&gt; just run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kubectl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; krew install trace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;re ready to go!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pre-built-binaries&quot;&gt;Pre-built binaries&lt;a class=&quot;zola-anchor&quot; href=&quot;#pre-built-binaries&quot; aria-label=&quot;Anchor link for: pre-built-binaries&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;See the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;releases&quot;&gt;release&lt;&#x2F;a&gt; page for the full list of pre-built assets.&lt;&#x2F;p&gt;
&lt;p&gt;The commands here show &lt;code&gt;amd64&lt;&#x2F;code&gt; versions, &lt;code&gt;386&lt;&#x2F;code&gt; versions are available in the releases page.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Linux&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -L -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectl-trace.tar.gz https:&#x2F;&#x2F;github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;releases&#x2F;download&#x2F;v0.1.0-rc.1&#x2F;kubectl-trace_0.1.0-rc.1_linux_amd64.tar.gz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;tar&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -xvf&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectl-trace.tar.gz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;mv&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectl-trace &#x2F;usr&#x2F;local&#x2F;bin&#x2F;kubectl-trace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;OSX&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -L -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectl-trace.tar.gz https:&#x2F;&#x2F;github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;releases&#x2F;download&#x2F;v0.1.0-rc.1&#x2F;kubectl-trace_0.1.0-rc.1_darwin_amd64.tar.gz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;tar&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -xvf&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectl-trace.tar.gz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;mv&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectl-trace &#x2F;usr&#x2F;local&#x2F;bin&#x2F;kubectl-trace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Windows&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In PowerShell v5+&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;powershell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;$url&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;releases&#x2F;download&#x2F;v0.1.0-rc.1&#x2F;kubectl-trace_0.1.0-rc.1_windows_amd64.zip&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;$output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;$PSScriptRoot&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;\kubectl-trace.zip&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;Invoke-WebRequest&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -Uri &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;$url&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -OutFile &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;$output&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;Expand-Archive&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;$PSScriptRoot&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;\kubectl-trace.zip&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -DestinationPath &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;$PSScriptRoot&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;\kubectl-trace&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;source&quot;&gt;Source&lt;a class=&quot;zola-anchor&quot; href=&quot;#source&quot; aria-label=&quot;Anchor link for: source&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Using go modules, you can build kubectl-trace at any git tag:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;GO111MODULE=on go get github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;cmd&#x2F;kubectl-trace@latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will download and compile &lt;code&gt;kubectl-trace&lt;&#x2F;code&gt; so that you can use it as a kubectl plugin with &lt;code&gt;kubectl trace&lt;&#x2F;code&gt;, note that you will need to be on a recent version of go which supports go modules.&lt;&#x2F;p&gt;
&lt;p&gt;To keep track of the ref you used to build, you can add an ldflag at build time to set this to match the ref provided to go modules:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; GO111MODULE=on go get -ldflags=&amp;#39;-X github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;pkg&#x2F;version.gitCommit=v0.1.2&amp;#39; github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;cmd&#x2F;kubectl-trace@v0.1.2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; $GOHOME&#x2F;bin&#x2F;kubectl-trace version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git commit: v0.1.2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;build date: 2021-08-10 12:38:37.921341766 -0400 EDT m=+0.034327432&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; It is recommended you build tagged revisions only if you are looking for stability. Building branches such as &lt;code&gt;master&lt;&#x2F;code&gt; or the &lt;code&gt;latest&lt;&#x2F;code&gt; tag may result in a more unstable build which has received less QA than a tagged release.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;packages&quot;&gt;Packages&lt;a class=&quot;zola-anchor&quot; href=&quot;#packages&quot; aria-label=&quot;Anchor link for: packages&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;You can&#x27;t find the package for your distro of choice?
You are very welcome and encouraged to create it and then &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;issues&#x2F;new&quot;&gt;open an issue&lt;&#x2F;a&gt; to inform us for review.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;arch-aur&quot;&gt;Arch - AUR&lt;a class=&quot;zola-anchor&quot; href=&quot;#arch-aur&quot; aria-label=&quot;Anchor link for: arch-aur&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;The official &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aur.archlinux.org&#x2F;cgit&#x2F;aur.git&#x2F;tree&#x2F;PKGBUILD?h=kubectl-trace-git&quot;&gt;PKGBUILD&lt;&#x2F;a&gt; is on AUR.&lt;&#x2F;p&gt;
&lt;p&gt;If you use &lt;code&gt;yay&lt;&#x2F;code&gt; to manage AUR packages you can do:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;yay -S kubectl-trace-git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;a class=&quot;zola-anchor&quot; href=&quot;#architecture&quot; aria-label=&quot;Anchor link for: architecture&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;See &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;tree&#x2F;master&#x2F;docs&#x2F;architecture.md&quot;&gt;architecture.md&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;a class=&quot;zola-anchor&quot; href=&quot;#usage&quot; aria-label=&quot;Anchor link for: usage&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;You don&#x27;t need to setup anything on your cluster before using it, please don&#x27;t use it already
on a production system, just because this isn&#x27;t yet 100% ready.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;run-a-program-from-string-literal&quot;&gt;Run a program from string literal&lt;a class=&quot;zola-anchor&quot; href=&quot;#run-a-program-from-string-literal&quot; aria-label=&quot;Anchor link for: run-a-program-from-string-literal&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;In this  case we are running a program that probes a tracepoint
on the node &lt;code&gt;ip-180-12-0-152.ec2.internal&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kubectl trace run ip-180-12-0-152.ec2.internal -e &amp;quot;tracepoint:syscalls:sys_enter_* { @[probe] = count(); }&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;run-a-program-from-file&quot;&gt;Run a program from file&lt;a class=&quot;zola-anchor&quot; href=&quot;#run-a-program-from-file&quot; aria-label=&quot;Anchor link for: run-a-program-from-file&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Here we run a program named &lt;code&gt;read.bt&lt;&#x2F;code&gt; against the node &lt;code&gt;ip-180-12-0-152.ec2.internal&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kubectl trace run ip-180-12-0-152.ec2.internal -f read.bt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;run-a-program-against-a-pod&quot;&gt;Run a program against a Pod&lt;a class=&quot;zola-anchor&quot; href=&quot;#run-a-program-against-a-pod&quot; aria-label=&quot;Anchor link for: run-a-program-against-a-pod&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;master&#x2F;docs&#x2F;img&#x2F;pod.png&quot; alt=&quot;Screenshot showing the read.bt program for kubectl-trace&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That pod has a Go program in it that is at &lt;code&gt;&#x2F;caturday&lt;&#x2F;code&gt;, that program has a function called &lt;code&gt;main.counterValue&lt;&#x2F;code&gt; in it that returns an integer
every time it is called.&lt;&#x2F;p&gt;
&lt;p&gt;The purpose of this program is to load an &lt;code&gt;uretprobe&lt;&#x2F;code&gt; on the &lt;code&gt;&#x2F;caturday&lt;&#x2F;code&gt; binary so that every time the &lt;code&gt;main.counterValue&lt;&#x2F;code&gt; function is called
we get the return value out.&lt;&#x2F;p&gt;
&lt;p&gt;Since &lt;code&gt;kubectl trace&lt;&#x2F;code&gt; for pods is just an helper to resolve the context of a container&#x27;s Pod, you will always be in the root namespaces
but in this case you will have a variable &lt;code&gt;$container_pid&lt;&#x2F;code&gt; containing the pid of the root process in that container on the root pid namespace.&lt;&#x2F;p&gt;
&lt;p&gt;What you do then is that you get the &lt;code&gt;&#x2F;caturday&lt;&#x2F;code&gt; binary via &lt;code&gt;&#x2F;proc&#x2F;$container_pid&#x2F;exe&lt;&#x2F;code&gt;, like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kubectl trace run -e &amp;#39;uretprobe:&#x2F;proc&#x2F;$container_pid&#x2F;exe:&amp;quot;main.counterValue&amp;quot; { printf(&amp;quot;%d\n&amp;quot;, retval) }&amp;#39; pod&#x2F;caturday-566d99889-8glv9 -a -n caturday&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;running-against-a-pod-vs-against-a-node&quot;&gt;Running against a Pod vs against a Node&lt;a class=&quot;zola-anchor&quot; href=&quot;#running-against-a-pod-vs-against-a-node&quot; aria-label=&quot;Anchor link for: running-against-a-pod-vs-against-a-node&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;In general, you run kprobes&#x2F;kretprobes, tracepoints, software, hardware and profile events against nodes using the &lt;code&gt;node&#x2F;node-name&lt;&#x2F;code&gt; syntax or just use the
node name, node is the default.&lt;&#x2F;p&gt;
&lt;p&gt;When you want to actually probe an userspace program with an uprobe&#x2F;uretprobe or use an user-level static tracepoint (usdt) your best
bet is to run it against a pod using the &lt;code&gt;pod&#x2F;pod-name&lt;&#x2F;code&gt; syntax.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s always important to remember that running a program against a pod, as of now, is just a facilitator to find the process id for the binary you want to probe
on the root process namespace.&lt;&#x2F;p&gt;
&lt;p&gt;You could do the same thing when running in a Node by knowing the pid of your process yourself after entering in the node via another medium, e.g: ssh.&lt;&#x2F;p&gt;
&lt;p&gt;So, running against a pod &lt;strong&gt;doesn&#x27;t mean&lt;&#x2F;strong&gt; that your bpftrace program will be contained in that pod but just that it will pass to your program some
knowledge of the context of a container, in this case only the root process id is supported via the &lt;code&gt;$container_pid&lt;&#x2F;code&gt; variable.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;using-a-custom-service-account&quot;&gt;Using a custom service account&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-a-custom-service-account&quot; aria-label=&quot;Anchor link for: using-a-custom-service-account&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;By default &lt;code&gt;kubectl trace&lt;&#x2F;code&gt; will use the &lt;code&gt;default&lt;&#x2F;code&gt; service account in the target namespace (that is also &lt;code&gt;default&lt;&#x2F;code&gt;), to schedule the pods needed for your bpftrace program.&lt;&#x2F;p&gt;
&lt;p&gt;If you need to pass a service account you can use the &lt;code&gt;--serviceaccount&lt;&#x2F;code&gt; flag.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kubectl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; trace run&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --serviceaccount=kubectltrace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ip-180-12-0-152.ec2.internal&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; read.bt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;executing-in-a-cluster-using-pod-security-policies&quot;&gt;Executing in a cluster using Pod Security Policies&lt;a class=&quot;zola-anchor&quot; href=&quot;#executing-in-a-cluster-using-pod-security-policies&quot; aria-label=&quot;Anchor link for: executing-in-a-cluster-using-pod-security-policies&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;If your cluster has pod security policies you will need to make so that &lt;code&gt;kubectl trace&lt;&#x2F;code&gt; can
use a service account that can run privileged containers.&lt;&#x2F;p&gt;
&lt;p&gt;That service account, then will need to be in a group that uses the proper privileged &lt;code&gt;PodSecurityPolicy&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;First, create the service account that you will use with &lt;code&gt;kubectl trace&lt;&#x2F;code&gt;,
you can use a different namespace other than &lt;code&gt;default&lt;&#x2F;code&gt;, just remember to pass that namespace to the &lt;code&gt;run&lt;&#x2F;code&gt; command when you will use &lt;code&gt;kubectl trace&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ServiceAccount&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectltrace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  namespace&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now that we have a &lt;code&gt;kubectltrace&lt;&#x2F;code&gt; service account let&#x27;s create a Pod Security Policy:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; policy&#x2F;v1beta1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; PodSecurityPolicy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectltrace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  fsGroup&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    rule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; RunAsAny&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  privileged&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  runAsUser&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    rule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; RunAsAny&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  seLinux&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    rule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; RunAsAny&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  supplementalGroups&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    rule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; RunAsAny&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  volumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  allowedCapabilities&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  hostPID&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  hostIPC&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  hostNetwork&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  hostPorts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; min&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    max&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 65536&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, this &lt;code&gt;PodSecurityPolicy&lt;&#x2F;code&gt; will allow users assigned to it to run privileged containers,
&lt;code&gt;kubectl trace&lt;&#x2F;code&gt; needs that because of the extended privileges eBPF programs need to run with
to trace your kernel and programs running in it.&lt;&#x2F;p&gt;
&lt;p&gt;Now with a &lt;code&gt;ClusterRoleBinding&lt;&#x2F;code&gt; you bind the &lt;code&gt;ClusterRole&lt;&#x2F;code&gt; with the &lt;code&gt;ServiceAccount&lt;&#x2F;code&gt;, so that
they can work together with the &lt;code&gt;PodSecurityPolicy&lt;&#x2F;code&gt; we just created.&lt;&#x2F;p&gt;
&lt;p&gt;You can change the &lt;code&gt;namespace: default&lt;&#x2F;code&gt; here if you created the service account in a namespace other than &lt;code&gt;default&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rbac.authorization.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ClusterRole&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectltrace-psp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; apiGroups&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; policy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  resources&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; podsecuritypolicies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  resourceNames&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectltrace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  verbs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; use&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rbac.authorization.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ClusterRoleBinding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectltrace-psp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;subjects&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; kind&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ServiceAccount&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectltrace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  namespace&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;roleRef&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;   apiGroup&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rbac.authorization.k8s.io&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;   kind&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ClusterRole&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;   name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kubectltrace-psp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;OK! Now that we are all set we can just run the program by specifying the service account
we just created and it will use our pod security policy!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kubectl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; trace run&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --serviceaccount=kubectltrace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ip-180-12-0-152.ec2.internal&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; read.bt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you used a different namespace other than default for your service account, you will want to specify the namespace too, like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kubectl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; trace run&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --namespace=mynamespace --serviceaccount=kubectltrace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ip-180-12-0-152.ec2.internal&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; read.bt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;using-a-patch-to-customize-the-trace-job&quot;&gt;Using a patch to customize the trace job&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-a-patch-to-customize-the-trace-job&quot; aria-label=&quot;Anchor link for: using-a-patch-to-customize-the-trace-job&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;There may be times when you need to customize the job descriptor that kubectl-trace generates. You can provide a patch file that will modify any of the job&#x27;s attributes before it executes on the cluster.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;--patch&lt;&#x2F;code&gt; and &lt;code&gt;--patch-type&lt;&#x2F;code&gt; arguments to the &lt;code&gt;run&lt;&#x2F;code&gt; command specify your patch file&#x27;s location and merge strategy:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--patch&lt;&#x2F;code&gt; - sets the path to a YAML or JSON file containing your patch.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--patch-type&lt;&#x2F;code&gt; - sets the strategy that will be used to modify the job descriptor.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Patch strategies&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The supported patch strategies are the same as those used by Kubernetes to support &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;v1-17.docs.kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;run-application&#x2F;update-api-object-kubectl-patch&#x2F;#use-a-json-merge-patch-to-update-a-deployment&quot;&gt;in-place API object updates&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;These 3 patch strategies are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;json&lt;&#x2F;code&gt; - Sets the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;jsonpatch.com&#x2F;&quot;&gt;JSON patch&lt;&#x2F;a&gt; strategy (see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6902&quot;&gt;RFC 6209&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;merge&lt;&#x2F;code&gt; - Sets the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc7396&quot;&gt;JSON merge patch&lt;&#x2F;a&gt; strategy.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;strategic&lt;&#x2F;code&gt; - JSON strategic merge patch is like the &quot;JSON merge patch&quot; but with different array handling (see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;v1-17.docs.kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;run-application&#x2F;update-api-object-kubectl-patch&#x2F;#use-a-json-merge-patch-to-update-a-deployment&quot;&gt;Kubernetes strategic merge&lt;&#x2F;a&gt; for more).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; You can create your patch files in either YAML or JSON format. The format is independent of the strategy used, e.g. the strategy &lt;code&gt;json&lt;&#x2F;code&gt; refers to the &quot;JSON patch&quot; strategy, not the format of the patch file.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Example: customizing resource limits&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A cluster administrator may have set strict resource limits that conflict with the defaults used by &lt;code&gt;kubectl-trace&lt;&#x2F;code&gt;, preventing your job from executing. With a patch you can adjust a job&#x27;s resource limits to match your cluster&#x27;s config.&lt;&#x2F;p&gt;
&lt;p&gt;Below is an example of a YAML patch which uses the &lt;code&gt;json&lt;&#x2F;code&gt; strategy (&quot;JSON patch&quot;). This strategy consists of a list of operations (add, replace, remove), a path which references a location in the document, and an optional value (to add or replace).&lt;&#x2F;p&gt;
&lt;p&gt;The patch below replaces the first container&#x27;s resources section, in order to increase both the request and limit values for cpu and memory:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# mypatch.yaml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  path&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;spec&#x2F;template&#x2F;spec&#x2F;containers&#x2F;0&#x2F;resources&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    limits&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      cpu&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      memory&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 500Mi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    requests&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      cpu&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      memory&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 500Mi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now run the job using our patch:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kubectl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; trace run ip-180-12-0-152.ec2.internal&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; read.bt&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --patch&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mypatch.yaml&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --patch-type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Example: setting an environment variable&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The following JSON format patch adds a &lt;code&gt;BPFTRACE_STRLEN&lt;&#x2F;code&gt; environment variable to the first container. The variable increases &lt;code&gt;bpftrace&lt;&#x2F;code&gt;&#x27;s string length limit from 64 to 128:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    &amp;quot;op&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;add&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    &amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&#x2F;spec&#x2F;template&#x2F;spec&#x2F;containers&#x2F;0&#x2F;env&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    &amp;quot;value&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [{&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt; &amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;BPFTRACE_STRLEN&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt; &amp;quot;value&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;128&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;kubectl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; trace run ip-180-12-0-152.ec2.internal&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; read.bt&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --patch&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mypatch.json&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --patch-type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;more-bpftrace-programs&quot;&gt;More bpftrace programs&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-bpftrace-programs&quot; aria-label=&quot;Anchor link for: more-bpftrace-programs&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Need more programs? Look &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iovisor&#x2F;bpftrace&#x2F;tree&#x2F;master&#x2F;tools&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;contributing&quot;&gt;Contributing&lt;a class=&quot;zola-anchor&quot; href=&quot;#contributing&quot; aria-label=&quot;Anchor link for: contributing&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Already pumped up to commit some code? Here are some resources to join the
discussions in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.iovisor.org&#x2F;&quot;&gt;IOVisor&lt;&#x2F;a&gt; community and see
what you want to work on.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Mailing List:&lt;&#x2F;em&gt; http:&#x2F;&#x2F;lists.iovisor.org&#x2F;mailman&#x2F;listinfo&#x2F;iovisor-dev&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;IRC:&lt;&#x2F;em&gt; #iovisor at irc.oftc.net&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Slack&lt;&#x2F;em&gt; #kubectl-trace in the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;kubernetes.slack.com&#x2F;&quot;&gt;Kubernetes Slack&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Kubectl Trace Issue Tracker:&lt;&#x2F;em&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iovisor&#x2F;kubectl-trace&#x2F;issues&quot;&gt;Github Issues&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Special thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RamonGilabert&quot;&gt;Ramon Gilabert&lt;&#x2F;a&gt; for the logo.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>go-syslog</title>
        <published>2018-03-28T00:00:00+00:00</published>
        <updated>2018-03-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://leodido.dev/projects/go-syslog/"/>
        <id>https://leodido.dev/projects/go-syslog/</id>
        
        <content type="html" xml:base="https://leodido.dev/projects/go-syslog/">&lt;p&gt;&lt;em&gt;This is the official continuation of influxdata&#x2F;go-syslog&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To wrap up, this package provides:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;rfc5424&quot;&gt;RFC5424-compliant parser and builder&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;rfc3164&quot;&gt;RFC3164-compliant parser&lt;&#x2F;a&gt; - ie., BSD-syslog messages&lt;&#x2F;li&gt;
&lt;li&gt;an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;auto&quot;&gt;auto-detect parser&lt;&#x2F;a&gt; that determines RFC 3164 vs RFC 5424 format per-message&lt;&#x2F;li&gt;
&lt;li&gt;an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;rfc3195&quot;&gt;RFC3195 parser&lt;&#x2F;a&gt; for syslog over &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc3195&quot;&gt;BEEP&lt;&#x2F;a&gt; (RAW and COOKED profiles)&lt;&#x2F;li&gt;
&lt;li&gt;a parser that works on streams for syslog with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc6587#section-3.4.1&quot;&gt;octet counting&lt;&#x2F;a&gt; framing technique, see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;octetcounting&quot;&gt;octetcounting&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;a parser that works on streams for syslog with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6587#section-3.4.2&quot;&gt;non-transparent&lt;&#x2F;a&gt; framing technique, see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;nontransparent&quot;&gt;nontransparent&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This library provides the pieces to parse Syslog messages transported following various RFCs.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;TLS with octet count (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc5425&quot;&gt;RFC5425&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;TCP with non-transparent framing or with octet count (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6587&quot;&gt;RFC 6587&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;UDP carrying one message per packet (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc5426&quot;&gt;RFC5426&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;a class=&quot;zola-anchor&quot; href=&quot;#installation&quot; aria-label=&quot;Anchor link for: installation&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Requires &lt;strong&gt;Go 1.22&lt;&#x2F;strong&gt; or later.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go get github.com&#x2F;leodido&#x2F;go-syslog&#x2F;v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;docs&quot;&gt;Docs&lt;a class=&quot;zola-anchor&quot; href=&quot;#docs&quot; aria-label=&quot;Anchor link for: docs&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;docs&#x2F;&quot;&gt;docs&lt;&#x2F;a&gt; directory contains &lt;code&gt;.dot&lt;&#x2F;code&gt; files representing the finite-state machines (FSMs) implementing the syslog parsers and transports.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;a class=&quot;zola-anchor&quot; href=&quot;#usage&quot; aria-label=&quot;Anchor link for: usage&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Suppose you want to parse a given sequence of bytes as a RFC5424 message.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Notice that the same interface applies for RFC3164. But you can always take a look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;rfc3164&#x2F;example_test.go&quot;&gt;examples file&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&amp;lt;165&amp;gt;4 2018-10-11T22:14:15.003Z mymach.it e - 1 [ex@32473 iut=&amp;quot;3&amp;quot;] An application event log entry...`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rfc5424&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewParser&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This results in &lt;code&gt;m&lt;&#x2F;code&gt; being equal to:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; (*rfc5424.SyslogMessage)({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  Base: (syslog.Base) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Facility: (*uint8)(20),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Severity: (*uint8)(5),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Priority: (*uint8)(165),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Timestamp: (*time.Time)(2018-10-11 22:14:15.003 +0000 UTC),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Hostname: (*string)((len=9) &amp;quot;mymach.it&amp;quot;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Appname: (*string)((len=1) &amp;quot;e&amp;quot;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   ProcID: (*string)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   MsgID: (*string)((len=1) &amp;quot;1&amp;quot;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Message: (*string)((len=33) &amp;quot;An application event log entry...&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  Version: (uint16) 4,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  StructuredData: (*map[string]map[string]string)((len=1) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   (string) (len=8) &amp;quot;ex@32473&amp;quot;: (map[string]string) (len=1) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;    (string) (len=3) &amp;quot;iut&amp;quot;: (string) (len=1) &amp;quot;3&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And &lt;code&gt;e&lt;&#x2F;code&gt; being equal to &lt;code&gt;nil&lt;&#x2F;code&gt; since the &lt;code&gt;i&lt;&#x2F;code&gt; byte slice contains a perfectly valid RFC5424 message.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;best-effort-mode&quot;&gt;Best effort mode&lt;a class=&quot;zola-anchor&quot; href=&quot;#best-effort-mode&quot; aria-label=&quot;Anchor link for: best-effort-mode&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;RFC5424 parser has the ability to perform partial matches (until it can).&lt;&#x2F;p&gt;
&lt;p&gt;With this mode enabled, when the parsing process errors out it returns the message collected until that position, and the error that caused the parser to stop.&lt;&#x2F;p&gt;
&lt;p&gt;Notice that in this modality the output is returned &lt;em&gt;iff&lt;&#x2F;em&gt; it represents a minimally valid message - ie., a message containing almost a priority field in &lt;code&gt;[1,191]&lt;&#x2F;code&gt; within angular brackets, followed by a version in &lt;code&gt;]0,999]&lt;&#x2F;code&gt; (in the case of RFC5424).&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s look at an example.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := []&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&amp;lt;1&amp;gt;1 A - - - - - -&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rfc5424&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewParser&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rfc5424&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithBestEffort&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This results in &lt;code&gt;m&lt;&#x2F;code&gt; being equal to the following &lt;code&gt;SyslogMessage&lt;&#x2F;code&gt; instance.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; (*rfc5424.SyslogMessage)({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  Base: (syslog.Base) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Facility: (*uint8)(0),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Severity: (*uint8)(1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Priority: (*uint8)(1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Timestamp: (*time.Time)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Hostname: (*string)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Appname: (*string)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   ProcID: (*string)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   MsgID: (*string)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Message: (*string)(&amp;lt;nil&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  Version: (uint16) 1,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  StructuredData: (*map[string]map[string]string)(&amp;lt;nil&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And, at the same time, in &lt;code&gt;e&lt;&#x2F;code&gt; reporting the error that actually stopped the parser.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; expecting a RFC3339MICRO timestamp or a nil value [col 5]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both &lt;code&gt;m&lt;&#x2F;code&gt; and &lt;code&gt;e&lt;&#x2F;code&gt; have a value since at the column the parser stopped it already was able to construct a minimally valid RFC5424 &lt;code&gt;SyslogMessage&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;builder&quot;&gt;Builder&lt;a class=&quot;zola-anchor&quot; href=&quot;#builder&quot; aria-label=&quot;Anchor link for: builder&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;This library also provides a builder to construct valid syslog messages.&lt;&#x2F;p&gt;
&lt;p&gt;Notice that its API ignores input values that does not match the grammar.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s have a look to an example.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; := &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;rfc5424&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;SyslogMessage&lt;&#x2F;span&gt;&lt;span&gt;{}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;SetTimestamp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;not a RFC3339MICRO timestamp&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Valid&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; Not yet a valid message (try msg.Valid())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;SetPriority&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;191&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;SetVersion&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Valid&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; Now it is minimally valid&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Printing &lt;code&gt;msg&lt;&#x2F;code&gt; you will verify it contains a &lt;code&gt;nil&lt;&#x2F;code&gt; timestamp (since an invalid one has been given).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; (*rfc5424.SyslogMessage)({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  Base: (syslog.Base) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Facility: (*uint8)(23),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Severity: (*uint8)(7),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Priority: (*uint8)(191),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Timestamp: (*time.Time)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Hostname: (*string)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Appname: (*string)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   ProcID: (*string)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   MsgID: (*string)(&amp;lt;nil&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;   Message: (*string)(&amp;lt;nil&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  Version: (uint16) 1,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F;  StructuredData: (*map[string]map[string]string)(&amp;lt;nil&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally you can serialize the message into a string.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; msg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; &amp;lt;191&amp;gt;1 - - - - - -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;auto-detect&quot;&gt;Auto-detect&lt;a class=&quot;zola-anchor&quot; href=&quot;#auto-detect&quot; aria-label=&quot;Anchor link for: auto-detect&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Suppose you don&#x27;t know whether incoming messages are RFC 5424 or RFC 3164. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;auto&quot;&gt;auto&lt;&#x2F;a&gt; package figures it out per-message.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; auto&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; m&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;DetectFormat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; &amp;quot;rfc5424&amp;quot; or &amp;quot;rfc3164&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can pass format-specific options to each inner parser:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; auto&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    auto&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithRFC3164Options&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rfc3164&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithYear&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;rfc3164&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Year&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;YYYY&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2025&lt;&#x2F;span&gt;&lt;span&gt;})),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    auto&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithRFC5424Options&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rfc5424&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithCompliantMsg&lt;&#x2F;span&gt;&lt;span&gt;()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It also works with the stream parsers via &lt;code&gt;NewParserAuto&lt;&#x2F;code&gt; - see &lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;go-syslog&#x2F;#octet-counting&quot;&gt;octet counting&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;go-syslog&#x2F;#non-transparent&quot;&gt;non-transparent&lt;&#x2F;a&gt; below.&lt;&#x2F;p&gt;
&lt;p&gt;Performance-wise, auto-detect peeks at a few bytes after the PRI to pick the format - no allocations, no copying. It&#x27;s as fast as calling the right parser yourself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;message-transfer&quot;&gt;Message transfer&lt;a class=&quot;zola-anchor&quot; href=&quot;#message-transfer&quot; aria-label=&quot;Anchor link for: message-transfer&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Excluding encapsulating one message for packet in packet protocols there are two ways to transfer syslog messages over streams.&lt;&#x2F;p&gt;
&lt;p&gt;The older - ie., the &lt;strong&gt;non-transparent&lt;&#x2F;strong&gt; framing - and the newer one - ie., the &lt;strong&gt;octet counting&lt;&#x2F;strong&gt; framing - which is reliable and has not been seen to cause problems noted with the non-transparent one.&lt;&#x2F;p&gt;
&lt;p&gt;This library provide stream parsers for both.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;octet-counting&quot;&gt;Octet counting&lt;a class=&quot;zola-anchor&quot; href=&quot;#octet-counting&quot; aria-label=&quot;Anchor link for: octet-counting&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;In short, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc5425#section-4.3&quot;&gt;RFC5425&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6587&quot;&gt;RFC6587&lt;&#x2F;a&gt;, aside from the protocol considerations, describe a &lt;strong&gt;transparent framing&lt;&#x2F;strong&gt; technique for Syslog messages that uses the &lt;strong&gt;octect counting&lt;&#x2F;strong&gt; technique - ie., the message length of the incoming message.&lt;&#x2F;p&gt;
&lt;p&gt;Each Syslog message is sent with a prefix representing the number of bytes it is made of.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;octetcounting&quot;&gt;octecounting package&lt;&#x2F;a&gt; parses messages stream following such rule.&lt;&#x2F;p&gt;
&lt;p&gt;To quickly understand how to use it please have a look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;octetcounting&#x2F;example_test.go&quot;&gt;example file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you have mixed RFC 5424 and RFC 3164 messages in the same stream, use &lt;code&gt;NewParserAuto&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; octetcounting&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewParserAuto&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    syslog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithListener&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;syslog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;DetectFormat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    syslog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithBestEffort&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;non-transparent&quot;&gt;Non transparent&lt;a class=&quot;zola-anchor&quot; href=&quot;#non-transparent&quot; aria-label=&quot;Anchor link for: non-transparent&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6587#section-3.4.2&quot;&gt;RFC6587&lt;&#x2F;a&gt; also describes the &lt;strong&gt;non-transparent framing&lt;&#x2F;strong&gt; transport of syslog messages.&lt;&#x2F;p&gt;
&lt;p&gt;In such case the messages are separated by a trailer, usually a line feed.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;nontransparent&quot;&gt;nontransparent package&lt;&#x2F;a&gt; parses message stream following such &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6587#section-3.4.2&quot;&gt;technique&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To quickly understand how to use it please have a look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;nontransparent&#x2F;example_test.go&quot;&gt;example file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Same as octet counting, use &lt;code&gt;NewParserAuto&lt;&#x2F;code&gt; for mixed-format streams:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; nontransparent&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewParserAuto&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    syslog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithListener&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;syslog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;DetectFormat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    syslog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithBestEffort&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Things we do not support:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;trailers other than &lt;code&gt;LF&lt;&#x2F;code&gt; or &lt;code&gt;NUL&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;trailers which length is greater than 1 byte&lt;&#x2F;li&gt;
&lt;li&gt;trailer change on a frame-by-frame basis&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;rfc-3195-beep&quot;&gt;RFC 3195 (BEEP)&lt;a class=&quot;zola-anchor&quot; href=&quot;#rfc-3195-beep&quot; aria-label=&quot;Anchor link for: rfc-3195-beep&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc3195&quot;&gt;RFC 3195&lt;&#x2F;a&gt; defines syslog transport over the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc3080&quot;&gt;BEEP&lt;&#x2F;a&gt; protocol. It specifies two profiles:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RAW&lt;&#x2F;strong&gt; (§4.2): syslog messages are carried as CRLF-terminated payloads in BEEP ANS frames. The inner messages can be either RFC 5424 or RFC 3164 format.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;COOKED&lt;&#x2F;strong&gt; (§4.3): syslog data is encoded as XML &lt;code&gt;&amp;lt;entry&amp;gt;&lt;&#x2F;code&gt; elements with attributes for facility, severity, timestamp, tag, and device identity.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;rfc3195&quot;&gt;rfc3195 package&lt;&#x2F;a&gt; provides parsers for both profiles. It implements BEEP frame scanning (MSG, RPY, ERR, ANS, NUL, SEQ frames) and extracts syslog messages from the frame payloads.&lt;&#x2F;p&gt;
&lt;p&gt;This is a parsing-only implementation - it does not handle BEEP session management, channel negotiation, or TLS. Feed it a stream of BEEP frames and it will emit parsed syslog messages.&lt;&#x2F;p&gt;
&lt;p&gt;To quickly understand how to use it please have a look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-syslog&#x2F;tree&#x2F;develop&#x2F;rfc3195&#x2F;example_test.go&quot;&gt;example file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performances&quot;&gt;Performances&lt;a class=&quot;zola-anchor&quot; href=&quot;#performances&quot; aria-label=&quot;Anchor link for: performances&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;To run the benchmark execute the following command.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;make&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bench&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On my machine&lt;sup&gt;&lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;go-syslog&#x2F;#mymachine&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; these are the results obtained paring RFC5424 syslog messages with best effort mode on.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_empty_input__________________________________-10  32072733   185.3 ns&#x2F;op   272 B&#x2F;op   4 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_multiple_syslog_messages_on_multiple_lines___-10  27058381   219.8 ns&#x2F;op   267 B&#x2F;op   7 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_impossible_timestamp_________________________-10   8732960   683.8 ns&#x2F;op   555 B&#x2F;op  12 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_malformed_structured_data____________________-10  17997814   335.6 ns&#x2F;op   499 B&#x2F;op   8 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[no]_with_duplicated_structured_data_id___________-10   9254920   645.7 ns&#x2F;op   672 B&#x2F;op  15 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal______________________________________-10  48347473   123.2 ns&#x2F;op   227 B&#x2F;op   5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_average_message______________________________-10   6058492   986.8 ns&#x2F;op  1344 B&#x2F;op  20 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_complicated_message__________________________-10   7052536   843.2 ns&#x2F;op  1232 B&#x2F;op  23 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_very_long_message____________________________-10   2644068  2279.0 ns&#x2F;op  2272 B&#x2F;op  21 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_all_max_length_and_complete__________________-10   3611186  1675.0 ns&#x2F;op  1848 B&#x2F;op  27 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_all_max_length_except_structured_data_and_mes-10   5729514  1059.0 ns&#x2F;op   851 B&#x2F;op  12 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal_with_message_containing_newline______-10  43165338   142.9 ns&#x2F;op   230 B&#x2F;op   6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_w&#x2F;o_procid,_w&#x2F;o_structured_data,_with_message-10  14832892   397.8 ns&#x2F;op   308 B&#x2F;op   9 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal_with_UTF-8_message___________________-10  20229313   306.2 ns&#x2F;op   339 B&#x2F;op   6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_minimal_with_UTF-8_message_starting_with_BOM_-10  19721539   306.7 ns&#x2F;op   355 B&#x2F;op   6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_with_structured_data_id,_w&#x2F;o_structured_data_-10  13860580   435.7 ns&#x2F;op   538 B&#x2F;op  10 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_with_multiple_structured_data________________-10   8368731   721.9 ns&#x2F;op  1173 B&#x2F;op  15 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_with_escaped_backslash_within_structured_data-10   9730569   632.6 ns&#x2F;op   864 B&#x2F;op  16 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ok]_with_UTF-8_structured_data_param_value,_with_-10   8864156   660.6 ns&#x2F;op   858 B&#x2F;op  15 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see it takes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;~125ns to parse the smallest legal message&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;less than 1µs to parse an average legal message&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;~2µs to parse a very long legal message&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Other RFC5424 implementations, like this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;roguelazer&#x2F;rust-syslog-rfc5424&quot;&gt;one&lt;&#x2F;a&gt; in Rust, spend 8µs to parse an average legal message.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a name=&quot;mymachine&quot;&gt;[1]&lt;&#x2F;a&gt;: Apple M1 Pro&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>go-urn</title>
        <published>2017-11-21T00:00:00+00:00</published>
        <updated>2017-11-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://leodido.dev/projects/go-urn/"/>
        <id>https://leodido.dev/projects/go-urn/</id>
        
        <content type="html" xml:base="https://leodido.dev/projects/go-urn/">&lt;p&gt;Starting with version 1.3 this library also supports &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc7643#section-10&quot;&gt;RFC 7643 SCIM URNs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Starting with version 1.4 this library also supports &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc8141&quot;&gt;RFC 8141 URNs (2017)&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;a class=&quot;zola-anchor&quot; href=&quot;#installation&quot; aria-label=&quot;Anchor link for: installation&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go get github.com&#x2F;leodido&#x2F;go-urn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;features&quot;&gt;Features&lt;a class=&quot;zola-anchor&quot; href=&quot;#features&quot; aria-label=&quot;Anchor link for: features&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;RFC 2141 URNs parsing (default)&lt;&#x2F;li&gt;
&lt;li&gt;RFC 8141 URNs parsing (supersedes RFC 2141)&lt;&#x2F;li&gt;
&lt;li&gt;RFC 7643 SCIM URNs parsing&lt;&#x2F;li&gt;
&lt;li&gt;Normalization as per RFCs&lt;&#x2F;li&gt;
&lt;li&gt;Lexical equivalence as per RFCs&lt;&#x2F;li&gt;
&lt;li&gt;Precise, fine-grained errors&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;performances&quot;&gt;Performances&lt;a class=&quot;zola-anchor&quot; href=&quot;#performances&quot; aria-label=&quot;Anchor link for: performances&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This implementation results to be really fast.&lt;&#x2F;p&gt;
&lt;p&gt;Usually below 400 ns on my machine&lt;sup&gt;&lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;go-urn&#x2F;#mymachine&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Notice it also performs, while parsing:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;fine-grained and informative erroring&lt;&#x2F;li&gt;
&lt;li&gt;specific-string normalization&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;00&#x2F;urn:a:b______________________________________&#x2F;-10    51372006    109.0 ns&#x2F;op    275 B&#x2F;op    3 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;01&#x2F;URN:foo:a123,456_____________________________&#x2F;-10    36024072    160.8 ns&#x2F;op    296 B&#x2F;op    6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;02&#x2F;urn:foo:a123%2C456___________________________&#x2F;-10    31901007    188.4 ns&#x2F;op    320 B&#x2F;op    7 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;03&#x2F;urn:ietf:params:scim:schemas:core:2.0:User___&#x2F;-10    22736756    266.6 ns&#x2F;op    376 B&#x2F;op    6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;04&#x2F;urn:ietf:params:scim:schemas:extension:enterp&#x2F;-10    18291859    335.2 ns&#x2F;op    408 B&#x2F;op    6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;05&#x2F;urn:ietf:params:scim:schemas:extension:enterp&#x2F;-10    15283087    379.4 ns&#x2F;op    440 B&#x2F;op    6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;06&#x2F;urn:burnout:nss______________________________&#x2F;-10    39407593    155.1 ns&#x2F;op    288 B&#x2F;op    6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;07&#x2F;urn:abcdefghilmnopqrstuvzabcdefghilm:x_______&#x2F;-10    27832718    211.4 ns&#x2F;op    307 B&#x2F;op    4 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;08&#x2F;urn:urnurnurn:urn____________________________&#x2F;-10    33269596    168.1 ns&#x2F;op    293 B&#x2F;op    6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;09&#x2F;urn:ciao:!!*_________________________________&#x2F;-10    41100675    148.8 ns&#x2F;op    288 B&#x2F;op    6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;10&#x2F;urn:ciao:=@__________________________________&#x2F;-10    37214253    149.7 ns&#x2F;op    284 B&#x2F;op    6 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;11&#x2F;urn:ciao:@!=%2C(xyz)+a,b.*@g=$_&amp;#39;_____________&#x2F;-10    26534240    229.8 ns&#x2F;op    336 B&#x2F;op    7 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ok&#x2F;12&#x2F;URN:x:abc%1Dz%2F%3az_________________________&#x2F;-10    28166396    211.8 ns&#x2F;op    336 B&#x2F;op    7 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;no&#x2F;13&#x2F;URN:---xxx:x_________________________________&#x2F;-10    23635159    255.6 ns&#x2F;op    419 B&#x2F;op    5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;no&#x2F;14&#x2F;urn::colon:nss_______________________________&#x2F;-10    23594779    258.4 ns&#x2F;op    419 B&#x2F;op    5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;no&#x2F;15&#x2F;URN:@,:x_____________________________________&#x2F;-10    23742535    261.5 ns&#x2F;op    419 B&#x2F;op    5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;no&#x2F;16&#x2F;URN:URN:NSS__________________________________&#x2F;-10    27432714    223.3 ns&#x2F;op    371 B&#x2F;op    5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;no&#x2F;17&#x2F;urn:UrN:NSS__________________________________&#x2F;-10    26922117    224.9 ns&#x2F;op    371 B&#x2F;op    5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;no&#x2F;18&#x2F;urn:a:%______________________________________&#x2F;-10    24926733    224.6 ns&#x2F;op    371 B&#x2F;op    5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;no&#x2F;19&#x2F;urn:urn:NSS__________________________________&#x2F;-10    27652641    220.7 ns&#x2F;op    371 B&#x2F;op    5 allocs&#x2F;op&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a name=&quot;mymachine&quot;&gt;[1]&lt;&#x2F;a&gt;: Apple M1 Pro&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;a class=&quot;zola-anchor&quot; href=&quot;#example&quot; aria-label=&quot;Anchor link for: example&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;For more examples take a look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leodido&#x2F;go-urn&#x2F;tree&#x2F;master&#x2F;examples_test.go&quot;&gt;examples file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;fmt&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;github.com&#x2F;leodido&#x2F;go-urn&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; uid&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;URN:foo:a123,456&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F; Parse the input string as a RFC 2141 URN only&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	u&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; urn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewMachine&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Errorf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;		return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;u&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ID&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;u&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;SS&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Output:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; foo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; a123,456&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;fmt&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;github.com&#x2F;leodido&#x2F;go-urn&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; uid&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;URN:foo:a123,456&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F; Parse the input string as a RFC 2141 URN only&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	u&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; urn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;([]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;		panic&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;error parsing urn&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;u&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ID&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;u&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;SS&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Output:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; foo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; a123,456&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;fmt&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;github.com&#x2F;leodido&#x2F;go-urn&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;urn:ietf:params:scim:api:messages:2.0:ListResponse&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Parsing the input string as a RFC 7643 SCIM URN&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	u&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; urn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Parse&lt;&#x2F;span&gt;&lt;span&gt;([]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-byte z-go&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; urn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;WithParsingMode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;urn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;RFC7643Only&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;		panic&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;error parsing urn&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;u&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;IsSCIM&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	scim&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; u&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;SCIM&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;scim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;scim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;scim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Other&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; Output:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; api&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; messages&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;	&#x2F;&#x2F; 2.0:ListResponse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
</feed>
