Skip to main content

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.

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. How a Git template source works: register the repo, resync to see drift, upgrade to mint new versions. 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

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:
FlagPurpose
--branchOverride the branch (default: the repo’s default branch).
--dirsComma-separated directories to track (default: every dir containing .tensor9.* files).
--dry-runWalk and print what would be imported. No control-plane writes.
--conflict-policyHow 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:
ValueEffect
fail (default)Abort the whole register on the first conflicting name. Safest for first-time imports.
skip-allSkip every conflicting file. The non-conflicting subset still imports.
duplicate-allAuto-rename each conflicting file with a -N suffix (linux-disk-usage-2, then -3, etc.).
Example:
# 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

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:
BucketMeaning
UnchangedTracked template whose source file at HEAD has the same content hash. No action needed.
ModifiedTracked template whose source file at HEAD has a different content hash. Run tensor9 ops template source upgrade to mint a new lineage version.
New availableFile at HEAD that no tracked template owns. Run tensor9 ops template source upgrade --actions add to import.
Removed upstreamTracked 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.
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.

Applying the diff: upgrade

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:
# 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

# 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

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

# 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