diff --git a/README.md b/README.md index 628bd48..619b0c1 100644 --- a/README.md +++ b/README.md @@ -232,8 +232,8 @@ func main() { }, } - // Add the hidden __opencli command - ourfave.FromCommand(command, ourfave.WithOutput(os.Stdout)) + // Add the hidden __opencli command, plus a visible `docgen` alias + ourfave.FromCommand(command, ourfave.WithPublicCommand("docgen")) app := command.App() app.Run(context.Background(), preprocessArgs(os.Args)) @@ -252,6 +252,18 @@ pleasantries __opencli # ... ``` +`__opencli` is always attached and hidden, so it works as a stable machine-facing +contract. `WithPublicCommand` adds a visible command with the same behaviour so +users (and AI agents reading `--help`) can discover it. Both accept `--format yaml|json` +and `-o/--out `. + +The `ocli` CLI accepts a binary in place of a spec file and tries `__opencli` +first, then `docgen`, so it works with CLIs that expose either command: + +```sh +ocli check ./pleasantries +ocli gen docs --format markdown --out ./docs ./pleasantries +``` ## Ecosystem Community projects built on the OpenCLI Specification: diff --git a/adapters/ocobra/ocobra.go b/adapters/ocobra/ocobra.go index c05aca4..2dbda8b 100644 --- a/adapters/ocobra/ocobra.go +++ b/adapters/ocobra/ocobra.go @@ -1,7 +1,8 @@ // Package ocobra provides the ability to create OpenCLI documents from existing Cobra CLIs. // -// It attaches a hidden subcommand to an existing Cobra root command that, when -// invoked, walks the entire command tree and emits a valid OpenCLI spec document. +// It attaches a hidden "__opencli" subcommand (and optionally a visible one via +// WithPublicCommand) to an existing Cobra root command that, when invoked, +// walks the entire command tree and emits a valid OpenCLI spec document. // // Typical usage: // @@ -30,6 +31,7 @@ type config struct { globalFlags []spec.FlagItem output io.Writer format codec.Format + publicName string } func (c *config) getInfo() spec.Info { @@ -64,25 +66,47 @@ func WithFormat(f codec.Format) Option { return func(c *config) { c.format = f } } +// WithPublicCommand additionally attaches a visible subcommand with the given +// name (e.g. "docgen") that behaves exactly like the hidden "__opencli" command. +// A visible command advertises in help output that the CLI can describe itself. +func WithPublicCommand(name string) Option { + return func(c *config) { c.publicName = name } +} + // WithOutput sets the io.Writer for the generated spec. // Defaults to os.Stdout if omitted. func WithOutput(w io.Writer) Option { return func(c *config) { c.output = w } } -// FromCommand attaches a hidden "__opencli" subcommand to rootCmd. -// Running that subcommand walks the Cobra command tree and writes an OpenCLI -// spec document to the configured output (default: stdout). +// generatorAnnotation marks subcommands attached by FromCommand so the tree walk +// can skip them. +const generatorAnnotation = "opencli.generator" + +// FromCommand attaches a hidden "__opencli" subcommand to rootCmd, plus a visible +// one when WithPublicCommand is used. Running either subcommand walks the Cobra +// command tree and writes an OpenCLI spec document to the configured output +// (default: stdout). func FromCommand(rootCmd *cobra.Command, opts ...Option) { c := defaultConfigWithOptions(opts...) - var flagOut string + + rootCmd.AddCommand(newGenCmd(rootCmd, c, "__opencli", true)) + if c.publicName != "" { + rootCmd.AddCommand(newGenCmd(rootCmd, c, c.publicName, false)) + } +} + +func newGenCmd(rootCmd *cobra.Command, c *config, name string, hidden bool) *cobra.Command { + var flagOut, flagFormat string genCmd := &cobra.Command{ - Use: "__opencli", - Short: "Generates OpenCLI specification", - Hidden: true, - Args: cobra.NoArgs, + Use: name, + Short: "Generate the OpenCLI specification for this CLI", + Hidden: hidden, + Annotations: map[string]string{generatorAnnotation: "true"}, + Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { + out := c.output if flagOut != "" { // The user has passed a file to output to f, err := os.OpenFile(flagOut, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) @@ -90,17 +114,21 @@ func FromCommand(rootCmd *cobra.Command, opts ...Option) { return fmt.Errorf("unable to write opencli doc to specified file: %w", err) } defer f.Close() - - c.output = f + out = f + } + format := c.format + if flagFormat != "" { + format = codec.Format(flagFormat) } doc := documentFromCommand(rootCmd, c) - return writeDoc(c.output, doc, c.format) + return writeDoc(out, doc, format) }, } - genCmd.Flags().StringVarP(&flagOut, "out", "o", "", "The path to the directory where the generated code will be output") + genCmd.Flags().StringVarP(&flagOut, "out", "o", "", "The path to the file where the generated spec will be written (default: stdout)") + genCmd.Flags().StringVar(&flagFormat, "format", "", "The output format: yaml or json") - rootCmd.AddCommand(genCmd) + return genCmd } // GenerateDocument walks a Cobra command tree and returns the corresponding @@ -222,8 +250,8 @@ func commandFromCobra(cmd *cobra.Command, parent *spec.CommandItem) *spec.Comman // Recurse into children for _, child := range cmd.Commands() { - if child.Use == "__opencli" { - continue // skip our own genator command + if child.Annotations[generatorAnnotation] != "" { + continue // skip our own generator commands } childItem := commandFromCobra(child, item) item.Commands = append(item.Commands, childItem) diff --git a/adapters/ocobra/ocobra_test.go b/adapters/ocobra/ocobra_test.go index acd4e15..946e797 100644 --- a/adapters/ocobra/ocobra_test.go +++ b/adapters/ocobra/ocobra_test.go @@ -390,3 +390,34 @@ func TestGenerateDocument_NonLocalRootFlagNoDuplication(t *testing.T) { } } } + +func TestFromCommand_WithPublicCommand(t *testing.T) { + root := &cobra.Command{Use: "myapp"} + buf := new(bytes.Buffer) + FromCommand(root, WithPublicCommand("docgen"), WithOutput(buf)) + + var pub *cobra.Command + for _, c := range root.Commands() { + if c.Use == "docgen" { + pub = c + } + } + if pub == nil { + t.Fatal("docgen subcommand not found") + } + if pub.Hidden { + t.Error("docgen should be visible") + } + + root.SetArgs([]string{"docgen", "--format", "json"}) + if err := root.Execute(); err != nil { + t.Fatalf("docgen failed: %v", err) + } + if !strings.HasPrefix(strings.TrimSpace(buf.String()), "{") { + t.Errorf("expected JSON output, got: %s", buf.String()) + } + // Neither generator command may appear in the document itself. + if strings.Contains(buf.String(), "docgen") || strings.Contains(buf.String(), "__opencli") { + t.Error("generator commands must be excluded from the generated document") + } +} diff --git a/adapters/ourfave/ourfave.go b/adapters/ourfave/ourfave.go index 0b9497b..a2b8c31 100644 --- a/adapters/ourfave/ourfave.go +++ b/adapters/ourfave/ourfave.go @@ -1,7 +1,8 @@ // Package ourfave provides the ability to create OpenCLI documents from existing urfave/cli v3 CLIs. // -// It attaches a hidden subcommand to an existing urfave/cli root command that, when -// invoked, walks the entire command tree and emits a valid OpenCLI spec document. +// It attaches a hidden "__opencli" subcommand (and optionally a visible one via +// WithPublicCommand) to an existing urfave/cli root command that, when invoked, +// walks the entire command tree and emits a valid OpenCLI spec document. // // Typical usage: // @@ -30,6 +31,7 @@ type config struct { globalFlags []spec.FlagItem output io.Writer format codec.Format + publicName string } func (c *config) getInfo() spec.Info { @@ -64,43 +66,71 @@ func WithFormat(f codec.Format) Option { return func(c *config) { c.format = f } } +// WithPublicCommand additionally attaches a visible subcommand with the given +// name (e.g. "docgen") that behaves exactly like the hidden "__opencli" command. +// A visible command advertises in help output that the CLI can describe itself. +func WithPublicCommand(name string) Option { + return func(c *config) { c.publicName = name } +} + // WithOutput sets the io.Writer for the generated spec. // Defaults to os.Stdout if omitted. func WithOutput(w io.Writer) Option { return func(c *config) { c.output = w } } -// FromCommand attaches a hidden "__opencli" subcommand to rootCmd. -// Running that subcommand walks the urfave/cli command tree and writes an OpenCLI -// spec document to the configured output (default: stdout). +// generatorMetadata marks subcommands attached by FromCommand so the tree walk +// can skip them. +const generatorMetadata = "opencli.generator" + +// FromCommand attaches a hidden "__opencli" subcommand to rootCmd, plus a visible +// one when WithPublicCommand is used. Running either subcommand walks the +// urfave/cli command tree and writes an OpenCLI spec document to the configured +// output (default: stdout). func FromCommand(rootCmd *cli.Command, opts ...Option) { c := defaultConfigWithOptions(opts...) - rootCmd.Commands = append(rootCmd.Commands, &cli.Command{ - Name: "__opencli", - Hidden: true, + rootCmd.Commands = append(rootCmd.Commands, newGenCmd(rootCmd, c, "__opencli", true)) + if c.publicName != "" { + rootCmd.Commands = append(rootCmd.Commands, newGenCmd(rootCmd, c, c.publicName, false)) + } +} + +func newGenCmd(rootCmd *cli.Command, c *config, name string, hidden bool) *cli.Command { + return &cli.Command{ + Name: name, + Usage: "Generate the OpenCLI specification for this CLI", + Hidden: hidden, + Metadata: map[string]any{generatorMetadata: true}, Action: func(ctx context.Context, cmd *cli.Command) error { - outPath := cmd.String("out") - if outPath != "" { + out := c.output + if outPath := cmd.String("out"); outPath != "" { f, err := os.OpenFile(outPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return fmt.Errorf("unable to write opencli doc to specified file: %w", err) } defer f.Close() - - c.output = f + out = f + } + format := c.format + if f := cmd.String("format"); f != "" { + format = codec.Format(f) } doc := documentFromCommand(rootCmd, c) - return writeDoc(c.output, doc, c.format) + return writeDoc(out, doc, format) }, Flags: []cli.Flag{ &cli.StringFlag{ Name: "out", Aliases: []string{"o"}, - Usage: "The path to the file where the generated spec will be output", + Usage: "The path to the file where the generated spec will be written (default: stdout)", + }, + &cli.StringFlag{ + Name: "format", + Usage: "The output format: yaml or json", }, }, - }) + } } // GenerateDocument walks a urfave/cli command tree and returns the corresponding @@ -215,8 +245,8 @@ func commandFromUrfave(cmd *cli.Command, parent *spec.CommandItem, isRoot bool) // Recurse into children (skip our own generator command) for _, child := range cmd.Commands { - if child.Name == "__opencli" { - continue + if child.Metadata[generatorMetadata] != nil { + continue // skip our own generator commands } childItem := commandFromUrfave(child, item, false) item.Commands = append(item.Commands, childItem) diff --git a/adapters/ourfave/ourfave_test.go b/adapters/ourfave/ourfave_test.go index 8ca5d30..9d2e281 100644 --- a/adapters/ourfave/ourfave_test.go +++ b/adapters/ourfave/ourfave_test.go @@ -437,3 +437,33 @@ func TestGenerateDocument_NonLocalRootFlagNoDuplication(t *testing.T) { } } } + +func TestFromCommand_WithPublicCommand(t *testing.T) { + root := &cli.Command{Name: "myapp"} + buf := new(bytes.Buffer) + FromCommand(root, WithPublicCommand("docgen"), WithOutput(buf)) + + var pub *cli.Command + for _, c := range root.Commands { + if c.Name == "docgen" { + pub = c + } + } + if pub == nil { + t.Fatal("docgen subcommand not found") + } + if pub.Hidden { + t.Error("docgen should be visible") + } + + if err := root.Run(context.Background(), []string{"myapp", "docgen", "--format", "json"}); err != nil { + t.Fatalf("docgen failed: %v", err) + } + if !strings.HasPrefix(strings.TrimSpace(buf.String()), "{") { + t.Errorf("expected JSON output, got: %s", buf.String()) + } + // Neither generator command may appear in the document itself. + if strings.Contains(buf.String(), "docgen") || strings.Contains(buf.String(), "__opencli") { + t.Error("generator commands must be excluded from the generated document") + } +} diff --git a/docs/ocli.ocs.md b/docs/ocli.ocs.md index fe39586..6384f95 100644 --- a/docs/ocli.ocs.md +++ b/docs/ocli.ocs.md @@ -112,6 +112,10 @@ by parsing it and checking it against the OpenCLI Specification. > [!TIP] > The format of the input file will be determined by the file extension. +The path may also point to a CLI binary built with one of the OpenCLI +adapters. In that case `ocli` runs ` __opencli`, falling back to +` docgen`, and checks the document it emits. + `string` @@ -156,7 +160,7 @@ generated using the `--format` flag. ##### `` -Path to the OpenCLI Spec document +Path to the OpenCLI Spec document, or a CLI binary that emits one via `__opencli` or `docgen` `string` @@ -222,7 +226,7 @@ various CLI frameworks from an OpenCLI Spec document. ##### `` -The spec used to generate the code +The spec used to generate the code, or a CLI binary that emits one via `__opencli` or `docgen` `string` diff --git a/internal/cli/app/actions.go b/internal/cli/app/actions.go index f3a2814..3e00d78 100644 --- a/internal/cli/app/actions.go +++ b/internal/cli/app/actions.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "os/exec" "path/filepath" "strings" @@ -14,6 +15,62 @@ import ( "github.com/bcdxn/opencli/validate" ) +// specCommands are the subcommands tried, in order, when the spec path is a CLI +// binary rather than a document. `__opencli` is the hidden command attached by +// the adapters; `docgen` is the public alternative (see WithPublicCommand). +var specCommands = []string{"__opencli", "docgen"} + +// loadSpec reads an OpenCLI document from path and reports its format as a file +// extension (".json", ".yaml", or ".yml"). A .json/.yaml/.yml path is read as a file. Any +// other executable path is treated as a CLI binary: each of specCommands is run in +// turn and the first successful stdout is used. +func loadSpec(path string) ([]byte, string, error) { + info, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + return nil, "", gencli.NewValidationError(fmt.Sprintf("file not found: %s", path)) + } + return nil, "", gencli.NewValidationError(fmt.Sprintf("cannot access file: %s (%v)", path, err)) + } + if info.IsDir() { + return nil, "", gencli.NewValidationError(fmt.Sprintf("path is a directory, not a file: %s", path)) + } + + ext := strings.ToLower(filepath.Ext(path)) + switch ext { + case ".json", ".yaml", ".yml": + data, err := os.ReadFile(path) + if err != nil { + return nil, "", gencli.NewValidationError(fmt.Sprintf("cannot read file: %s (%v)", path, err)) + } + return data, ext, nil + } + + if info.Mode()&0111 == 0 { + return nil, "", gencli.NewValidationError(fmt.Sprintf("unsupported file format: %s (only .json, .yaml, .yml, or an executable CLI are supported)", ext)) + } + + var errs []string + for _, sub := range specCommands { + out, err := exec.Command(path, sub).Output() + if err == nil { + if strings.HasPrefix(strings.TrimSpace(string(out)), "{") { + return out, ".json", nil + } + return out, ".yaml", nil + } + errs = append(errs, fmt.Sprintf("%s %s: %v", filepath.Base(path), sub, err)) + } + return nil, "", gencli.NewValidationError(fmt.Sprintf("cannot get spec from %s (tried %s): %s", path, strings.Join(specCommands, ", "), strings.Join(errs, "; "))) +} + +func decoderFor(ext string) func([]byte) (*spec.Document, error) { + if ext == ".json" { + return codec.UnmarshalJSON + } + return codec.UnmarshalYAML +} + // Ensure we conform to the generated ActionsInterface var _ gencli.ActionsInterface = (*Actions)(nil) @@ -31,29 +88,11 @@ type Actions struct { } func (a Actions) OcliGenDocs(_ context.Context, args gencli.OcliGenDocsArgs, flags gencli.OcliGenDocsFlags) error { - // Validate file exists and is not a directory - info, err := os.Stat(args.PathToSpec) + data, ext, err := loadSpec(args.PathToSpec) if err != nil { - if os.IsNotExist(err) { - return gencli.NewValidationError(fmt.Sprintf("file not found: %s", args.PathToSpec)) - } - return gencli.NewValidationError(fmt.Sprintf("cannot access file: %s (%v)", args.PathToSpec, err)) - } - if info.IsDir() { - return gencli.NewValidationError(fmt.Sprintf("path is a directory, not a file: %s", args.PathToSpec)) - } - - // Select decoder by file extension - ext := strings.ToLower(filepath.Ext(args.PathToSpec)) - decode := codec.UnmarshalYAML - switch ext { - case ".json": - decode = codec.UnmarshalJSON - case ".yaml", ".yml": - // default - default: - return gencli.NewValidationError(fmt.Sprintf("unsupported spec format: %s (only .json, .yaml, .yml are supported)", ext)) + return err } + decode := decoderFor(ext) // Map the --format flag to a DocFormat; this map is the extension point for new formats type docFormatMeta struct { @@ -78,11 +117,7 @@ func (a Actions) OcliGenDocs(_ context.Context, args gencli.OcliGenDocsArgs, fla stdout := a.IOS.Out() fmt.Fprintf(stdout, "\n→ Reading spec: %s\n", args.PathToSpec) - // Read and parse the spec document - data, err := os.ReadFile(args.PathToSpec) - if err != nil { - return gencli.NewValidationError(fmt.Sprintf("cannot read file: %s (%v)", args.PathToSpec, err)) - } + // Parse the spec document doc, err := decode(data) if err != nil { return gencli.NewValidationError(fmt.Sprintf("failed to parse spec: %v", err)) @@ -135,36 +170,16 @@ func (a Actions) OcliGenDocs(_ context.Context, args gencli.OcliGenDocsArgs, fla // OcliCheck implements the `ocli check` command and uses the `validate` package to validate/check the specified document. func (a Actions) OcliCheck(_ context.Context, args gencli.OcliCheckArgs, flags gencli.OcliCheckFlags) error { - // Verify file exists and is readable - info, err := os.Stat(args.PathToSpec) - if err != nil { - if os.IsNotExist(err) { - return gencli.NewValidationError(fmt.Sprintf("file not found: %s", args.PathToSpec)) - } - return gencli.NewValidationError(fmt.Sprintf("cannot access file: %s (%v)", args.PathToSpec, err)) - } - - if info.IsDir() { - return gencli.NewValidationError(fmt.Sprintf("path is a directory, not a file: %s", args.PathToSpec)) - } - - // Read file content - data, err := os.ReadFile(args.PathToSpec) + data, ext, err := loadSpec(args.PathToSpec) if err != nil { - return gencli.NewValidationError(fmt.Sprintf("cannot read file: %s (%v)", args.PathToSpec, err)) + return err } - // Determine format by file extension - ext := strings.ToLower(filepath.Ext(args.PathToSpec)) var validationErr error - - switch ext { - case ".json": + if ext == ".json" { validationErr = validate.ValidateJSON(data) - case ".yaml", ".yml": + } else { validationErr = validate.ValidateYAML(data) - default: - return gencli.NewValidationError(fmt.Sprintf("unsupported file format: %s (only .json, .yaml, .yml are supported)", ext)) } // Output results @@ -190,38 +205,16 @@ func (a Actions) OcliCheck(_ context.Context, args gencli.OcliCheckArgs, flags g } func (a Actions) OcliGenCli(_ context.Context, args gencli.OcliGenCliArgs, flags gencli.OcliGenCliFlags) error { - // Validate file exists and is not a directory - info, err := os.Stat(args.PathToSpec) + data, ext, err := loadSpec(args.PathToSpec) if err != nil { - if os.IsNotExist(err) { - return gencli.NewValidationError(fmt.Sprintf("file not found: %s", args.PathToSpec)) - } - return gencli.NewValidationError(fmt.Sprintf("cannot access file: %s (%v)", args.PathToSpec, err)) - } - if info.IsDir() { - return gencli.NewValidationError(fmt.Sprintf("path is a directory, not a file: %s", args.PathToSpec)) - } - - // Select decoder by file extension - ext := strings.ToLower(filepath.Ext(args.PathToSpec)) - decode := codec.UnmarshalYAML - switch ext { - case ".json": - decode = codec.UnmarshalJSON - case ".yaml", ".yml": - // default - default: - return gencli.NewValidationError(fmt.Sprintf("unsupported spec format: %s (only .json, .yaml, .yml are supported)", ext)) + return err } + decode := decoderFor(ext) stdout := a.IOS.Out() fmt.Fprintf(stdout, "\n→ Reading spec: %s\n", args.PathToSpec) - // Read and parse the spec document - data, err := os.ReadFile(args.PathToSpec) - if err != nil { - return gencli.NewValidationError(fmt.Sprintf("cannot read file: %s (%v)", args.PathToSpec, err)) - } + // Parse the spec document doc, err := decode(data) if err != nil { return gencli.NewValidationError(fmt.Sprintf("failed to parse spec: %v", err)) diff --git a/internal/cli/app/actions_test.go b/internal/cli/app/actions_test.go index f269522..a47d944 100644 --- a/internal/cli/app/actions_test.go +++ b/internal/cli/app/actions_test.go @@ -891,3 +891,53 @@ func TestOcliGenCliParseError(t *testing.T) { t.Errorf("expected ValidationError for parse error, got %T", err) } } + +// fakeCLI writes an executable shell script that only answers to `docgen`, so the +// `__opencli` attempt fails and the fallback must be used. +func fakeCLI(t *testing.T) string { + t.Helper() + path := filepath.Join(t.TempDir(), "mycli") + script := "#!/bin/sh\nif [ \"$1\" = \"docgen\" ]; then cat <<'SPEC'\n" + validSpecJSON + "\nSPEC\nexit 0; fi\nexit 1\n" + if err := os.WriteFile(path, []byte(script), 0755); err != nil { + t.Fatalf("failed to write fake cli: %v", err) + } + return path +} + +func TestOcliCheckFromBinaryFallsBackToDocgen(t *testing.T) { + ios, _, output, _ := gencli.TestIOS() + actions := Actions{IOS: ios} + + err := actions.OcliCheck(t.Context(), gencli.OcliCheckArgs{PathToSpec: fakeCLI(t)}, gencli.OcliCheckFlags{FailOnErr: true}) + if err != nil { + t.Fatalf("expected spec from binary to validate, got: %v", err) + } + if !contains(output.String(), "Document is valid") { + t.Errorf("expected valid document output, got: %s", output.String()) + } +} + +func TestOcliGenDocsFromBinary(t *testing.T) { + ios, _, _, _ := gencli.TestIOS() + actions := Actions{IOS: ios} + out := t.TempDir() + + err := actions.OcliGenDocs(t.Context(), gencli.OcliGenDocsArgs{PathToSpec: fakeCLI(t)}, gencli.OcliGenDocsFlags{Format: "markdown", Out: out}) + if err != nil { + t.Fatalf("expected docs from binary, got: %v", err) + } + if _, err := os.Stat(filepath.Join(out, "mycli.md")); err != nil { + t.Errorf("expected mycli.md to be written: %v", err) + } +} + +func TestLoadSpecBinaryNoSpecCommand(t *testing.T) { + path := filepath.Join(t.TempDir(), "nocli") + if err := os.WriteFile(path, []byte("#!/bin/sh\nexit 1\n"), 0755); err != nil { + t.Fatal(err) + } + _, _, err := loadSpec(path) + if err == nil || !contains(err.Error(), "tried __opencli, docgen") { + t.Errorf("expected error listing tried commands, got: %v", err) + } +} diff --git a/internal/cli/gencli/cmd_ocli_gen_cli.gen.go b/internal/cli/gencli/cmd_ocli_gen_cli.gen.go index 55b7f17..e56dc9f 100644 --- a/internal/cli/gencli/cmd_ocli_gen_cli.gen.go +++ b/internal/cli/gencli/cmd_ocli_gen_cli.gen.go @@ -60,7 +60,7 @@ func getSpecOcliGenCliCmd() *spec.CommandItem { "[flags]", }, Args: []spec.ArgumentItem{ - {Name: "path-to-spec", Summary: "The spec used to generate the code"}, + {Name: "path-to-spec", Summary: "The spec used to generate the code, or a CLI binary that emits one via `__opencli` or `docgen`"}, }, Flags: []spec.FlagItem{ {Name: "out", Summary: "The path to the directory where the generated code will be output"}, diff --git a/internal/cli/gencli/cmd_ocli_gen_docs.gen.go b/internal/cli/gencli/cmd_ocli_gen_docs.gen.go index 6b8ede5..67b2782 100644 --- a/internal/cli/gencli/cmd_ocli_gen_docs.gen.go +++ b/internal/cli/gencli/cmd_ocli_gen_docs.gen.go @@ -66,7 +66,7 @@ func getSpecOcliGenDocsCmd() *spec.CommandItem { "[flags]", }, Args: []spec.ArgumentItem{ - {Name: "path-to-spec", Summary: "Path to the OpenCLI Spec document"}, + {Name: "path-to-spec", Summary: "Path to the OpenCLI Spec document, or a CLI binary that emits one via `__opencli` or `docgen`"}, }, Flags: []spec.FlagItem{ {Name: "format", Summary: "The format of the documentation to generate"}, diff --git a/ocli.ocs.yaml b/ocli.ocs.yaml index d5eb35e..cc490e9 100644 --- a/ocli.ocs.yaml +++ b/ocli.ocs.yaml @@ -90,6 +90,10 @@ commands: > [!TIP] > The format of the input file will be determined by the file extension. + + The path may also point to a CLI binary built with one of the OpenCLI + adapters. In that case `ocli` runs ` __opencli`, falling back to + ` docgen`, and checks the document it emits. required: true type: "string" flags: @@ -119,7 +123,7 @@ commands: generated using the `--format` flag. args: - name: "path-to-spec" - summary: "Path to the OpenCLI Spec document" + summary: "Path to the OpenCLI Spec document, or a CLI binary that emits one via `__opencli` or `docgen`" required: true type: "string" flags: @@ -171,7 +175,7 @@ commands: various CLI frameworks from an OpenCLI Spec document. args: - name: "path-to-spec" - summary: "The spec used to generate the code" + summary: "The spec used to generate the code, or a CLI binary that emits one via `__opencli` or `docgen`" required: true type: "string" flags: diff --git a/web/public/ocli-docs.js b/web/public/ocli-docs.js index 6c9ee89..fa0b1db 100644 --- a/web/public/ocli-docs.js +++ b/web/public/ocli-docs.js @@ -5,7 +5,7 @@ return; } - var EMBED_MARKUP = "\n\n\u003cstyle\u003e\n \n\n \n.ocli[data-theme=\"light\"] {\n --ocli-bg: #ffffff;\n --ocli-bg-sidebar: #f7f9fc;\n --ocli-bg-code: #eef1f6;\n --ocli-bg-hover: #eef2f8;\n --ocli-border: #dde3ec;\n --ocli-border-light: #edf0f5;\n --ocli-text: #3a4a5c;\n --ocli-text-muted: #7a8aa0;\n --ocli-text-active: #0d1f2d;\n --ocli-accent: #5469d4;\n --ocli-accent-soft: #eef0fb;\n --ocli-badge-bg: #e8edf8;\n --ocli-badge-text: #3d5caa;\n --ocli-required-bg: #fef2f2;\n --ocli-required-text:#c0392b;\n --ocli-group-bg: #f0f4f8;\n --ocli-group-text: #5a6a7e;\n --ocli-sticky-shadow:0 2px 8px rgba(0,0,0,0.06);\n}\n\n.ocli[data-theme=\"dark\"] {\n --ocli-bg: #2e3440;\n --ocli-bg-sidebar: #262c38;\n --ocli-bg-code: #3b4252;\n --ocli-bg-hover: #353d4f;\n --ocli-border: #4c566a;\n --ocli-border-light: #3e4759;\n --ocli-text: #c8d3e6;\n --ocli-text-muted: #7b8fa8;\n --ocli-text-active: #eceff4;\n --ocli-accent: #81a1c1;\n --ocli-accent-soft: #2d3b4f;\n --ocli-badge-bg: #2c3d55;\n --ocli-badge-text: #88c0d0;\n --ocli-required-bg: #3a2020;\n --ocli-required-text:#f08080;\n --ocli-group-bg: #3b4252;\n --ocli-group-text: #8a9ab5;\n --ocli-sticky-shadow:0 2px 8px rgba(0,0,0,0.25);\n}\n\n \n.ocli, .ocli *, .ocli *::before, .ocli *::after {\n box-sizing: border-box;\n}\n\n.ocli {\n background: var(--ocli-bg);\n color: var(--ocli-text);\n display: flex;\n flex-direction: row;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen,\n Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif;\n font-size: 15px;\n line-height: 1.6;\n height: 100%;\n min-width: 0;\n}\n\n \n.ocli__sidebar {\n background: var(--ocli-bg-sidebar);\n border-right: 1px solid var(--ocli-border);\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n height: 100vh;\n overflow-y: auto;\n position: sticky;\n top: 0;\n width: 260px;\n}\n\n.ocli__sidebar::-webkit-scrollbar { width: 4px; }\n.ocli__sidebar::-webkit-scrollbar-thumb { background: var(--ocli-border); border-radius: 2px; }\n\n.ocli__sidebar-header {\n align-items: stretch;\n border-bottom: 1px solid var(--ocli-border);\n display: flex;\n flex-direction: column;\n gap: 6px;\n justify-content: center;\n min-height: 60px;\n padding: 12px 16px;\n}\n\n.ocli__sidebar-header-top {\n align-items: center;\n display: flex;\n gap: 10px;\n justify-content: space-between;\n}\n\n.ocli__sidebar-title {\n color: var(--ocli-text-active);\n font-size: 15px;\n font-weight: 700;\n line-height: 1.3;\n}\n\n.ocli__sidebar-version {\n color: var(--ocli-text-muted);\n font-size: 11px;\n font-weight: 500;\n}\n\n.ocli-theme-toggle {\n align-items: center;\n background: var(--ocli-bg-hover);\n border: 1px solid var(--ocli-border);\n border-radius: 999px;\n color: var(--ocli-text-muted);\n cursor: pointer;\n display: inline-flex;\n flex-shrink: 0;\n height: 28px;\n justify-content: flex-start;\n padding: 3px;\n transition: background 0.2s ease, border-color 0.2s ease;\n width: 52px;\n}\n\n.ocli-theme-toggle:hover {\n border-color: var(--ocli-accent);\n}\n\n.ocli-theme-toggle:focus-visible {\n outline: 2px solid var(--ocli-accent);\n outline-offset: 2px;\n}\n\n.ocli-theme-toggle__thumb {\n align-items: center;\n background: var(--ocli-bg);\n border-radius: 999px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.25);\n display: inline-flex;\n height: 20px;\n justify-content: center;\n position: relative;\n transform: translateX(0);\n transition: transform 0.2s ease, background 0.2s ease;\n width: 20px;\n}\n\n.ocli-theme-toggle__icon {\n fill: none;\n height: 12px;\n left: 50%;\n position: absolute;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n top: 50%;\n transform: translate(-50%, -50%);\n transition: opacity 0.15s ease;\n width: 12px;\n}\n\n.ocli-theme-toggle__icon--sun {\n opacity: 1;\n}\n\n.ocli-theme-toggle__icon--moon {\n opacity: 0;\n}\n\n.ocli[data-theme=\"light\"] .ocli-theme-toggle {\n background: #d9dee7;\n}\n\n.ocli[data-theme=\"light\"] .ocli-theme-toggle__thumb {\n background: #ffffff;\n color: #d59a22;\n}\n\n.ocli[data-theme=\"dark\"] .ocli-theme-toggle {\n background: #5d6577;\n}\n\n.ocli[data-theme=\"dark\"] .ocli-theme-toggle__thumb {\n background: #1f2531;\n color: #d6dded;\n transform: translateX(24px);\n}\n\n.ocli[data-theme=\"dark\"] .ocli-theme-toggle__icon--sun {\n opacity: 0;\n}\n\n.ocli[data-theme=\"dark\"] .ocli-theme-toggle__icon--moon {\n opacity: 1;\n}\n\n.ocli__sidebar-body {\n flex: 1;\n overflow-y: auto;\n padding: 12px 0 24px;\n}\n\n.ocli__nav-section {\n margin: 16px 0 4px;\n padding: 0 16px;\n}\n\n.ocli__nav-section-label {\n color: var(--ocli-text-muted);\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.08em;\n padding: 4px 0;\n text-transform: uppercase;\n}\n\n.ocli__nav-list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.ocli__nav-list--nested {\n border-left: 2px solid var(--ocli-border-light);\n margin-left: 10px;\n padding-left: 8px;\n}\n\n.ocli__nav-item {\n margin: 0;\n padding: 0;\n}\n\n.ocli__nav-link {\n align-items: center;\n border-radius: 5px;\n color: var(--ocli-text);\n cursor: pointer;\n display: flex;\n font-size: 13px;\n gap: 4px;\n justify-content: space-between;\n padding: 5px 8px;\n text-decoration: none;\n transition: background 0.1s, color 0.1s;\n}\n\n.ocli__nav-link:hover {\n background: var(--ocli-bg-hover);\n color: var(--ocli-text-active);\n}\n\n.ocli__nav-link.is-active {\n background: var(--ocli-accent-soft);\n color: var(--ocli-accent);\n font-weight: 600;\n}\n\n.ocli__nav-link .ocli__nav-toggle {\n display: inline-block;\n font-size: 10px;\n opacity: 0.6;\n transition: transform 0.15s;\n}\n\n.ocli__nav-item.is-open \u003e .ocli__nav-link .ocli__nav-toggle {\n transform: rotate(90deg);\n}\n\n.ocli__nav-sublist {\n display: none;\n list-style: none;\n margin: 2px 0 4px 12px;\n padding: 0;\n}\n\n.ocli__nav-item.is-open \u003e .ocli__nav-sublist {\n display: block;\n}\n\n \n.ocli__main {\n flex: 1;\n height: 100%;\n min-width: 0;\n overflow-y: auto;\n}\n\n.ocli__main::-webkit-scrollbar { width: 6px; }\n.ocli__main::-webkit-scrollbar-thumb { background: var(--ocli-border); border-radius: 3px; }\n\n \n.ocli-section {\n border-bottom: 1px solid var(--ocli-border);\n}\n\n.ocli-section__sticky {\n align-items: center;\n background: var(--ocli-bg);\n border-bottom: 1px solid transparent;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n min-height: 60px;\n padding: 0 24px;\n position: sticky;\n top: -1px;\n transition: border-color 0.15s, box-shadow 0.15s;\n z-index: 10;\n}\n\n.ocli-section__sticky.is-stuck {\n border-bottom-color: var(--ocli-border);\n box-shadow: var(--ocli-sticky-shadow);\n}\n\n.ocli-section__sticky-title {\n color: var(--ocli-text-active);\n font-size: 16px;\n font-weight: 600;\n}\n\n.ocli-section__cmd {\n background: var(--ocli-bg-code);\n border-radius: 5px;\n color: var(--ocli-text-active);\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 14px;\n font-weight: 600;\n padding: 3px 8px;\n margin-left: 6px;\n}\n\n.ocli-section__body {\n padding: 0px 24px 28px 30px;\n}\n\n.ocli-section__intro-grid {\n display: grid;\n gap: 24px;\n grid-template-columns: 1fr 1fr;\n padding: 20px 24px 28px;\n}\n\n@media (max-width: 720px) {\n .ocli-section__intro-grid {\n grid-template-columns: 1fr;\n }\n}\n\n \n.ocli-section__body--two-col {\n display: grid;\n gap: 32px;\n grid-template-columns: 1fr 1fr;\n padding: 20px 24px 28px;\n}\n\n@media (max-width: 720px) {\n .ocli-section__body--two-col {\n grid-template-columns: 1fr;\n }\n}\n\n.ocli-section__col-left {\n min-width: 0;\n}\n\n.ocli-section__col-right {\n align-self: start;\n position: sticky;\n top: 80px;\n max-height: calc(100vh - 100px);\n overflow-y: auto;\n}\n\n \n.ocli-examples {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.ocli-examples__heading {\n color: var(--ocli-text-active);\n font-size: 14px;\n font-weight: 700;\n letter-spacing: 0.04em;\n margin: 0 0 4px;\n text-transform: uppercase;\n}\n\n.ocli-example {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.ocli-example__title {\n color: var(--ocli-text);\n font-size: 13px;\n font-weight: 600;\n line-height: 1.4;\n}\n\n \n.ocli-badges {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n gap: 5px;\n}\n\n.ocli-badge {\n border-radius: 4px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n padding: 2px 7px;\n}\n\n.ocli-badge--default {\n background: var(--ocli-badge-bg);\n color: var(--ocli-badge-text);\n}\n\n.ocli-badge--group {\n background: var(--ocli-group-bg);\n color: var(--ocli-group-text);\n}\n\n.ocli-badge--required {\n background: var(--ocli-required-bg);\n color: var(--ocli-required-text);\n}\n\n \n.ocli-section__body h2, .ocli-section__intro-grid h2 {\n color: var(--ocli-text-active);\n font-size: 14px;\n font-weight: 700;\n margin: 0 0 8px;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.ocli-summary {\n color: var(--ocli-text-active);\n font-size: 15px;\n font-weight: 500;\n margin-bottom: 12px;\n}\n\n \n.ocli-md p {\n color: var(--ocli-text);\n line-height: 1.7;\n margin: 0 0 12px;\n}\n.ocli-md p:last-child { margin-bottom: 0; }\n.ocli-md a { color: var(--ocli-accent); text-decoration: none; }\n.ocli-md a:hover { text-decoration: underline; }\n.ocli-md strong { color: var(--ocli-text-active); font-weight: 600; }\n.ocli-md em { font-style: italic; }\n.ocli-md ul, .ocli-md ol { margin: 8px 0 12px 20px; }\n.ocli-md li { margin: 4px 0; }\n.ocli-md code {\n background: var(--ocli-bg-code);\n border-radius: 4px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 0.875em;\n padding: 2px 5px;\n}\n.ocli-md pre {\n background: var(--ocli-bg-code);\n border-radius: 6px;\n margin: 12px 0;\n overflow-x: auto;\n padding: 14px 16px;\n}\n.ocli-md pre code {\n background: none;\n font-size: 13px;\n padding: 0;\n}\n.ocli-md h1, .ocli-md h2, .ocli-md h3 {\n color: var(--ocli-text-active);\n font-weight: 600;\n margin: 16px 0 8px;\n}\n\n \n.ocli-meta-box {\n margin-bottom: 16px;\n}\n\n.ocli-meta-box__label {\n color: var(--ocli-text-muted);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.07em;\n margin-bottom: 6px;\n text-transform: uppercase;\n}\n\n.ocli-meta-box__value {\n color: var(--ocli-text);\n font-size: 14px;\n}\n\n.ocli-meta-box__value a {\n color: var(--ocli-accent);\n text-decoration: none;\n}\n\n.ocli-meta-box__value a:hover { text-decoration: underline; }\n\n \n.ocli-tabs__tablist {\n border-bottom: 1px solid var(--ocli-border);\n display: flex;\n flex-wrap: wrap;\n gap: 0;\n margin-bottom: 20px;\n}\n\n.ocli-tabs__tab {\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n color: var(--ocli-text-muted);\n cursor: pointer;\n font-family: inherit;\n font-size: 14px;\n font-weight: 500;\n margin-bottom: -1px;\n padding: 10px 16px;\n transition: color 0.15s, border-color 0.15s;\n}\n\n.ocli-tabs__tab:hover {\n color: var(--ocli-text-active);\n}\n\n.ocli-tabs__tab.is-active {\n border-bottom-color: var(--ocli-accent);\n color: var(--ocli-accent);\n}\n\n.ocli-tabs__panel {\n display: none;\n}\n\n.ocli-tabs__panel.is-active {\n display: block;\n}\n\n.ocli-tabs__panel-desc {\n color: var(--ocli-text);\n font-size: 14px;\n margin: 0 0 12px;\n}\n\n.ocli-tabs__panel-url {\n font-size: 14px;\n margin-top: 10px;\n}\n\n.ocli-tabs__panel-url a {\n color: var(--ocli-accent);\n}\n\n \n.ocli-code-block {\n background: var(--ocli-bg-code);\n border-radius: 6px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 13px;\n line-height: 1.6;\n overflow-x: auto;\n padding: 12px 14px;\n}\n\n \n.ocli-code-block--terminal {\n background: none;\n border: 1px solid var(--ocli-border);\n border-radius: 8px;\n overflow: hidden;\n padding: 0;\n}\n\n.ocli-code-block__header {\n align-items: center;\n background: #1a2133;\n border-bottom: 1px solid rgba(255,255,255,0.08);\n display: flex;\n padding: 8px 14px;\n}\n\n.ocli-code-block__label {\n color: rgba(255,255,255,0.55);\n font-size: 12px;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.ocli-code-block__body {\n background: #1e2d45;\n color: #a8d8f0;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 13px;\n line-height: 1.6;\n margin: 0;\n overflow-x: auto;\n padding: 16px 18px;\n white-space: pre;\n}\n\n \n\n.ocli-table-container {\n border: 1px solid var(--ocli-border);\n border-radius: 8px;\n overflow: hidden;\n display: inline-block;\n width: 100%;\n}\n\n.ocli-table {\n border-collapse: collapse;\n font-size: 14px;\n width: 100%;\n}\n\n.ocli-table th {\n background: var(--ocli-bg-sidebar);\n border: 1px solid var(--ocli-border);\n color: var(--ocli-text-muted);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.05em;\n padding: 8px 12px;\n text-align: left;\n text-transform: uppercase;\n}\n\n.ocli-table td {\n border: 1px solid var(--ocli-border);\n padding: 8px 12px;\n color: var(--ocli-text);\n}\n\n.ocli-table tr:first-child th { border-top: none; }\n.ocli-table tr:last-child td { border-bottom: none; }\n.ocli-table tr td:first-child, tr th:first-child { border-left: none; }\n.ocli-table tr td:last-child, tr th:last-child { border-right: none; }\n\n.ocli-table code {\n background: var(--ocli-bg-code);\n border-radius: 3px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 0.875em;\n padding: 1px 4px;\n}\n\n \n.ocli-exit-code {\n align-items: flex-start;\n border-bottom: 1px solid var(--ocli-border-light);\n display: flex;\n gap: 12px;\n padding: 12px 0;\n}\n\n.ocli-exit-code:last-child { border-bottom: none; }\n\n.ocli-exit-code__code {\n background: var(--ocli-bg-code);\n border-radius: 4px;\n color: var(--ocli-text-active);\n flex-shrink: 0;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 13px;\n font-weight: 600;\n min-width: 28px;\n padding: 2px 7px;\n text-align: center;\n}\n\n.ocli-exit-code__details {}\n\n.ocli-exit-code__status {\n background: var(--ocli-badge-bg);\n border-radius: 4px;\n color: var(--ocli-badge-text);\n display: inline-block;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 11px;\n font-weight: 600;\n margin-bottom: 4px;\n padding: 2px 6px;\n}\n\n.ocli-exit-code__summary {\n color: var(--ocli-text);\n font-size: 14px;\n}\n\n.ocli-exit-code__desc {\n color: var(--ocli-text-muted);\n font-size: 13px;\n margin-top: 4px;\n}\n\n \n.ocli-params {\n margin-top: 24px;\n}\n\n.ocli-params__heading {\n border-bottom: 1px solid var(--ocli-border);\n color: var(--ocli-text-muted);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.07em;\n margin-bottom: 4px;\n padding-bottom: 8px;\n text-transform: uppercase;\n}\n\n.ocli-param {\n border-bottom: 1px solid var(--ocli-border-light);\n padding: 14px 0;\n scroll-margin-top: 60px;\n}\n\n.ocli-param:last-child { border-bottom: none; }\n\n.ocli-param__header {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 6px;\n}\n\n.ocli-param__name {\n color: var(--ocli-text-active);\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 13px;\n font-weight: 600;\n padding: 2px 7px 2px 4px;\n}\n\n \n.ocli-param__anchor,\n.ocli-section__cmd-anchor {\n align-items: center;\n color: inherit;\n display: inline-flex;\n gap: 6px;\n position: relative;\n}\n\n.ocli-deeplink-btn {\n background: none;\n border: none;\n cursor: pointer;\n left: -20px;\n padding: 0 6px;\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n}\n\n.ocli-deeplink-icon {\n color: var(--ocli-accent);\n display: block;\n opacity: 0;\n transition: opacity 0.15s;\n}\n\n.ocli-param__anchor:hover .ocli-deeplink-icon,\n.ocli-section__cmd-anchor:hover .ocli-deeplink-icon {\n opacity: 1;\n}\n\n.ocli-param__summary {\n color: var(--ocli-text);\n font-size: 14px;\n margin-bottom: 4px;\n}\n\n.ocli-param__desc {\n color: var(--ocli-text);\n font-size: 14px;\n margin-top: 6px;\n}\n\n.ocli-param__desc p { margin: 0 0 4px; }\n\n \n.ocli-choices {\n margin-top: 10px;\n}\n\n.ocli-choices__label {\n color: var(--ocli-text-muted);\n font-size: 12px;\n font-weight: 600;\n margin-bottom: 6px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.ocli-choices__list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.ocli-choices__item {\n align-items: baseline;\n display: flex;\n font-size: 13px;\n gap: 8px;\n padding: 3px 0;\n}\n\n.ocli-choices__item code {\n background: var(--ocli-bg-code);\n border-radius: 3px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n flex-shrink: 0;\n padding: 1px 5px;\n}\n\n.ocli-choices__item-desc { color: var(--ocli-text-muted); }\n\n \n.ocli-alt-sources {\n margin-top: 10px;\n}\n\n.ocli-alt-sources__label {\n color: var(--ocli-text-muted);\n font-size: 12px;\n font-weight: 600;\n margin-bottom: 6px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.ocli-alt-sources__list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.ocli-alt-sources__item {\n font-size: 13px;\n padding: 2px 0;\n}\n\n.ocli-alt-sources__item code {\n background: var(--ocli-bg-code);\n border-radius: 3px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n padding: 1px 5px;\n}\n\n \n.ocli-section__body a {\n color: var(--ocli-accent);\n text-decoration: none;\n}\n\n.ocli-section__body a:hover {\n text-decoration: underline;\n}\n\n \n.ocli-footer {\n color: var(--ocli-text-muted);\n font-size: 12px;\n padding: 24px;\n text-align: center;\n}\n\n.ocli-footer a { color: var(--ocli-accent); text-decoration: none; }\n.ocli-footer a:hover { text-decoration: underline; }\n\n \n@media (max-width: 900px) {\n .ocli__sidebar {\n display: none;\n }\n}\n\u003c/style\u003e\n\n\n\u003cdiv class=\"ocli\" data-theme=\"light\"\u003e\n \n\u003cnav class=\"ocli__sidebar\" aria-label=\"Navigation\"\u003e\n \u003cdiv class=\"ocli__sidebar-header\"\u003e\n \u003cdiv class=\"ocli__sidebar-header-top\"\u003e\n \u003cspan class=\"ocli__sidebar-title\"\u003eOpenCLI\u003c/span\u003e\n \u003cbutton\n class=\"ocli-theme-toggle\"\n type=\"button\"\n data-theme-toggle\n aria-label=\"Switch to dark theme\"\n aria-pressed=\"false\"\n \u003e\n \u003cspan class=\"ocli-theme-toggle__thumb\" aria-hidden=\"true\"\u003e\n \u003csvg class=\"ocli-theme-toggle__icon ocli-theme-toggle__icon--sun\" viewBox=\"0 0 24 24\" focusable=\"false\"\u003e\n \u003ccircle cx=\"12\" cy=\"12\" r=\"4\"\u003e\u003c/circle\u003e\n \u003cpath d=\"M12 2v2.2M12 19.8V22M4.9 4.9l1.6 1.6M17.5 17.5l1.6 1.6M2 12h2.2M19.8 12H22M4.9 19.1l1.6-1.6M17.5 6.5l1.6-1.6\"\u003e\u003c/path\u003e\n \u003c/svg\u003e\n \u003csvg class=\"ocli-theme-toggle__icon ocli-theme-toggle__icon--moon\" viewBox=\"0 0 24 24\" focusable=\"false\"\u003e\n \u003cpath d=\"M20.4 14.8A8.7 8.7 0 0 1 9.2 3.6a8.6 8.6 0 1 0 11.2 11.2z\"\u003e\u003c/path\u003e\n \u003c/svg\u003e\n \u003c/span\u003e\n \u003c/button\u003e\n \u003c/div\u003e\n \u003cspan class=\"ocli__sidebar-version\"\u003ev1.2.0\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli__sidebar-body\"\u003e\n \u003cdiv class=\"ocli__nav-section\"\u003e\n \u003cdiv class=\"ocli__nav-section-label\"\u003eOverview\u003c/div\u003e\n \u003cul class=\"ocli__nav-list\"\u003e\n \u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#intro\" data-section=\"intro\"\u003eIntroduction\u003c/a\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#install\" data-section=\"install\"\u003eInstallation\u003c/a\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#config\" data-section=\"config\"\u003eConfiguration\u003c/a\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#exit-codes\" data-section=\"exit-codes\"\u003eExit Codes\u003c/a\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli__nav-section\"\u003e\n \u003cdiv class=\"ocli__nav-section-label\"\u003eCommands\u003c/div\u003e\n \u003cul class=\"ocli__nav-list\"\u003e\n\u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#ocli-check\" data-section=\"ocli-check\"\u003e\n \u003cspan\u003echeck\u003c/span\u003e\n \u003c/a\u003e\n\u003c/li\u003e\n\n\u003cli class=\"ocli__nav-item ocli__nav-item--group\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#ocli-gen\" data-section=\"ocli-gen\"\u003e\n \u003cspan\u003egen\u003c/span\u003e\n \u003cspan class=\"ocli__nav-toggle\"\u003e▸\u003c/span\u003e\n \u003c/a\u003e\n \u003cul class=\"ocli__nav-sublist\"\u003e\n\u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#ocli-gen-docs\" data-section=\"ocli-gen-docs\"\u003e\n \u003cspan\u003edocs\u003c/span\u003e\n \u003c/a\u003e\n\u003c/li\u003e\n\n\u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#ocli-gen-cli\" data-section=\"ocli-gen-cli\"\u003e\n \u003cspan\u003ecli\u003c/span\u003e\n \u003c/a\u003e\n\u003c/li\u003e\n\n \u003c/ul\u003e\n\u003c/li\u003e\n\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/nav\u003e\n\n \u003cdiv class=\"ocli__main\"\u003e\n \n\u003csection class=\"ocli-section\" id=\"intro\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cspan class=\"ocli-section__sticky-title\"\u003eIntroduction\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__intro-grid\"\u003e\n \u003cdiv class=\"ocli-section__intro-left\"\u003e\n \u003cimg src=\"https://img.shields.io/badge/OpenCLI_Spec-Compliant-brightgreen?link=https%3A%2F%2Fgithub.com%2Fbcdxn%2Fopencli\"/\u003e\n \u003cp class=\"ocli-summary\"\u003eA CLI for working with OpenCLI Specs\u003c/p\u003e\n \u003cdiv class=\"ocli-md\"\u003e\u003cp\u003e\u003ccode\u003eocli\u003c/code\u003e is a command line interface designed to make working with \u003ca href=\"https://github.com/bcdxn/opencli/tree/main\"\u003eOpenCLI\nSpec documents\u003c/a\u003e easier. It provides a number of capabilities, including:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003evalidating OpenCLI Spec documents\u003c/li\u003e\n\u003cli\u003egenerating Documentation from OpenCLI Spec documents\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe commands are documented below. You can also find out more about each\ncommand using the contextual \u003ccode\u003e--help\u003c/code\u003e flag. e.g.:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003eocli gen --help\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__intro-right\"\u003e\n \u003cdiv class=\"ocli-meta-box\"\u003e\n \u003cdiv class=\"ocli-meta-box__label\"\u003eLicense\u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box__value\"\u003e\n \u003ca href=\"https://spdx.org/licenses/MIT.html\"\u003eMIT\u003c/a\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box\"\u003e\n \u003cdiv class=\"ocli-meta-box__label\"\u003eContact\u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box__value\"\u003e\u003cdiv\u003eOpenCLI Team\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://github.com/bcdxn/opencli\"\u003ehttps://github.com/bcdxn/opencli\u003c/a\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box\"\u003e\n \u003cdiv class=\"ocli-meta-box__label\"\u003eBinary\u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box__value\"\u003e\u003ccode style=\"font-family:monospace;background:var(--ocli-bg-code);padding:2px 6px;border-radius:4px;\"\u003eocli\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\u003csection class=\"ocli-section\" id=\"install\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cspan class=\"ocli-section__sticky-title\"\u003eInstallation\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body\"\u003e\n \u003cdiv class=\"ocli-tabs\"\u003e\n \u003cdiv class=\"ocli-tabs__tablist\" role=\"tablist\"\u003e\n \u003cbutton class=\"ocli-tabs__tab is-active\"\n role=\"tab\"\n aria-selected=\"true\"\n aria-controls=\"install-panel-0\"\n data-tab=\"install-panel-0\"\u003eBinary Download\u003c/button\u003e\n \u003cbutton class=\"ocli-tabs__tab\"\n role=\"tab\"\n aria-selected=\"false\"\n aria-controls=\"install-panel-1\"\n data-tab=\"install-panel-1\"\u003eGo Install\u003c/button\u003e\n \u003cbutton class=\"ocli-tabs__tab\"\n role=\"tab\"\n aria-selected=\"false\"\n aria-controls=\"install-panel-2\"\n data-tab=\"install-panel-2\"\u003eHomebrew\u003c/button\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-tabs__panel is-active\"\n id=\"install-panel-0\"\n role=\"tabpanel\"\u003e\n \u003cp class=\"ocli-tabs__panel-desc\"\u003eYou can visit the GitHub releases page of the project to download pre-compiled binaries\nappropriate for your system.\n\u003c/p\u003e\n \u003cdiv class=\"ocli-tabs__panel-url\"\u003e\u003ca href=\"https://github.com/bcdxn/opencli/releases\"\u003ehttps://github.com/bcdxn/opencli/releases\u003c/a\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-tabs__panel\"\n id=\"install-panel-1\"\n role=\"tabpanel\"\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eCommand Line\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003ego install github.com/bcdxn/opencli/cmd/ocli@latest\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-tabs__panel\"\n id=\"install-panel-2\"\n role=\"tabpanel\"\u003e\n \u003cp class=\"ocli-tabs__panel-desc\"\u003eInstall the openclidev tap\n```\nbrew tap openclidev/tap\n```\n\nTrust the tap\n```\nbrew trust openclidev/tap\n```\n\nNow you\u0026#39;re ready to install `ocli` using homebrew\n\u003c/p\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eCommand Line\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003ebrew install ocli\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n \n\u003csection class=\"ocli-section\" id=\"config\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cspan class=\"ocli-section__sticky-title\"\u003eConfiguration\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body\"\u003e\n \u003cdiv class=\"ocli-table-container\"\u003e\n \u003ctable class=\"ocli-table\"\u003e\n \u003cthead\u003e\n \u003ctr\u003e\n \u003cth\u003eFormat\u003c/th\u003e\n \u003cth\u003ePath\u003c/th\u003e\n \u003c/tr\u003e\n \u003c/thead\u003e\n \u003ctbody\u003e\n \u003ctr\u003e\u003ctd\u003eYAML\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e~/.ocli/config.yaml\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n \u003c/tbody\u003e\n \u003c/table\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n \n\u003csection class=\"ocli-section\" id=\"exit-codes\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cspan class=\"ocli-section__sticky-title\"\u003eExit Codes\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body\"\u003e\n \u003cdiv class=\"ocli-exit-code\"\u003e\n \u003cspan class=\"ocli-exit-code__code\"\u003e0\u003c/span\u003e\n \u003cdiv class=\"ocli-exit-code__details\"\u003e\n \u003cdiv class=\"ocli-exit-code__status\"\u003eOK\u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code__summary\"\u003eThe command was successful\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code\"\u003e\n \u003cspan class=\"ocli-exit-code__code\"\u003e1\u003c/span\u003e\n \u003cdiv class=\"ocli-exit-code__details\"\u003e\n \u003cdiv class=\"ocli-exit-code__status\"\u003eINTERNAL_CLI_ERROR\u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code__summary\"\u003eThe command failed\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code\"\u003e\n \u003cspan class=\"ocli-exit-code__code\"\u003e2\u003c/span\u003e\n \u003cdiv class=\"ocli-exit-code__details\"\u003e\n \u003cdiv class=\"ocli-exit-code__status\"\u003eBAD_USER_INPUT_ERROR\u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code__summary\"\u003eMissing or invalid input\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\u003csection class=\"ocli-section\" id=\"ocli-check\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cdiv class=\"ocli-section__cmd-anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-check\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-section__cmd\"\u003e$ ocli check \u0026lt;arguments\u0026gt; [flags]\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body ocli-section__body--two-col\"\u003e\n \u003cdiv class=\"ocli-section__col-left\"\u003e\n \n\u003cp class=\"ocli-summary\"\u003eCheck an OpenCLI Spec document for errors\u003c/p\u003e\n\u003cdiv class=\"ocli-md\"\u003e\u003cp\u003eThe \u003ccode\u003echeck\u003c/code\u003e command will validate an OpenCLI Spec document and return any\nerrors that are found.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eArguments\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-check-arg-path-to-spec\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-check-arg-path-to-spec\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e\u0026lt;path-to-spec\u0026gt;\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe path to the OpenCLI Spec document to check\u003c/p\u003e\n\u003c/p\u003e\u003cdiv class=\"ocli-param__desc ocli-md\"\u003e\u003cp\u003ethis command will check the validity of the given OpenCLI document\nby parsing it and checking it against the OpenCLI Specification.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e[!TIP]\nThe format of the input file will be determined by the file extension.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eFlags\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-check-flag-fail-on-err\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-check-flag-fail-on-err\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--fail-on-err\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003eboolean\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--default\"\u003edefault: true\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eReturn a non-zero exit code if validation fails\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__col-right\"\u003e\n \n\u003cdiv class=\"ocli-examples\"\u003e\n \u003cdiv class=\"ocli-examples__heading\"\u003eExamples\u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003eValidate a spec document\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli check ./examples/petstore-cli.ocs.yaml\n# ✓ Checking ./examples/petstore-cli.ocs.yaml\n# Format: yaml\n# ✓ Document is valid\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\u003csection class=\"ocli-section\" id=\"ocli-gen\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cdiv class=\"ocli-section__cmd-anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-section__cmd\"\u003e$ ocli gen {command} \u0026lt;arguments\u0026gt; [flags]\u003c/code\u003e\u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--group\"\u003egrouping\u003c/span\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body\"\u003e\n \n\u003cp class=\"ocli-summary\"\u003eCollection of commands used to generate code/docs from an OpenCLI Spec document\u003c/p\u003e\n\n \u003c/div\u003e\n\u003c/section\u003e\n\u003csection class=\"ocli-section\" id=\"ocli-gen-docs\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cdiv class=\"ocli-section__cmd-anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-section__cmd\"\u003e$ ocli gen docs \u0026lt;arguments\u0026gt; [flags]\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body ocli-section__body--two-col\"\u003e\n \u003cdiv class=\"ocli-section__col-left\"\u003e\n \n\u003cp class=\"ocli-summary\"\u003eGenerate documentation\u003c/p\u003e\n\u003cdiv class=\"ocli-md\"\u003e\u003cp\u003eThe \u003ccode\u003eocli gen docs\u003c/code\u003e command will generate documentation from an OpenCLI\nSpec document. You can specify the format of the documentation to be\ngenerated using the \u003ccode\u003e--format\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eArguments\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-arg-path-to-spec\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-arg-path-to-spec\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e\u0026lt;path-to-spec\u0026gt;\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003ePath to the OpenCLI Spec document\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eFlags\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-flag-format\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-flag-format\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--format\u003c/code\u003e\u003ccode class=\"ocli-param__name\"\u003e-f\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--default\"\u003eenum\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe format of the documentation to generate\u003c/p\u003e\n\u003c/p\u003e\n \u003cdiv class=\"ocli-choices\"\u003e\n \u003cdiv class=\"ocli-choices__label\"\u003eAccepted values\u003c/div\u003e\n \u003cul class=\"ocli-choices__list\"\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003emarkdown\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003ePlain text using standard \u003ca href=\"https://commonmark.org\"\u003eMarkdown\u003c/a\u003e.\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003ehtml-page\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003eFull standalone HTML document\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003ehtml-embed\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003eAn embeddable js bundle including CSS and HTML\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003eman\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Man_page\"\u003eMan Page\u003c/a\u003e using standard groff\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-alt-sources\"\u003e\n \u003cdiv class=\"ocli-alt-sources__label\"\u003eAlternative sources\u003c/div\u003e\n \u003cul class=\"ocli-alt-sources__list\"\u003e\n \u003cli class=\"ocli-alt-sources__item\"\u003e\n \u003ccode\u003eenv: $OCLI_DOCS_FORMAT\u003c/code\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-alt-sources__item\"\u003e\n \u003ccode\u003efile: $.docs.format\u003c/code\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-flag-out\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-flag-out\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--out\u003c/code\u003e\u003ccode class=\"ocli-param__name\"\u003e-o\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--default\"\u003edefault: ./docs\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe path to the directory where the generated docs will be written\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-flag-no-footer\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-flag-no-footer\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--no-footer\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003eboolean\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eDo not include the footer in the docs\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-flag-no-badge\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-flag-no-badge\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--no-badge\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003eboolean\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eDo not include the OpenCLI badge\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__col-right\"\u003e\n \n\u003cdiv class=\"ocli-examples\"\u003e\n \u003cdiv class=\"ocli-examples__heading\"\u003eExamples\u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003egenerate markdown docs\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli gen docs -f markdown ./my-cli.ocs.yaml\n# → Reading spec: ./my-cli.ocs.yaml\n# → Generating docs: format=markdown, output=./docs\n# ✓ Documentation written to: docs/my-cli.ocs.md\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\u003csection class=\"ocli-section\" id=\"ocli-gen-cli\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cdiv class=\"ocli-section__cmd-anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-cli\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-section__cmd\"\u003e$ ocli gen cli \u0026lt;arguments\u0026gt; [flags]\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body ocli-section__body--two-col\"\u003e\n \u003cdiv class=\"ocli-section__col-left\"\u003e\n \n\u003cp class=\"ocli-summary\"\u003eGenerate CLI Boilerplate code\u003c/p\u003e\n\u003cdiv class=\"ocli-md\"\u003e\u003cp\u003eThe \u003ccode\u003eocli gen cli\u003c/code\u003e command will generate the boilerplate code for\nvarious CLI frameworks from an OpenCLI Spec document.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eArguments\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-cli-arg-path-to-spec\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-cli-arg-path-to-spec\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e\u0026lt;path-to-spec\u0026gt;\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe spec used to generate the code\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eFlags\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-cli-flag-out\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-cli-flag-out\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--out\u003c/code\u003e\u003ccode class=\"ocli-param__name\"\u003e-o\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe path to the directory where the generated code will be output\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-cli-flag-framework\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-cli-flag-framework\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--framework\u003c/code\u003e\u003ccode class=\"ocli-param__name\"\u003e-f\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--default\"\u003eenum\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe framework of the CLI boilerplate to generate\u003c/p\u003e\n\u003c/p\u003e\n \u003cdiv class=\"ocli-choices\"\u003e\n \u003cdiv class=\"ocli-choices__label\"\u003eAccepted values\u003c/div\u003e\n \u003cul class=\"ocli-choices__list\"\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003ecobra\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003e\u003ca href=\"https://github.com/spf13/cobra?tab=readme-ov-file\"\u003eCobra\u003c/a\u003e a powerful, battle-tested CLI framework for Go\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003eurfavecli\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003e\u003ca href=\"https://github.com/urfave/cli\"\u003eurfave/cli\u003c/a\u003e is a declarative, simple, fast, and fun package for building command line tools in Go\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003eyargs\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003e\u003ca href=\"https://yargs.js.org\"\u003eyargs\u003c/a\u003e be a node.js library fer hearties tryin' ter parse optstrings\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-alt-sources\"\u003e\n \u003cdiv class=\"ocli-alt-sources__label\"\u003eAlternative sources\u003c/div\u003e\n \u003cul class=\"ocli-alt-sources__list\"\u003e\n \u003cli class=\"ocli-alt-sources__item\"\u003e\n \u003ccode\u003eenv: $OCLI_CLI_FRAMEWORK\u003c/code\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-alt-sources__item\"\u003e\n \u003ccode\u003efile: $.cli.framework\u003c/code\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__col-right\"\u003e\n \n\u003cdiv class=\"ocli-examples\"\u003e\n \u003cdiv class=\"ocli-examples__heading\"\u003eExamples\u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003egenerate Cobra (Go) CLI\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli gen cli \\\n --framework cobra \\\n --out ./internal \\\n ./my-cli.ocs.yaml\n# → Reading spec: ./my-cli.ocs.yaml\n# → Generating CLI code: framework=cobra, output=./internal\n# ✓ CLI Code written to: ./internal\n\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003egenerate urfave/cli (Go) CLI\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli gen cli \\\n --framework urfavecli \\\n --out ./internal \\\n ./my-cli.ocs.yaml\n# → Reading spec: ./my-cli.ocs.yaml\n# → Generating CLI code: framework=urfavecli, output=./internal\n# ✓ CLI Code written to: ./internal\n\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003egenerate Yargs (Node.JS) CLI\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli gen cli \\\n --framework yargs \\\n --out ./src \\\n ./my-cli.ocs.yaml\n# → Reading spec: ./my-cli.ocs.yaml\n# → Generating CLI code: framework=yargs, output=./src\n# ✓ CLI Code written to: ./src\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\n \u003cfooter class=\"ocli-footer\"\u003e\n generated by \u003ca href=\"https://opencli.dev\"\u003eOpenCLI\u003c/a\u003e\n \u003c/footer\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n"; + var EMBED_MARKUP = "\n\n\u003cstyle\u003e\n \n\n \n.ocli[data-theme=\"light\"] {\n --ocli-bg: #ffffff;\n --ocli-bg-sidebar: #f7f9fc;\n --ocli-bg-code: #eef1f6;\n --ocli-bg-hover: #eef2f8;\n --ocli-border: #dde3ec;\n --ocli-border-light: #edf0f5;\n --ocli-text: #3a4a5c;\n --ocli-text-muted: #7a8aa0;\n --ocli-text-active: #0d1f2d;\n --ocli-accent: #5469d4;\n --ocli-accent-soft: #eef0fb;\n --ocli-badge-bg: #e8edf8;\n --ocli-badge-text: #3d5caa;\n --ocli-required-bg: #fef2f2;\n --ocli-required-text:#c0392b;\n --ocli-group-bg: #f0f4f8;\n --ocli-group-text: #5a6a7e;\n --ocli-sticky-shadow:0 2px 8px rgba(0,0,0,0.06);\n}\n\n.ocli[data-theme=\"dark\"] {\n --ocli-bg: #2e3440;\n --ocli-bg-sidebar: #262c38;\n --ocli-bg-code: #3b4252;\n --ocli-bg-hover: #353d4f;\n --ocli-border: #4c566a;\n --ocli-border-light: #3e4759;\n --ocli-text: #c8d3e6;\n --ocli-text-muted: #7b8fa8;\n --ocli-text-active: #eceff4;\n --ocli-accent: #81a1c1;\n --ocli-accent-soft: #2d3b4f;\n --ocli-badge-bg: #2c3d55;\n --ocli-badge-text: #88c0d0;\n --ocli-required-bg: #3a2020;\n --ocli-required-text:#f08080;\n --ocli-group-bg: #3b4252;\n --ocli-group-text: #8a9ab5;\n --ocli-sticky-shadow:0 2px 8px rgba(0,0,0,0.25);\n}\n\n \n.ocli, .ocli *, .ocli *::before, .ocli *::after {\n box-sizing: border-box;\n}\n\n.ocli {\n background: var(--ocli-bg);\n color: var(--ocli-text);\n display: flex;\n flex-direction: row;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen,\n Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif;\n font-size: 15px;\n line-height: 1.6;\n height: 100%;\n min-width: 0;\n}\n\n \n.ocli__sidebar {\n background: var(--ocli-bg-sidebar);\n border-right: 1px solid var(--ocli-border);\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n height: 100vh;\n overflow-y: auto;\n position: sticky;\n top: 0;\n width: 260px;\n}\n\n.ocli__sidebar::-webkit-scrollbar { width: 4px; }\n.ocli__sidebar::-webkit-scrollbar-thumb { background: var(--ocli-border); border-radius: 2px; }\n\n.ocli__sidebar-header {\n align-items: stretch;\n border-bottom: 1px solid var(--ocli-border);\n display: flex;\n flex-direction: column;\n gap: 6px;\n justify-content: center;\n min-height: 60px;\n padding: 12px 16px;\n}\n\n.ocli__sidebar-header-top {\n align-items: center;\n display: flex;\n gap: 10px;\n justify-content: space-between;\n}\n\n.ocli__sidebar-title {\n color: var(--ocli-text-active);\n font-size: 15px;\n font-weight: 700;\n line-height: 1.3;\n}\n\n.ocli__sidebar-version {\n color: var(--ocli-text-muted);\n font-size: 11px;\n font-weight: 500;\n}\n\n.ocli-theme-toggle {\n align-items: center;\n background: var(--ocli-bg-hover);\n border: 1px solid var(--ocli-border);\n border-radius: 999px;\n color: var(--ocli-text-muted);\n cursor: pointer;\n display: inline-flex;\n flex-shrink: 0;\n height: 28px;\n justify-content: flex-start;\n padding: 3px;\n transition: background 0.2s ease, border-color 0.2s ease;\n width: 52px;\n}\n\n.ocli-theme-toggle:hover {\n border-color: var(--ocli-accent);\n}\n\n.ocli-theme-toggle:focus-visible {\n outline: 2px solid var(--ocli-accent);\n outline-offset: 2px;\n}\n\n.ocli-theme-toggle__thumb {\n align-items: center;\n background: var(--ocli-bg);\n border-radius: 999px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.25);\n display: inline-flex;\n height: 20px;\n justify-content: center;\n position: relative;\n transform: translateX(0);\n transition: transform 0.2s ease, background 0.2s ease;\n width: 20px;\n}\n\n.ocli-theme-toggle__icon {\n fill: none;\n height: 12px;\n left: 50%;\n position: absolute;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n top: 50%;\n transform: translate(-50%, -50%);\n transition: opacity 0.15s ease;\n width: 12px;\n}\n\n.ocli-theme-toggle__icon--sun {\n opacity: 1;\n}\n\n.ocli-theme-toggle__icon--moon {\n opacity: 0;\n}\n\n.ocli[data-theme=\"light\"] .ocli-theme-toggle {\n background: #d9dee7;\n}\n\n.ocli[data-theme=\"light\"] .ocli-theme-toggle__thumb {\n background: #ffffff;\n color: #d59a22;\n}\n\n.ocli[data-theme=\"dark\"] .ocli-theme-toggle {\n background: #5d6577;\n}\n\n.ocli[data-theme=\"dark\"] .ocli-theme-toggle__thumb {\n background: #1f2531;\n color: #d6dded;\n transform: translateX(24px);\n}\n\n.ocli[data-theme=\"dark\"] .ocli-theme-toggle__icon--sun {\n opacity: 0;\n}\n\n.ocli[data-theme=\"dark\"] .ocli-theme-toggle__icon--moon {\n opacity: 1;\n}\n\n.ocli__sidebar-body {\n flex: 1;\n overflow-y: auto;\n padding: 12px 0 24px;\n}\n\n.ocli__nav-section {\n margin: 16px 0 4px;\n padding: 0 16px;\n}\n\n.ocli__nav-section-label {\n color: var(--ocli-text-muted);\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.08em;\n padding: 4px 0;\n text-transform: uppercase;\n}\n\n.ocli__nav-list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.ocli__nav-list--nested {\n border-left: 2px solid var(--ocli-border-light);\n margin-left: 10px;\n padding-left: 8px;\n}\n\n.ocli__nav-item {\n margin: 0;\n padding: 0;\n}\n\n.ocli__nav-link {\n align-items: center;\n border-radius: 5px;\n color: var(--ocli-text);\n cursor: pointer;\n display: flex;\n font-size: 13px;\n gap: 4px;\n justify-content: space-between;\n padding: 5px 8px;\n text-decoration: none;\n transition: background 0.1s, color 0.1s;\n}\n\n.ocli__nav-link:hover {\n background: var(--ocli-bg-hover);\n color: var(--ocli-text-active);\n}\n\n.ocli__nav-link.is-active {\n background: var(--ocli-accent-soft);\n color: var(--ocli-accent);\n font-weight: 600;\n}\n\n.ocli__nav-link .ocli__nav-toggle {\n display: inline-block;\n font-size: 10px;\n opacity: 0.6;\n transition: transform 0.15s;\n}\n\n.ocli__nav-item.is-open \u003e .ocli__nav-link .ocli__nav-toggle {\n transform: rotate(90deg);\n}\n\n.ocli__nav-sublist {\n display: none;\n list-style: none;\n margin: 2px 0 4px 12px;\n padding: 0;\n}\n\n.ocli__nav-item.is-open \u003e .ocli__nav-sublist {\n display: block;\n}\n\n \n.ocli__main {\n flex: 1;\n height: 100%;\n min-width: 0;\n overflow-y: auto;\n}\n\n.ocli__main::-webkit-scrollbar { width: 6px; }\n.ocli__main::-webkit-scrollbar-thumb { background: var(--ocli-border); border-radius: 3px; }\n\n \n.ocli-section {\n border-bottom: 1px solid var(--ocli-border);\n}\n\n.ocli-section__sticky {\n align-items: center;\n background: var(--ocli-bg);\n border-bottom: 1px solid transparent;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n min-height: 60px;\n padding: 0 24px;\n position: sticky;\n top: -1px;\n transition: border-color 0.15s, box-shadow 0.15s;\n z-index: 10;\n}\n\n.ocli-section__sticky.is-stuck {\n border-bottom-color: var(--ocli-border);\n box-shadow: var(--ocli-sticky-shadow);\n}\n\n.ocli-section__sticky-title {\n color: var(--ocli-text-active);\n font-size: 16px;\n font-weight: 600;\n}\n\n.ocli-section__cmd {\n background: var(--ocli-bg-code);\n border-radius: 5px;\n color: var(--ocli-text-active);\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 14px;\n font-weight: 600;\n padding: 3px 8px;\n margin-left: 6px;\n}\n\n.ocli-section__body {\n padding: 0px 24px 28px 30px;\n}\n\n.ocli-section__intro-grid {\n display: grid;\n gap: 24px;\n grid-template-columns: 1fr 1fr;\n padding: 20px 24px 28px;\n}\n\n@media (max-width: 720px) {\n .ocli-section__intro-grid {\n grid-template-columns: 1fr;\n }\n}\n\n \n.ocli-section__body--two-col {\n display: grid;\n gap: 32px;\n grid-template-columns: 1fr 1fr;\n padding: 20px 24px 28px;\n}\n\n@media (max-width: 720px) {\n .ocli-section__body--two-col {\n grid-template-columns: 1fr;\n }\n}\n\n.ocli-section__col-left {\n min-width: 0;\n}\n\n.ocli-section__col-right {\n align-self: start;\n position: sticky;\n top: 80px;\n max-height: calc(100vh - 100px);\n overflow-y: auto;\n}\n\n \n.ocli-examples {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.ocli-examples__heading {\n color: var(--ocli-text-active);\n font-size: 14px;\n font-weight: 700;\n letter-spacing: 0.04em;\n margin: 0 0 4px;\n text-transform: uppercase;\n}\n\n.ocli-example {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.ocli-example__title {\n color: var(--ocli-text);\n font-size: 13px;\n font-weight: 600;\n line-height: 1.4;\n}\n\n \n.ocli-badges {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n gap: 5px;\n}\n\n.ocli-badge {\n border-radius: 4px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n padding: 2px 7px;\n}\n\n.ocli-badge--default {\n background: var(--ocli-badge-bg);\n color: var(--ocli-badge-text);\n}\n\n.ocli-badge--group {\n background: var(--ocli-group-bg);\n color: var(--ocli-group-text);\n}\n\n.ocli-badge--required {\n background: var(--ocli-required-bg);\n color: var(--ocli-required-text);\n}\n\n \n.ocli-section__body h2, .ocli-section__intro-grid h2 {\n color: var(--ocli-text-active);\n font-size: 14px;\n font-weight: 700;\n margin: 0 0 8px;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.ocli-summary {\n color: var(--ocli-text-active);\n font-size: 15px;\n font-weight: 500;\n margin-bottom: 12px;\n}\n\n \n.ocli-md p {\n color: var(--ocli-text);\n line-height: 1.7;\n margin: 0 0 12px;\n}\n.ocli-md p:last-child { margin-bottom: 0; }\n.ocli-md a { color: var(--ocli-accent); text-decoration: none; }\n.ocli-md a:hover { text-decoration: underline; }\n.ocli-md strong { color: var(--ocli-text-active); font-weight: 600; }\n.ocli-md em { font-style: italic; }\n.ocli-md ul, .ocli-md ol { margin: 8px 0 12px 20px; }\n.ocli-md li { margin: 4px 0; }\n.ocli-md code {\n background: var(--ocli-bg-code);\n border-radius: 4px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 0.875em;\n padding: 2px 5px;\n}\n.ocli-md pre {\n background: var(--ocli-bg-code);\n border-radius: 6px;\n margin: 12px 0;\n overflow-x: auto;\n padding: 14px 16px;\n}\n.ocli-md pre code {\n background: none;\n font-size: 13px;\n padding: 0;\n}\n.ocli-md h1, .ocli-md h2, .ocli-md h3 {\n color: var(--ocli-text-active);\n font-weight: 600;\n margin: 16px 0 8px;\n}\n\n \n.ocli-meta-box {\n margin-bottom: 16px;\n}\n\n.ocli-meta-box__label {\n color: var(--ocli-text-muted);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.07em;\n margin-bottom: 6px;\n text-transform: uppercase;\n}\n\n.ocli-meta-box__value {\n color: var(--ocli-text);\n font-size: 14px;\n}\n\n.ocli-meta-box__value a {\n color: var(--ocli-accent);\n text-decoration: none;\n}\n\n.ocli-meta-box__value a:hover { text-decoration: underline; }\n\n \n.ocli-tabs__tablist {\n border-bottom: 1px solid var(--ocli-border);\n display: flex;\n flex-wrap: wrap;\n gap: 0;\n margin-bottom: 20px;\n}\n\n.ocli-tabs__tab {\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n color: var(--ocli-text-muted);\n cursor: pointer;\n font-family: inherit;\n font-size: 14px;\n font-weight: 500;\n margin-bottom: -1px;\n padding: 10px 16px;\n transition: color 0.15s, border-color 0.15s;\n}\n\n.ocli-tabs__tab:hover {\n color: var(--ocli-text-active);\n}\n\n.ocli-tabs__tab.is-active {\n border-bottom-color: var(--ocli-accent);\n color: var(--ocli-accent);\n}\n\n.ocli-tabs__panel {\n display: none;\n}\n\n.ocli-tabs__panel.is-active {\n display: block;\n}\n\n.ocli-tabs__panel-desc {\n color: var(--ocli-text);\n font-size: 14px;\n margin: 0 0 12px;\n}\n\n.ocli-tabs__panel-url {\n font-size: 14px;\n margin-top: 10px;\n}\n\n.ocli-tabs__panel-url a {\n color: var(--ocli-accent);\n}\n\n \n.ocli-code-block {\n background: var(--ocli-bg-code);\n border-radius: 6px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 13px;\n line-height: 1.6;\n overflow-x: auto;\n padding: 12px 14px;\n}\n\n \n.ocli-code-block--terminal {\n background: none;\n border: 1px solid var(--ocli-border);\n border-radius: 8px;\n overflow: hidden;\n padding: 0;\n}\n\n.ocli-code-block__header {\n align-items: center;\n background: #1a2133;\n border-bottom: 1px solid rgba(255,255,255,0.08);\n display: flex;\n padding: 8px 14px;\n}\n\n.ocli-code-block__label {\n color: rgba(255,255,255,0.55);\n font-size: 12px;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.ocli-code-block__body {\n background: #1e2d45;\n color: #a8d8f0;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 13px;\n line-height: 1.6;\n margin: 0;\n overflow-x: auto;\n padding: 16px 18px;\n white-space: pre;\n}\n\n \n\n.ocli-table-container {\n border: 1px solid var(--ocli-border);\n border-radius: 8px;\n overflow: hidden;\n display: inline-block;\n width: 100%;\n}\n\n.ocli-table {\n border-collapse: collapse;\n font-size: 14px;\n width: 100%;\n}\n\n.ocli-table th {\n background: var(--ocli-bg-sidebar);\n border: 1px solid var(--ocli-border);\n color: var(--ocli-text-muted);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.05em;\n padding: 8px 12px;\n text-align: left;\n text-transform: uppercase;\n}\n\n.ocli-table td {\n border: 1px solid var(--ocli-border);\n padding: 8px 12px;\n color: var(--ocli-text);\n}\n\n.ocli-table tr:first-child th { border-top: none; }\n.ocli-table tr:last-child td { border-bottom: none; }\n.ocli-table tr td:first-child, tr th:first-child { border-left: none; }\n.ocli-table tr td:last-child, tr th:last-child { border-right: none; }\n\n.ocli-table code {\n background: var(--ocli-bg-code);\n border-radius: 3px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 0.875em;\n padding: 1px 4px;\n}\n\n \n.ocli-exit-code {\n align-items: flex-start;\n border-bottom: 1px solid var(--ocli-border-light);\n display: flex;\n gap: 12px;\n padding: 12px 0;\n}\n\n.ocli-exit-code:last-child { border-bottom: none; }\n\n.ocli-exit-code__code {\n background: var(--ocli-bg-code);\n border-radius: 4px;\n color: var(--ocli-text-active);\n flex-shrink: 0;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 13px;\n font-weight: 600;\n min-width: 28px;\n padding: 2px 7px;\n text-align: center;\n}\n\n.ocli-exit-code__details {}\n\n.ocli-exit-code__status {\n background: var(--ocli-badge-bg);\n border-radius: 4px;\n color: var(--ocli-badge-text);\n display: inline-block;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 11px;\n font-weight: 600;\n margin-bottom: 4px;\n padding: 2px 6px;\n}\n\n.ocli-exit-code__summary {\n color: var(--ocli-text);\n font-size: 14px;\n}\n\n.ocli-exit-code__desc {\n color: var(--ocli-text-muted);\n font-size: 13px;\n margin-top: 4px;\n}\n\n \n.ocli-params {\n margin-top: 24px;\n}\n\n.ocli-params__heading {\n border-bottom: 1px solid var(--ocli-border);\n color: var(--ocli-text-muted);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.07em;\n margin-bottom: 4px;\n padding-bottom: 8px;\n text-transform: uppercase;\n}\n\n.ocli-param {\n border-bottom: 1px solid var(--ocli-border-light);\n padding: 14px 0;\n scroll-margin-top: 60px;\n}\n\n.ocli-param:last-child { border-bottom: none; }\n\n.ocli-param__header {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 6px;\n}\n\n.ocli-param__name {\n color: var(--ocli-text-active);\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 13px;\n font-weight: 600;\n padding: 2px 7px 2px 4px;\n}\n\n \n.ocli-param__anchor,\n.ocli-section__cmd-anchor {\n align-items: center;\n color: inherit;\n display: inline-flex;\n gap: 6px;\n position: relative;\n}\n\n.ocli-deeplink-btn {\n background: none;\n border: none;\n cursor: pointer;\n left: -20px;\n padding: 0 6px;\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n}\n\n.ocli-deeplink-icon {\n color: var(--ocli-accent);\n display: block;\n opacity: 0;\n transition: opacity 0.15s;\n}\n\n.ocli-param__anchor:hover .ocli-deeplink-icon,\n.ocli-section__cmd-anchor:hover .ocli-deeplink-icon {\n opacity: 1;\n}\n\n.ocli-param__summary {\n color: var(--ocli-text);\n font-size: 14px;\n margin-bottom: 4px;\n}\n\n.ocli-param__desc {\n color: var(--ocli-text);\n font-size: 14px;\n margin-top: 6px;\n}\n\n.ocli-param__desc p { margin: 0 0 4px; }\n\n \n.ocli-choices {\n margin-top: 10px;\n}\n\n.ocli-choices__label {\n color: var(--ocli-text-muted);\n font-size: 12px;\n font-weight: 600;\n margin-bottom: 6px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.ocli-choices__list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.ocli-choices__item {\n align-items: baseline;\n display: flex;\n font-size: 13px;\n gap: 8px;\n padding: 3px 0;\n}\n\n.ocli-choices__item code {\n background: var(--ocli-bg-code);\n border-radius: 3px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n flex-shrink: 0;\n padding: 1px 5px;\n}\n\n.ocli-choices__item-desc { color: var(--ocli-text-muted); }\n\n \n.ocli-alt-sources {\n margin-top: 10px;\n}\n\n.ocli-alt-sources__label {\n color: var(--ocli-text-muted);\n font-size: 12px;\n font-weight: 600;\n margin-bottom: 6px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.ocli-alt-sources__list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.ocli-alt-sources__item {\n font-size: 13px;\n padding: 2px 0;\n}\n\n.ocli-alt-sources__item code {\n background: var(--ocli-bg-code);\n border-radius: 3px;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n padding: 1px 5px;\n}\n\n \n.ocli-section__body a {\n color: var(--ocli-accent);\n text-decoration: none;\n}\n\n.ocli-section__body a:hover {\n text-decoration: underline;\n}\n\n \n.ocli-footer {\n color: var(--ocli-text-muted);\n font-size: 12px;\n padding: 24px;\n text-align: center;\n}\n\n.ocli-footer a { color: var(--ocli-accent); text-decoration: none; }\n.ocli-footer a:hover { text-decoration: underline; }\n\n \n@media (max-width: 900px) {\n .ocli__sidebar {\n display: none;\n }\n}\n\u003c/style\u003e\n\n\n\u003cdiv class=\"ocli\" data-theme=\"light\"\u003e\n \n\u003cnav class=\"ocli__sidebar\" aria-label=\"Navigation\"\u003e\n \u003cdiv class=\"ocli__sidebar-header\"\u003e\n \u003cdiv class=\"ocli__sidebar-header-top\"\u003e\n \u003cspan class=\"ocli__sidebar-title\"\u003eOpenCLI\u003c/span\u003e\n \u003cbutton\n class=\"ocli-theme-toggle\"\n type=\"button\"\n data-theme-toggle\n aria-label=\"Switch to dark theme\"\n aria-pressed=\"false\"\n \u003e\n \u003cspan class=\"ocli-theme-toggle__thumb\" aria-hidden=\"true\"\u003e\n \u003csvg class=\"ocli-theme-toggle__icon ocli-theme-toggle__icon--sun\" viewBox=\"0 0 24 24\" focusable=\"false\"\u003e\n \u003ccircle cx=\"12\" cy=\"12\" r=\"4\"\u003e\u003c/circle\u003e\n \u003cpath d=\"M12 2v2.2M12 19.8V22M4.9 4.9l1.6 1.6M17.5 17.5l1.6 1.6M2 12h2.2M19.8 12H22M4.9 19.1l1.6-1.6M17.5 6.5l1.6-1.6\"\u003e\u003c/path\u003e\n \u003c/svg\u003e\n \u003csvg class=\"ocli-theme-toggle__icon ocli-theme-toggle__icon--moon\" viewBox=\"0 0 24 24\" focusable=\"false\"\u003e\n \u003cpath d=\"M20.4 14.8A8.7 8.7 0 0 1 9.2 3.6a8.6 8.6 0 1 0 11.2 11.2z\"\u003e\u003c/path\u003e\n \u003c/svg\u003e\n \u003c/span\u003e\n \u003c/button\u003e\n \u003c/div\u003e\n \u003cspan class=\"ocli__sidebar-version\"\u003ev1.2.0\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli__sidebar-body\"\u003e\n \u003cdiv class=\"ocli__nav-section\"\u003e\n \u003cdiv class=\"ocli__nav-section-label\"\u003eOverview\u003c/div\u003e\n \u003cul class=\"ocli__nav-list\"\u003e\n \u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#intro\" data-section=\"intro\"\u003eIntroduction\u003c/a\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#install\" data-section=\"install\"\u003eInstallation\u003c/a\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#config\" data-section=\"config\"\u003eConfiguration\u003c/a\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#exit-codes\" data-section=\"exit-codes\"\u003eExit Codes\u003c/a\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli__nav-section\"\u003e\n \u003cdiv class=\"ocli__nav-section-label\"\u003eCommands\u003c/div\u003e\n \u003cul class=\"ocli__nav-list\"\u003e\n\u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#ocli-check\" data-section=\"ocli-check\"\u003e\n \u003cspan\u003echeck\u003c/span\u003e\n \u003c/a\u003e\n\u003c/li\u003e\n\n\u003cli class=\"ocli__nav-item ocli__nav-item--group\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#ocli-gen\" data-section=\"ocli-gen\"\u003e\n \u003cspan\u003egen\u003c/span\u003e\n \u003cspan class=\"ocli__nav-toggle\"\u003e▸\u003c/span\u003e\n \u003c/a\u003e\n \u003cul class=\"ocli__nav-sublist\"\u003e\n\u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#ocli-gen-docs\" data-section=\"ocli-gen-docs\"\u003e\n \u003cspan\u003edocs\u003c/span\u003e\n \u003c/a\u003e\n\u003c/li\u003e\n\n\u003cli class=\"ocli__nav-item\"\u003e\n \u003ca class=\"ocli__nav-link\" href=\"#ocli-gen-cli\" data-section=\"ocli-gen-cli\"\u003e\n \u003cspan\u003ecli\u003c/span\u003e\n \u003c/a\u003e\n\u003c/li\u003e\n\n \u003c/ul\u003e\n\u003c/li\u003e\n\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/nav\u003e\n\n \u003cdiv class=\"ocli__main\"\u003e\n \n\u003csection class=\"ocli-section\" id=\"intro\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cspan class=\"ocli-section__sticky-title\"\u003eIntroduction\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__intro-grid\"\u003e\n \u003cdiv class=\"ocli-section__intro-left\"\u003e\n \u003cimg src=\"https://img.shields.io/badge/OpenCLI_Spec-Compliant-brightgreen?link=https%3A%2F%2Fgithub.com%2Fbcdxn%2Fopencli\"/\u003e\n \u003cp class=\"ocli-summary\"\u003eA CLI for working with OpenCLI Specs\u003c/p\u003e\n \u003cdiv class=\"ocli-md\"\u003e\u003cp\u003e\u003ccode\u003eocli\u003c/code\u003e is a command line interface designed to make working with \u003ca href=\"https://github.com/bcdxn/opencli/tree/main\"\u003eOpenCLI\nSpec documents\u003c/a\u003e easier. It provides a number of capabilities, including:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003evalidating OpenCLI Spec documents\u003c/li\u003e\n\u003cli\u003egenerating Documentation from OpenCLI Spec documents\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe commands are documented below. You can also find out more about each\ncommand using the contextual \u003ccode\u003e--help\u003c/code\u003e flag. e.g.:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003eocli gen --help\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__intro-right\"\u003e\n \u003cdiv class=\"ocli-meta-box\"\u003e\n \u003cdiv class=\"ocli-meta-box__label\"\u003eLicense\u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box__value\"\u003e\n \u003ca href=\"https://spdx.org/licenses/MIT.html\"\u003eMIT\u003c/a\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box\"\u003e\n \u003cdiv class=\"ocli-meta-box__label\"\u003eContact\u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box__value\"\u003e\u003cdiv\u003eOpenCLI Team\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://github.com/bcdxn/opencli\"\u003ehttps://github.com/bcdxn/opencli\u003c/a\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box\"\u003e\n \u003cdiv class=\"ocli-meta-box__label\"\u003eBinary\u003c/div\u003e\n \u003cdiv class=\"ocli-meta-box__value\"\u003e\u003ccode style=\"font-family:monospace;background:var(--ocli-bg-code);padding:2px 6px;border-radius:4px;\"\u003eocli\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\u003csection class=\"ocli-section\" id=\"install\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cspan class=\"ocli-section__sticky-title\"\u003eInstallation\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body\"\u003e\n \u003cdiv class=\"ocli-tabs\"\u003e\n \u003cdiv class=\"ocli-tabs__tablist\" role=\"tablist\"\u003e\n \u003cbutton class=\"ocli-tabs__tab is-active\"\n role=\"tab\"\n aria-selected=\"true\"\n aria-controls=\"install-panel-0\"\n data-tab=\"install-panel-0\"\u003eBinary Download\u003c/button\u003e\n \u003cbutton class=\"ocli-tabs__tab\"\n role=\"tab\"\n aria-selected=\"false\"\n aria-controls=\"install-panel-1\"\n data-tab=\"install-panel-1\"\u003eGo Install\u003c/button\u003e\n \u003cbutton class=\"ocli-tabs__tab\"\n role=\"tab\"\n aria-selected=\"false\"\n aria-controls=\"install-panel-2\"\n data-tab=\"install-panel-2\"\u003eHomebrew\u003c/button\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-tabs__panel is-active\"\n id=\"install-panel-0\"\n role=\"tabpanel\"\u003e\n \u003cp class=\"ocli-tabs__panel-desc\"\u003eYou can visit the GitHub releases page of the project to download pre-compiled binaries\nappropriate for your system.\n\u003c/p\u003e\n \u003cdiv class=\"ocli-tabs__panel-url\"\u003e\u003ca href=\"https://github.com/bcdxn/opencli/releases\"\u003ehttps://github.com/bcdxn/opencli/releases\u003c/a\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-tabs__panel\"\n id=\"install-panel-1\"\n role=\"tabpanel\"\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eCommand Line\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003ego install github.com/bcdxn/opencli/cmd/ocli@latest\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-tabs__panel\"\n id=\"install-panel-2\"\n role=\"tabpanel\"\u003e\n \u003cp class=\"ocli-tabs__panel-desc\"\u003eInstall the openclidev tap\n```\nbrew tap openclidev/tap\n```\n\nTrust the tap\n```\nbrew trust openclidev/tap\n```\n\nNow you\u0026#39;re ready to install `ocli` using homebrew\n\u003c/p\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eCommand Line\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003ebrew install ocli\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n \n\u003csection class=\"ocli-section\" id=\"config\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cspan class=\"ocli-section__sticky-title\"\u003eConfiguration\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body\"\u003e\n \u003cdiv class=\"ocli-table-container\"\u003e\n \u003ctable class=\"ocli-table\"\u003e\n \u003cthead\u003e\n \u003ctr\u003e\n \u003cth\u003eFormat\u003c/th\u003e\n \u003cth\u003ePath\u003c/th\u003e\n \u003c/tr\u003e\n \u003c/thead\u003e\n \u003ctbody\u003e\n \u003ctr\u003e\u003ctd\u003eYAML\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e~/.ocli/config.yaml\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n \u003c/tbody\u003e\n \u003c/table\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n \n\u003csection class=\"ocli-section\" id=\"exit-codes\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cspan class=\"ocli-section__sticky-title\"\u003eExit Codes\u003c/span\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body\"\u003e\n \u003cdiv class=\"ocli-exit-code\"\u003e\n \u003cspan class=\"ocli-exit-code__code\"\u003e0\u003c/span\u003e\n \u003cdiv class=\"ocli-exit-code__details\"\u003e\n \u003cdiv class=\"ocli-exit-code__status\"\u003eOK\u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code__summary\"\u003eThe command was successful\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code\"\u003e\n \u003cspan class=\"ocli-exit-code__code\"\u003e1\u003c/span\u003e\n \u003cdiv class=\"ocli-exit-code__details\"\u003e\n \u003cdiv class=\"ocli-exit-code__status\"\u003eINTERNAL_CLI_ERROR\u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code__summary\"\u003eThe command failed\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code\"\u003e\n \u003cspan class=\"ocli-exit-code__code\"\u003e2\u003c/span\u003e\n \u003cdiv class=\"ocli-exit-code__details\"\u003e\n \u003cdiv class=\"ocli-exit-code__status\"\u003eBAD_USER_INPUT_ERROR\u003c/div\u003e\n \u003cdiv class=\"ocli-exit-code__summary\"\u003eMissing or invalid input\u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\u003csection class=\"ocli-section\" id=\"ocli-check\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cdiv class=\"ocli-section__cmd-anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-check\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-section__cmd\"\u003e$ ocli check \u0026lt;arguments\u0026gt; [flags]\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body ocli-section__body--two-col\"\u003e\n \u003cdiv class=\"ocli-section__col-left\"\u003e\n \n\u003cp class=\"ocli-summary\"\u003eCheck an OpenCLI Spec document for errors\u003c/p\u003e\n\u003cdiv class=\"ocli-md\"\u003e\u003cp\u003eThe \u003ccode\u003echeck\u003c/code\u003e command will validate an OpenCLI Spec document and return any\nerrors that are found.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eArguments\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-check-arg-path-to-spec\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-check-arg-path-to-spec\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e\u0026lt;path-to-spec\u0026gt;\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe path to the OpenCLI Spec document to check\u003c/p\u003e\n\u003c/p\u003e\u003cdiv class=\"ocli-param__desc ocli-md\"\u003e\u003cp\u003ethis command will check the validity of the given OpenCLI document\nby parsing it and checking it against the OpenCLI Specification.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e[!TIP]\nThe format of the input file will be determined by the file extension.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe path may also point to a CLI binary built with one of the OpenCLI\nadapters. In that case \u003ccode\u003eocli\u003c/code\u003e runs \u003ccode\u003e\u0026lt;binary\u0026gt; __opencli\u003c/code\u003e, falling back to\n\u003ccode\u003e\u0026lt;binary\u0026gt; docgen\u003c/code\u003e, and checks the document it emits.\u003c/p\u003e\n\u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eFlags\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-check-flag-fail-on-err\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-check-flag-fail-on-err\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--fail-on-err\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003eboolean\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--default\"\u003edefault: true\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eReturn a non-zero exit code if validation fails\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__col-right\"\u003e\n \n\u003cdiv class=\"ocli-examples\"\u003e\n \u003cdiv class=\"ocli-examples__heading\"\u003eExamples\u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003eValidate a spec document\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli check ./examples/petstore-cli.ocs.yaml\n# ✓ Checking ./examples/petstore-cli.ocs.yaml\n# Format: yaml\n# ✓ Document is valid\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\u003csection class=\"ocli-section\" id=\"ocli-gen\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cdiv class=\"ocli-section__cmd-anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-section__cmd\"\u003e$ ocli gen {command} \u0026lt;arguments\u0026gt; [flags]\u003c/code\u003e\u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--group\"\u003egrouping\u003c/span\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body\"\u003e\n \n\u003cp class=\"ocli-summary\"\u003eCollection of commands used to generate code/docs from an OpenCLI Spec document\u003c/p\u003e\n\n \u003c/div\u003e\n\u003c/section\u003e\n\u003csection class=\"ocli-section\" id=\"ocli-gen-docs\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cdiv class=\"ocli-section__cmd-anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-section__cmd\"\u003e$ ocli gen docs \u0026lt;arguments\u0026gt; [flags]\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body ocli-section__body--two-col\"\u003e\n \u003cdiv class=\"ocli-section__col-left\"\u003e\n \n\u003cp class=\"ocli-summary\"\u003eGenerate documentation\u003c/p\u003e\n\u003cdiv class=\"ocli-md\"\u003e\u003cp\u003eThe \u003ccode\u003eocli gen docs\u003c/code\u003e command will generate documentation from an OpenCLI\nSpec document. You can specify the format of the documentation to be\ngenerated using the \u003ccode\u003e--format\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eArguments\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-arg-path-to-spec\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-arg-path-to-spec\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e\u0026lt;path-to-spec\u0026gt;\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003ePath to the OpenCLI Spec document, or a CLI binary that emits one via \u003ccode\u003e__opencli\u003c/code\u003e or \u003ccode\u003edocgen\u003c/code\u003e\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eFlags\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-flag-format\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-flag-format\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--format\u003c/code\u003e\u003ccode class=\"ocli-param__name\"\u003e-f\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--default\"\u003eenum\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe format of the documentation to generate\u003c/p\u003e\n\u003c/p\u003e\n \u003cdiv class=\"ocli-choices\"\u003e\n \u003cdiv class=\"ocli-choices__label\"\u003eAccepted values\u003c/div\u003e\n \u003cul class=\"ocli-choices__list\"\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003emarkdown\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003ePlain text using standard \u003ca href=\"https://commonmark.org\"\u003eMarkdown\u003c/a\u003e.\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003ehtml-page\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003eFull standalone HTML document\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003ehtml-embed\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003eAn embeddable js bundle including CSS and HTML\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003eman\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Man_page\"\u003eMan Page\u003c/a\u003e using standard groff\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-alt-sources\"\u003e\n \u003cdiv class=\"ocli-alt-sources__label\"\u003eAlternative sources\u003c/div\u003e\n \u003cul class=\"ocli-alt-sources__list\"\u003e\n \u003cli class=\"ocli-alt-sources__item\"\u003e\n \u003ccode\u003eenv: $OCLI_DOCS_FORMAT\u003c/code\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-alt-sources__item\"\u003e\n \u003ccode\u003efile: $.docs.format\u003c/code\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-flag-out\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-flag-out\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--out\u003c/code\u003e\u003ccode class=\"ocli-param__name\"\u003e-o\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--default\"\u003edefault: ./docs\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe path to the directory where the generated docs will be written\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-flag-no-footer\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-flag-no-footer\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--no-footer\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003eboolean\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eDo not include the footer in the docs\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-docs-flag-no-badge\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-docs-flag-no-badge\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--no-badge\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003eboolean\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eDo not include the OpenCLI badge\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__col-right\"\u003e\n \n\u003cdiv class=\"ocli-examples\"\u003e\n \u003cdiv class=\"ocli-examples__heading\"\u003eExamples\u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003egenerate markdown docs\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli gen docs -f markdown ./my-cli.ocs.yaml\n# → Reading spec: ./my-cli.ocs.yaml\n# → Generating docs: format=markdown, output=./docs\n# ✓ Documentation written to: docs/my-cli.ocs.md\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\u003csection class=\"ocli-section\" id=\"ocli-gen-cli\"\u003e\n \u003cdiv class=\"ocli-section__sticky\"\u003e\n \u003cdiv class=\"ocli-section__cmd-anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-cli\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-section__cmd\"\u003e$ ocli gen cli \u0026lt;arguments\u0026gt; [flags]\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__body ocli-section__body--two-col\"\u003e\n \u003cdiv class=\"ocli-section__col-left\"\u003e\n \n\u003cp class=\"ocli-summary\"\u003eGenerate CLI Boilerplate code\u003c/p\u003e\n\u003cdiv class=\"ocli-md\"\u003e\u003cp\u003eThe \u003ccode\u003eocli gen cli\u003c/code\u003e command will generate the boilerplate code for\nvarious CLI frameworks from an OpenCLI Spec document.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eArguments\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-cli-arg-path-to-spec\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-cli-arg-path-to-spec\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e\u0026lt;path-to-spec\u0026gt;\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe spec used to generate the code, or a CLI binary that emits one via \u003ccode\u003e__opencli\u003c/code\u003e or \u003ccode\u003edocgen\u003c/code\u003e\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ocli-params\"\u003e\n \u003cdiv class=\"ocli-params__heading\"\u003eFlags\u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-cli-flag-out\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-cli-flag-out\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--out\u003c/code\u003e\u003ccode class=\"ocli-param__name\"\u003e-o\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe path to the directory where the generated code will be output\u003c/p\u003e\n\u003c/p\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-param\" id=\"ocli-gen-cli-flag-framework\"\u003e\n \u003cdiv class=\"ocli-param__header\"\u003e\n \u003cdiv class=\"ocli-param__anchor\"\u003e\u003cbutton class=\"ocli-deeplink-btn\" type=\"button\" data-href=\"#ocli-gen-cli-flag-framework\" aria-label=\"Copy link\"\u003e\u003csvg class=\"ocli-deeplink-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\u003cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/\u003e\u003cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/\u003e\u003c/svg\u003e\u003c/button\u003e\u003ccode class=\"ocli-param__name\"\u003e--framework\u003c/code\u003e\u003ccode class=\"ocli-param__name\"\u003e-f\u003c/code\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-badges\"\u003e\n \u003cspan class=\"ocli-badge ocli-badge--default\"\u003estring\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--default\"\u003eenum\u003c/span\u003e\u003cspan class=\"ocli-badge ocli-badge--required\"\u003erequired\u003c/span\u003e\n \u003c/div\u003e\u003cp class=\"ocli-param__summary\"\u003e\u003cp\u003eThe framework of the CLI boilerplate to generate\u003c/p\u003e\n\u003c/p\u003e\n \u003cdiv class=\"ocli-choices\"\u003e\n \u003cdiv class=\"ocli-choices__label\"\u003eAccepted values\u003c/div\u003e\n \u003cul class=\"ocli-choices__list\"\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003ecobra\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003e\u003ca href=\"https://github.com/spf13/cobra?tab=readme-ov-file\"\u003eCobra\u003c/a\u003e a powerful, battle-tested CLI framework for Go\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003eurfavecli\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003e\u003ca href=\"https://github.com/urfave/cli\"\u003eurfave/cli\u003c/a\u003e is a declarative, simple, fast, and fun package for building command line tools in Go\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-choices__item\"\u003e\n \u003ccode\u003eyargs\u003c/code\u003e\u003cspan class=\"ocli-choices__item-desc\"\u003e\u003cp\u003e\u003ca href=\"https://yargs.js.org\"\u003eyargs\u003c/a\u003e be a node.js library fer hearties tryin' ter parse optstrings\u003c/p\u003e\n\u003c/span\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-alt-sources\"\u003e\n \u003cdiv class=\"ocli-alt-sources__label\"\u003eAlternative sources\u003c/div\u003e\n \u003cul class=\"ocli-alt-sources__list\"\u003e\n \u003cli class=\"ocli-alt-sources__item\"\u003e\n \u003ccode\u003eenv: $OCLI_CLI_FRAMEWORK\u003c/code\u003e\n \u003c/li\u003e\n \u003cli class=\"ocli-alt-sources__item\"\u003e\n \u003ccode\u003efile: $.cli.framework\u003c/code\u003e\n \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003cdiv class=\"ocli-section__col-right\"\u003e\n \n\u003cdiv class=\"ocli-examples\"\u003e\n \u003cdiv class=\"ocli-examples__heading\"\u003eExamples\u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003egenerate Cobra (Go) CLI\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli gen cli \\\n --framework cobra \\\n --out ./internal \\\n ./my-cli.ocs.yaml\n# → Reading spec: ./my-cli.ocs.yaml\n# → Generating CLI code: framework=cobra, output=./internal\n# ✓ CLI Code written to: ./internal\n\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003egenerate urfave/cli (Go) CLI\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli gen cli \\\n --framework urfavecli \\\n --out ./internal \\\n ./my-cli.ocs.yaml\n# → Reading spec: ./my-cli.ocs.yaml\n# → Generating CLI code: framework=urfavecli, output=./internal\n# ✓ CLI Code written to: ./internal\n\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv class=\"ocli-example\"\u003e\n \u003cdiv class=\"ocli-example__title\"\u003egenerate Yargs (Node.JS) CLI\u003c/div\u003e\n \u003cdiv class=\"ocli-code-block ocli-code-block--terminal\"\u003e\n \u003cdiv class=\"ocli-code-block__header\"\u003e\n \u003cspan class=\"ocli-code-block__label\"\u003eTerminal\u003c/span\u003e\n \u003c/div\u003e\n \u003cpre class=\"ocli-code-block__body\"\u003e$ ocli gen cli \\\n --framework yargs \\\n --out ./src \\\n ./my-cli.ocs.yaml\n# → Reading spec: ./my-cli.ocs.yaml\n# → Generating CLI code: framework=yargs, output=./src\n# ✓ CLI Code written to: ./src\u003c/pre\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n\u003c/section\u003e\n\n\n \u003cfooter class=\"ocli-footer\"\u003e\n generated by \u003ca href=\"https://opencli.dev\"\u003eOpenCLI\u003c/a\u003e\n \u003c/footer\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\n"; var DEFAULT_CONTAINER_ID = "docs";