> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Git Template Sources

A template source is a Git repository whose `*.tensor9.{tf,sh,kubectl}`
and `*.t9.{tf,sh,kubectl}` files become Tensor9 ops command templates
in your control plane. You register the source once; later, as the repo
evolves, you re-sync to discover new templates, upgrade modified ones,
or retire those removed upstream.

This is the canonical way to maintain a library. The open-source
`tensor9ine/cmdlib` repo is laid out exactly this way and is a good
starting point if you're new to authoring templates.

<img src="https://mintcdn.com/tensor9/Q7wEl9vOj9lICJg4/images/diagrams/sources-howitworks-dark.svg?fit=max&auto=format&n=Q7wEl9vOj9lICJg4&q=85&s=0e9dec053d35e8ab2eeb3c0e115d880f" className="block dark:hidden" alt="How a Git template source works: register the repo, resync to see drift, upgrade to mint new versions." width="820" height="200" data-path="images/diagrams/sources-howitworks-dark.svg" />

<img src="https://mintcdn.com/tensor9/Q7wEl9vOj9lICJg4/images/diagrams/sources-howitworks-light.svg?fit=max&auto=format&n=Q7wEl9vOj9lICJg4&q=85&s=1245d455fbb63da4f60dc19f251033d8" className="hidden dark:block" alt="How a Git template source works: register the repo, resync to see drift, upgrade to mint new versions." width="820" height="200" data-path="images/diagrams/sources-howitworks-light.svg" />

Three properties keep authoring sane:

1. **Templates live in code review.** Pull requests against the repo
   gate every change before customers ever see it.
2. **Resync surfaces drift.** When the repo lands new templates or
   modifies existing ones, `tensor9 ops template source resync` shows
   the four-bucket diff (unchanged, modified, new, removed) without
   committing anything.
3. **Upgrades are explicit.** `tensor9 ops template source upgrade` is
   a separate step. Diff first, then apply only the picks you want,
   scoped by file or action kind.

## A reference layout

The `cmdlib` repo groups templates by category. Each subdirectory
contributes one template per `.tensor9.*` file inside it:

```
src/
  aws/
    find-idle-instances.tensor9.tf
    list-public-s3-buckets.tensor9.tf
    ...
  k8s/
    drain-node.tensor9.tf
    scale-deployment.tensor9.tf
    ...
  linux/
    disk-usage.tensor9.tf
    host-info.tensor9.tf
    ...
  darwin/
    disk-usage.tensor9.tf
    host-info.tensor9.tf
    ...
```

Both `linux/` and `darwin/` carry a `disk-usage.tensor9.tf`. They
coexist because Tensor9 prefixes the parent directory name onto the
imported template, producing `linux-disk-usage` and `darwin-disk-usage`
as distinct templates. See "Conflict resolution" below for the cases
where the prefix alone does not disambiguate.

## Registering a source

```bash theme={null}
tensor9 ops template source create \
  --sourceType GitHub \
  --sourceUrl https://github.com/tensor9ine/cmdlib \
  --appName my-app \
  --sourceName cmdlib
```

The action shells out to `gh` to clone the repo at HEAD, walks every
matching file in the tree, ships the raw bytes to the appliance for
parsing, and persists one template per file plus a single
`OpsCmdTmplSrc` row binding the source to its templates.

Useful flags:

