A command-line tool for your GitHub repos

One folder structure
for every machine.

Laptop, desktop, work machine — on each one the repo you want is either missing or somewhere you have to go and find. talea keeps one catalogue of your GitHub repos, one tree, and one command that makes any machine match it.

Node 20+ · macOS, Linux and Windows · zero dependencies, runtime and dev. It never pushes, and it never deletes anything.

talea — ~/Workspace — zsh built by Ajay Kumar
~

Every machine ends up its own private filing system. The same repo lives in three places, and none of them is the one you remember.

A tool that fixed this by re-cloning would throw away your branches, your stashes and your uncommitted work. talea moves what is already there instead, matching every checkout by its git remote rather than its folder name — and it deletes nothing, ever.

The name

A cutting, taken and replanted

01

A talea is a cutting

Latin, and still the word gardeners use: a shoot taken off a living plant so it can be rooted somewhere else. Not a seed, and not a drawing of the plant — a piece of the plant itself.

02

Planted, it grows the same

A cutting is not a copy that resembles the original. It carries the whole thing with it and grows into the same plant in new ground, which is exactly what a catalogue on a new laptop has to do.

03

Here, the cutting is your tree

Publish the catalogue from one machine, pull it on the next, and the same structure grows there. What you keep on each machine stays that machine's business.

The run

What one command does

Before talea clones anything it scans the workspace — and any folder you name with --from — and matches every checkout it finds by its git remote, not by folder name. A repo cloned into ~/tmp/clone2/whatever is recognised as the repo it holds and moved into place.

That distinction is the whole safety story. A move keeps branches, stashes, the reflog and your uncommitted changes. A re-clone silently throws all of it away, so talea does not do one.

  • Matched on the remote URL. A name-only match — a fork, a mirror, an SDK cache — is listed and left alone until you say otherwise.
  • Worktrees travel with their repo. The sibling <repo>-worktrees/ folder moves too, and every link is repaired afterwards.
  • A second copy is parked, not deleted. It goes to .talea-duplicates/ with everything in it; clearing that folder is your call.
  • Paths that pointed at the old location are repaired. Claude Code session history, project settings, .idea, .vscode.
  1. 1

    It asks GitHub what you have

    talea discover reads your own repos, every org you belong to, and anything shared with you directly. That list is the catalogue, and it is yours.

  2. 2

    You tick what this machine keeps

    Once, in a checklist. A different machine can keep a different set, and neither fights the other.

    laptop: 6 repos desktop: 40 work: 3
  3. 3

    It finds the checkouts you already have

    Every git directory in the tree is read for its remote and matched against the catalogue. Nothing that matches is ever cloned a second time.

  4. 4

    It moves them into place

    A rename, not a copy — so it is instant and keeps everything. A cross-device move is refused and reported rather than turned into a copy-then-delete.

  5. 5

    It clones what is genuinely missing

    On the default branch GitHub recorded for that repo, never an assumed main. A repo with none recorded is cloned on whatever the server hands over.

  6. 6

    And fast-forwards the rest

    The branch you are on, or nothing at all with a line saying why. A dirty repo is fetched and left alone. It never merges a divergence, and it never pushes.

The promise

Nothing you have is ever destroyed

There is no rm in the part of talea that moves things, and that is enforced rather than intended.

Moved, never re-cloned

A repo in the wrong place is renamed into the right one. Branches, stashes, the reflog and your uncommitted work come with it, because none of them ever left the directory.

Duplicates are parked

If the same repo turns up twice, the copy at the catalogue path wins and the other moves to .talea-duplicates/ intact. Emptying that folder is a decision you make, not one talea makes for you.

It stays off your branch

No reset --hard, no clean -fd, no checkout --force, and no push. A tool that moves you off a feature branch mid-task is no better than one that clobbers your changes.

The data model

Three files, and only one travels

The split everything hangs off: the catalogue is shared, the selection is not. Pulling the catalogue onto a new laptop hands you the full list to choose from — never the last machine's choices.

