usage: kanon add [-h] [--catalog-source <git-url>@<ref>]
                 [--catalog-default-branch <branch>] [--as <alias>]
                 [--kanon-file <path>] [--force] [--dry-run]
                 [--marketplace-install | --no-marketplace-install]
                 <name>[@<spec>] [<name>[@<spec>] ...]

Resolve catalog entries from a manifest repo and append the
alias-keyed KANON_SOURCE_<alias>_{URL,REF,PATH,NAME} block (plus an
optional per-dependency env-var line per ${VAR} the manifest needs)
to the destination .kanon file. The only global header written is the
single CLAUDE_MARKETPLACES_DIR line, auto-added once when a
claude-marketplace entry is added (and pruned by 'kanon remove' /
'kanon marketplace disable' once the last marketplace dependency is
gone); hand-set that line to override the directory.

Each ENTRY is '<name>' or '<name>@<spec>' where <spec> is a PEP 440
constraint (e.g. ==1.0.0, ~=1.2, >=1.0.0,<2.0.0). The last '@' in
each argument is the delimiter -- see spec Section 4.0 resolver rules.
When <spec> is omitted the highest PEP 440-valid git tag in the
entry's refs/tags/<name>/ namespace is selected, or the highest
bare refs/tags/<pep440> tag when the entry has no namespaced tags.

positional arguments:
  <name>[@<spec>]       One or more catalog entry names, optionally suffixed
                        with '@<spec>' where <spec> is a PEP 440 version
                        constraint. The last '@' is the delimiter (spec
                        Section 4.0). Shell-quote constraints containing
                        special characters such as '>' or '<'.

options:
  -h, --help            show this help message and exit
  --catalog-source <git-url>@<ref>
                        Remote catalog source as '<git_url>@<ref>' where ref
                        is a branch, tag, or 'latest'. Overrides the
                        KANON_CATALOG_SOURCES env var. Required when
                        KANON_CATALOG_SOURCES configures no single source.
  --catalog-default-branch <branch>
                        Branch to use for a catalog source supplied without an
                        '@ref'. Precedence: an inline '@ref' on the source >
                        this flag > the KANON_CATALOG_DEFAULT_BRANCH env var
                        (default 'main') > the literal 'auto', which resolves
                        the remote HEAD symref via 'git ls-remote --symref'. A
                        defaulted branch is verified to exist on the remote
                        (fail fast) and a single WARNING naming it is written
                        to stderr.
  --as <alias>          Override the auto-computed local alias for the
                        (single) added entry. The alias charset is
                        [A-Za-z0-9_] with no '__' run. When the alias is
                        already mapped to a different source it is a hard
                        error (use --force to overwrite, or 'kanon remove
                        <alias>' first). Without --as, the alias is the
                        sanitized manifest name, auto-suffixed
                        deterministically on a cross-source collision.
  --kanon-file <path>   Destination .kanon file path. Defaults to './.kanon'.
                        Overridden by the KANON_KANON_FILE environment
                        variable; the CLI flag takes precedence when both are
                        set.
  --force               Overwrite an existing alias block when re-adding the
                        same package (same source@ref), and re-pin its
                        .kanon.lock entry while keeping the dep's NAME.
                        Without this flag, a re-add of an existing alias is a
                        hard error (with a diff and the guiding message). A
                        cross-source collision (a different source for the
                        same manifest name) is auto-suffixed deterministically
                        and is never an error, with or without --force.
  --dry-run             Print the diff that WOULD be written to the
                        destination .kanon file ('+' for added lines, '-' for
                        removed lines when a --force overwrite replaces an
                        existing block). Makes no on-disk change. Exits 0.
                        Alias resolution still runs first, so a within-request
                        duplicate or a re-add of an existing alias (without
                        --force) is reported before any diff is shown.
  --marketplace-install
                        Force the added dependency to register as a Claude
                        marketplace (write
                        KANON_SOURCE_<alias>_MARKETPLACE=true), overriding the
                        auto-detected <catalog-metadata><type>. Errors if the
                        entry is not a 'claude-marketplace' type. Mutually
                        exclusive with --no-marketplace-install.
  --no-marketplace-install
                        Force the added dependency to NOT register as a
                        marketplace (omit the KANON_SOURCE_<alias>_MARKETPLACE
                        line), overriding the auto-detected <catalog-
                        metadata><type>. Mutually exclusive with
                        --marketplace-install.

Note: when supplying a PEP 440 range, quote the spec to avoid shell parsing:
   kanon add 'package-a@>=1.0,<2.0'