| Flag                | Purpose                                                                                  |
| ------------------- | ---------------------------------------------------------------------------------------- |
| `--branch`          | Override the branch (default: the repo's default branch).                                |
| `--dirs`            | Comma-separated directories to track (default: every dir containing `.tensor9.*` files). |
| `--dry-run`         | Walk and print what would be imported. No control-plane writes.                          |
| `--conflict-policy` | How to handle template-name conflicts in the target app. See below.                      |

`gh auth login` must succeed first. The action will fail with a clear
message if the GitHub CLI is missing or unauthenticated.

## Conflict resolution

The persisted template name is the dir-prefixed file stem
(`linux-disk-usage` from `linux/disk-usage.tensor9.tf`). A name
conflict happens when that stem already exists in the target app
because, say, the same source was registered before and you are
re-importing.

`--conflict-policy` controls the bulk behavior:

| Value            | Effect                                                                                        |
| ---------------- | --------------------------------------------------------------------------------------------- |
| `fail` (default) | Abort the whole register on the first conflicting name. Safest for first-time imports.        |
| `skip-all`       | Skip every conflicting file. The non-conflicting subset still imports.                        |
| `duplicate-all`  | Auto-rename each conflicting file with a `-N` suffix (`linux-disk-usage-2`, then `-3`, etc.). |

Example:

```bash theme={null}
# Re-import cmdlib, dropping anything we already track and importing only the new files
tensor9 ops template source create \
  --sourceType GitHub \
  --sourceUrl https://github.com/tensor9ine/cmdlib \
  --appName my-app \
  --sourceName cmdlib-v2 \
  --conflict-policy skip-all
```

The action's output lists the skipped or renamed files explicitly so
you can audit what landed.

## Resyncing against HEAD

```bash theme={null}
tensor9 ops template source resync --sourceName cmdlib
```

Resync clones the repo, lifts each file's spec, and reports the
four-bucket diff against what's already imported:

| Bucket             | Meaning                                                                                                                                            |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Unchanged`        | Tracked template whose source file at HEAD has the same content hash. No action needed.                                                            |
| `Modified`         | Tracked template whose source file at HEAD has a different content hash. Run `tensor9 ops template source upgrade` to mint a new lineage version.  |
| `New available`    | File at HEAD that no tracked template owns. Run `tensor9 ops template source upgrade --actions add` to import.                                     |
| `Removed upstream` | Tracked template whose source file vanished from HEAD. Run `tensor9 ops template source upgrade --actions retire-here` to drop the source binding. |

Resync is read-only; it never persists anything. Run it as often as you
like.

<Note>
  Resync walks the **whole** repo, not just the directories you selected
  at register time. If a new sibling directory landed upstream after you
  registered (a `darwin/` next to your originally-selected `linux/`), its
  files surface as `New available` automatically. You do not need to
  re-register the source to track new dirs.
</Note>

## Applying the diff: upgrade

```bash theme={null}
tensor9 ops template source upgrade --sourceName cmdlib
```

By default `tensor9 ops template source upgrade` applies every action
the diff implies: evolve modified templates, add newly-available
ones, retire-here those removed upstream. Tracked template lineages
are versioned, so an upgrade mints `v1.1.0` (or the appropriate
semver bump) without breaking customers who pre-approved `v1.0.0`.

### Scoping with `--only` and `--actions`

Two filters narrow what the upgrade does:

```bash theme={null}
# Only evolve modified templates; don't add new files or retire missing ones
tensor9 ops template source upgrade \
  --sourceName cmdlib \
  --actions upgrade

# Only add newly-discovered files; leave existing tracked templates alone
tensor9 ops template source upgrade \
  --sourceName cmdlib \
  --actions add

# Apply the diff but only for two specific files
tensor9 ops template source upgrade \
  --sourceName cmdlib \
  --only linux-disk-usage.tensor9.tf,linux-host-info.tensor9.tf
```

`--actions` accepts any subset of `upgrade`, `add`, `retire-here`. `--only`
restricts to a CSV of file names matching what
`tensor9 ops template source resync` listed.

### What "retire-here" means

When a source file vanishes from upstream, customers who ran the
template before still have valid pre-approvals against the persisted
template versions. `retire-here` deprecates the latest version (so new
runs surface a deprecation notice) and drops the binding from the
source's tracked id list. The template lineage itself stays in your
control plane until you explicitly revoke or evolve it. Customers can
keep using already-approved versions until pre-approvals expire.

## Inventory

```bash theme={null}
# All sources you've registered
tensor9 ops template source list

# A single source's full detail
tensor9 ops template source retrieve --sourceName cmdlib
```

`retrieve` shows the GitHub coordinates, last-synced commit, selected
directories, and the imported template id list.

## Retiring a source

```bash theme={null}
tensor9 ops template source retire --sourceName cmdlib
```

Soft-delete. The source row is marked retired; the imported templates
stay. They become orphan lineages: usable, evolveable, and revokable on
their own, but no longer reachable through
`tensor9 ops template source resync` or
`tensor9 ops template source upgrade`. Use `--auto` to skip the
confirmation prompt in scripts.

## End-to-end example

```bash theme={null}
# 1. Register the public cmdlib repo as a template source for `my-app`
tensor9 ops template source create \
  --sourceType GitHub \
  --sourceUrl https://github.com/tensor9ine/cmdlib \
  --appName my-app \
  --sourceName cmdlib

# 2. Some weeks later, a new `darwin/` dir landed upstream.
#    See what's changed:
tensor9 ops template source resync --sourceName cmdlib

# 3. Pull only the new darwin templates (don't touch existing linux ones)
tensor9 ops template source upgrade \
  --sourceName cmdlib \
  --actions add

# 4. Review what you now expose:
tensor9 ops template list --appName my-app
```

## Related

* [Authoring templates](/fundamentals/operations/templates): the file format, variables, data access tags, permission tiers.
* [Submitting and tracking ops commands](/fundamentals/operations/lifecycle): use a registered template to actually run something.
