Docs/CLI reference

CLI reference

tama copies list

Reports dependency checkouts, bare Git caches and other second repository copies under the roots you name, with their canonical checkout, apparent size and removal refusals. It mutates nothing.

Reports dependency checkouts, bare Git caches and other second repository copies under the roots you name, with their canonical checkout, apparent size and removal refusals. It mutates nothing.

#Invocation

tama copies list [--root <PATH>]... [--json]

#Inputs and options

OptionMeaning
--root <PATH>Repeatable, and required at least once. Each value is a directory whose checkouts are walked. There is deliberately no default root
--jsonPrints the exact document below instead of the text report. Both modes read the same state

#What counts as a copy

The named roots and their direct child repositories are canonical. Deeper repositories are candidates, including ignored paths, package-manager checkouts, repositories, node_modules, Pods and build directories. Only Git's own .git metadata is pruned; a directory name never hides a dependency checkout.

A .git file does not by itself mean a linked worktree: submodules also use one. Git's private and common metadata directories distinguish them. Linked worktrees appear once under linkedWorktrees and belong to tama worktrees list; submodule checkouts remain copy candidates. Bare repositories are recognized by Git and have no working-tree changes, but their history is still checked.

The pass checks working-tree changes, the origin, and every stored Git object, including dangling commits and annotated tags. Remote-tracking refs remain a local record, not a network check. When they do not retain the history, Tama looks for a canonical checkout whose refs reach every stored object. That checkout must use its own object storage, without alternates or symlinks. The result is named in historyRetainedBy; null means no such proof was established. Missing objects or failed history reads do not become a clean result. Git's lazy fetching is disabled.

Ownership still follows origins, not merely shared history. A retention proof does not claim that two differently named repositories are the same. An owner-less candidate still needs an explicit --only claim. Canonical checkouts from every named root contribute, regardless of root order.

An initialized repository without commits is readable. Damaged metadata never borrows the enclosing repository's history: Git must identify the candidate itself, or the pass reports it under unreadable.

#Output document

Under --json, exactly these fields, with the schema version the whole copies contract is fixed at:

{"schemaVersion":Number,"roots":[String],"copies":[{"path":String,"owner":String|null,"origin":String|null,"bytes":Number,"dirty":Boolean,"unpublished":Boolean,"historyRetainedBy":String|null,"ownsWorktrees":Boolean|null,"named":Boolean}],"copyCount":Number,"bytes":Number,"linkedWorktrees":[String],"twins":[{"path":String,"twin":String,"origin":String,"basis":"origin"|"first-commits"}],"unreadable":[String],"unreadableDirectories":[{"path":String,"reason":String}]}

roots echoes the roots you passed, resolved. owner is the canonical checkout of the same repository under those roots, or null when this directory is the only checkout of its repository here — which is a refusal on remove until you name it with --only. bytes is apparent size, per copy and summed for the pass. named is false here and only ever true in a narrowed removal document.

twins carries two checkouts of one repository that the pass reports and removes neither of. With basis origin, both sit directly under a root and name the same origin, and origin is that origin. With basis first-commits, their origins differ but their histories start from the same commits, and origin holds those commits. That is what a repository GitHub moved looks like: every checkout cloned before the move keeps the old address. A fork starts from the same commits too, which is why this match only reports and never makes one checkout the owner of the other. The text report prints it as twin history: <path> and <path> start from the same commits (<commits>) under different origins, …. unreadable names every candidate repository git then refused to answer for: reported rather than dropped, because silence would be the pass claiming it read a checkout it never read.

unreadableDirectories names every directory or entry the walk could not read, each with the operating system's reason. A pass carrying one of these cannot say the roots hold one checkout per repository, only that it saw no second one where it could look, so it exits 1 and prints could not read <path>: <reason> to stderr in both output modes. A checkout whose .git/worktrees records exist and cannot be read is listed here too, with the read error as its reason, instead of being treated as owning no worktree; a copy whose own records cannot be read carries ownsWorktrees: null and the error in its inspection, which remove refuses as unreadable Git state.

The same document is the answer of tama request copies/list with body {"roots":[String]}, the operation Tama Desktop runs (tama request).

#State effect

None. The command walks directories and runs read-only Git status, ref, object and origin queries. It does not fetch missing objects, and it has no --apply, no --force, no --except and no --only: those belong to tama copies remove, which is the only leaf with anything to spare, narrow or delete.

#Refusal boundary

Passing no --root is a usage error, exit code two:

tama copies needs at least one --root; a machine-wide default would walk directories Tama does not own.

A root that cannot be read is reported in unreadableDirectories with the operating system's own reason, and the command exits 1 rather than reporting a clean tree it never walked. A failed history query is an operational error and names the actual failed read. Safety refusals belong to tama copies remove.

Return to the copies command group or the complete CLI tree.