~/.talea/talea.repos.json Your catalogue
travels shared

Every repo you can reach, its owner, its folder and its default branch. Written by talea discover, moved between machines through a private gist.

Discovery refreshes facts and never choices. A repo the API stops returning is kept and marked missing — a narrower token and a deleted repo look identical from here, and forgetting it is the one unrecoverable reading.

<workspace>/.talea.json What this machine keeps
never local

A list of names, written when you tick the checklist. Your work laptop can keep three repos while the desktop keeps forty.

A list of names rather than a filter over the catalogue, deliberately: a filter would re-evaluate, and marking a repo as a default would then start cloning it on every machine you own.

<workspace>/talea.repos.json A catalogue for one tree
optional local

Drop one next to a workspace and it wins over the one in your home directory. For a tree that is not yours — a shared machine, a container, a client's set of repos.

Nearest catalogue wins. The one packaged with talea is last, and ships empty on purpose: talea is the machinery, not a list of anybody's repositories.

ignore: true Hands off entirely
opt-in ignored

One flag on a catalogue entry and no command touches that checkout — not sync, not adopt, not an explicit selection.

For repos another tool already organises. Without it, two tools that both arrange repositories each drag the same checkout back where it thinks it belongs, on every run, forever.

The gist is private, but it still holds the names of your private repositories. Treat the id like a bookmark you would not paste into a public channel. talea manifest push prints it once.

Sixteen commands

talea init [dir]Create the workspace on this machine and fill it
talea discoverBuild or refresh the catalogue from GitHub
talea syncClone what is missing, fast-forward what is there
talea adoptMove checkouts you already have into place
talea statusBranch, clean or dirty, ahead or behind, in one table
talea selectReopen the checklist — what this machine keeps
talea where <repo>Print a repo's path, for cd $( )
talea exec -- <cmd>Run one command in every repo
talea manifest push/pullMove the catalogue between machines
talea skillInstall the skill that lets your coding agent drive talea

Plus clone, add, rm, list, tree, doctor and upgrade. Every one takes -g <group> and -r <repo> to narrow the run — or a bare name, talea sync eklavya — and --help for its own examples. An unknown group or repo name exits non-zero rather than quietly doing nothing. The full reference

Zero dependencies

Not at runtime, not to build it. Argument parsing, subprocesses, the filesystem, colour and HTTP all come out of Node's standard library, so a tool you install globally carries no supply chain with it.

Reading the catalogue prefers the gh CLI when it is installed. That is not only about the token: gh trusts your system certificate store, so talea keeps working behind a corporate proxy or VPN where Node's own HTTPS would fail.

For your coding agent

“Where is eklavya?”

One command installs a skill into Claude Code at user scope, so every project you open has it. Your agent then knows which talea command answers a question — and, more to the point, which flags it must never reach for on your behalf.

$ talea skill install
▣ Installed ~/.claude/skills/talea/SKILL.md
==> Restart Claude Code to pick it up
  • An adopt is always shown as a dry run first — a move relocates directories you may have open
  • --loose is never taken on your behalf, because a name-only match is how an SDK cache gets adopted and breaks a toolchain
  • A removal is reported as taken off the list, never as a delete, because that is what it is
  • The gist id never lands in a message going somewhere shared

User scope, not per-repo: your workspace spans every project, so the agent needs the same instructions in all of them. talea skill uninstall takes it back out, and it refuses to overwrite a skill called talea that talea did not write.

You

where's the eklavya repo on this machine?

Claude
talea where eklavya
~/Workspace/ProjectAJ14/eklavya
You

my repos are scattered all over, tidy them up

Claude
talea adopt --from ~/Desktop
10 would move, 1 name-only match left alone.
Nothing has changed yet — shall I apply it?

Same paths
on every machine.

$ npm install -g @ajaykumarnpm/talea
$ talea init ~/Workspace

Node 20+ · macOS, Linux and Windows · the package is scoped, the command is just talea

Then cd $(talea where eklavya) works everywhere.