Skip to main content

A package manager for Git-based knowledge packages

Project description

Tana

Tana is a package manager for Git-based knowledge vaults.

A knowledge vault is simply a folder — usually a Git repository — of knowledge. Tana manages the adding, listing, and updating of these vaults on your machine. It is not a Git replacement, and it is not an AI tool — it is a small, focused manager that happens to use Git as its transport.


Installation

Requires Python 3.10+.

With pipx (recommended)

pipx installs the tana command into its own isolated environment and puts it on your PATH — no venv juggling.

# Install straight from GitHub
pipx install git+https://github.com/wxharry/tana.git

# …or from a local clone
git clone https://github.com/wxharry/tana.git
cd tana
pipx install .

Upgrade or remove later with:

pipx upgrade tana
pipx uninstall tana

With pip (editable / development)

git clone https://github.com/wxharry/tana.git
cd tana
pip install -e .          # or: pip install -e ".[dev]"  (tests included)

Any of these expose the tana command.


Quick start

# Set up Tana in ~/.tana
tana init

# Add a knowledge vault — source type is detected automatically
tana add git@github.com:company/git-knowledge-vault.git --name my-vault   # Git URL → cloned
tana add https://github.com/company/php.git --name php
tana add ~/Documents/wiki --name wiki                                # folder  → linked in place

# See what's tracked
tana list

# Update everything (or a single vault)
tana update
tana update my-vault

# Remove a vault (asks before deleting files)
tana remove my-vault
tana remove my-vault --keep-files

# Discover the agent skills a vault carries
tana skills
tana skills show my-vault rebase
tana skills export
tana skills export --target claude

CLI reference

Command Description
tana init Create ~/.tana/, ~/.tana/vaults/, and ~/.tana/config.toml.
tana add <source> [--name NAME] Add a vault. <source> is a Git URL (cloned) or a local folder path (linked in place). Name inferred unless overridden.
tana list Show tracked vaults as a table.
tana info <name> Show a vault's URL, path, branch, commit, last change, and dirty state.
tana update [name] Update all vaults, or a single named vault.
tana remove <name> [--keep-files] Remove a vault. Asks before deleting files unless --keep-files.
tana skills List every agent skill discovered across tracked vaults.
tana skills show <vault> <skill> Print a skill's Markdown with placeholders rendered.
tana skills export [--target claude] Export skills to ~/.tana/exports/. --target claude uses a Claude-specific folder.

Vault kinds

tana add detects the source type:

Kind Source Lives in Updates Remove
git a Git URL (git@…, https://…) ~/.tana/vaults/<name> (cloned) fetch + fast-forward asks before deleting files
local a local folder path wherever it already is (not copied) pulls if the folder is a Git repo, otherwise skipped only unlinks — never deletes your files

The local kind is for a knowledge base you maintain yourself — e.g. an Obsidian vault:

tana add ~/Documents/wiki --name wiki

Tana tracks it in place. There is no second copy to drift out of sync, and removing only forgets it.

How updates stay safe

For each vault, tana update:

  1. Verifies the vault directory exists and is a Git repository.
  2. Detects local modifications (git status --porcelain).
  3. Skips any vault with local changes — you commit or stash manually.
  4. Otherwise fetches and fast-forwards only.

Tana never commits, pushes, stashes, merges, or resolves conflicts. If a fast-forward is not possible, the update is reported as Failed and left for you to handle with Git directly.

Per-vault status is one of: Updated, Already up to date, Skipped, or Failed.


Agent skills

A vault can carry skills: Markdown files that tell an AI agent when to use the vault, what knowledge it holds, where to look, and which conventions to follow. Tana discovers, lists, renders, and exports these files. It does not own or interpret the knowledge — skills are content the vault carries, and agent integrations consume the exported result.

The skills/ convention

A vault exposes skills under its own skills/ directory — an ordinary content folder the vault already owns, alongside notes/ and examples/. Tana imposes no special metadata directory. Every *.md under skills/ is one skill; its filename (without .md) is the skill name. Non-Markdown files are ignored.

git-knowledge-vault/
├── skills/          # agent-readable skills (Tana discovers these)
│   ├── rebase.md
│   └── merge.md
├── notes/           # the knowledge itself
├── examples/
└── README.md

Example skill — skills/rebase.md

# Git Rebase Skill

Use this skill when the user asks about:
- git rebase / `git rebase --onto`
- interactive rebase (`git rebase -i`) — squash, fixup, reword, drop
- replaying commits onto a new base
- resolving conflicts during a rebase (`--continue` / `--abort` / `--skip`)

Knowledge vault: {{vault_name}}
Knowledge vault path: {{vault_path}}
Skill file: {{skill_path}}

Before answering:
1. Search this vault's notes and examples for the branching model.
2. Prefer the team convention: rebase local branches, never shared history.
3. Explain tradeoffs vs. merge clearly.

Placeholders

Tana substitutes these tokens when showing or exporting a skill (plain string replacement, for now):

Placeholder Replaced with
{{vault_name}} the vault name
{{vault_path}} absolute path to the vault on disk
{{skill_name}} the skill name (filename without .md)
{{skill_path}} absolute path to the skill file

Listing

$ tana skills
VAULT       SKILL    FILE
my-vault    merge    ~/.tana/vaults/my-vault/skills/merge.md
my-vault    rebase   ~/.tana/vaults/my-vault/skills/rebase.md

Exporting

tana skills export writes each skill to ~/.tana/exports/skills/ as <vault>-<skill>.md, with placeholders rendered:

~/.tana/exports/skills/my-vault-rebase.md
~/.tana/exports/skills/my-vault-merge.md

--target claude is a simple folder export — it writes to ~/.tana/exports/claude/skills/ instead. Tana does not touch Claude's real config directory; the exported files are yours to copy wherever you like.


Claude Code plugin

Tana ships as a Claude Code plugin (the repo root doubles as the plugin root: .claude-plugin/, skills/, hooks/, statusline.sh). The plugin does two things:

  1. Wraps the CLI as skills — each tana command is a skill Claude can run for you by name or in plain language (/tana-add ~/Documents/wiki, "list my tana vaults", "update the wiki vault").
  2. Thinks with your vaults — a toggle that puts a fixed [TANA] badge on the statusline and injects a directive telling Claude to consult your tracked vaults (and the skills/ they carry) before answering.

Unlike a standalone thinking plugin, tana needs no separate "bind" step — the vault list comes straight from ~/.tana/config.toml, so tana add / tana remove are the binding. (The tana skills command is intentionally not exposed as a plugin skill — the plugin itself is the skills surface.)

Install

This repository is also a Claude marketplace (.claude-plugin/marketplace.json). Register it, then install the plugin:

/plugin marketplace add local-dev https://github.com/wxharry/tana
/plugin marketplace update local-dev
/plugin install tana@local-dev

Then reload Claude Code so the hooks and skills register.

Skills

Skill Runs / does
/tana-init tana init
/tana-add <source> [name] tana add (Git URL cloned, local folder linked)
/tana-list tana list
/tana-info <name> tana info
/tana-update [name] tana update
/tana-remove <name> [--keep-files] tana remove
/tana on | /tana off enable / disable the [TANA] badge + "think with your vaults" directive

The [TANA] badge and thinking directive

/tana on writes ~/.tana-active=on, validates that at least one tracked vault resolves to a real directory, and patches your statusline to prepend a cyan [TANA] badge. Two hooks then feed Claude a directive built from the live vault list:

  • SessionStart — foundational priming at session boot.
  • UserPromptSubmit — a per-turn reminder.

The directive tells Claude to read the relevant vault's skills/*.md to route, grep the vault, open the top matches, and cite findings as (from <vault>: <title>). Because the list is read live from tana's config, adding or removing a vault changes the substrate immediately — no re-toggle.

/tana off clears the flag and removes the badge block from your statusline. Both patch operations are idempotent and guarded by # >>> tana-plugin-badge >>> markers, so they never clobber the rest of your statusline script.


Configuration

Everything lives under ~/.tana:

~/.tana/
├── config.toml      # tracked vaults
└── vaults/          # cloned Git vaults

config.toml looks like:

[vaults.my-vault]
url = "git@github.com:company/git-knowledge-vault.git"
path = "/Users/me/.tana/vaults/my-vault"

Project layout

tana/
├── pyproject.toml
├── README.md
├── src/
│   └── tana/
│       ├── __init__.py
│       ├── cli.py        # Typer commands + Rich output (presentation only)
│       ├── config.py     # read/write ~/.tana/config.toml (testable)
│       ├── git.py        # the only module that shells out to Git
│       ├── models.py     # Vault dataclass + name inference
│       ├── skills.py     # discover + render a vault's skills/*.md
│       └── export.py     # write skills into agent-friendly folders
├── examples/
│   └── git-knowledge-vault/   # sample vault with a skills/ directory
└── tests/

Design philosophy

Tana is not a Git wrapper. Git keeps everything it is good at, and Tana stays out of its way.

Git owns Tana owns
commits, branches, history adding vaults
remotes, conflict resolution local organization
vault management & updates

Two principles fall out of this split:

  • User-facing language is vault languageadd, update, vault — not clone or pull.
  • Layers are separated — Git operations (git.py) are isolated from config (config.py), skills (skills.py/export.py), and CLI presentation (cli.py), which keeps each piece small and testable.

Tana never reaches into a vault's knowledge — it only reads the skills/ a vault chooses to publish. A vault stays a plain folder of Markdown that works fine without Tana.


Tests

pip install -e ".[dev]"
pytest

Coverage includes vault name inference, config read/write round-trips, duplicate vault detection, update-skipping when local changes exist, and skill discovery / placeholder rendering / export.


Roadmap

Skill discovery and export (above) are the first step of AI-agent integration. The intended future — documented but not yet implemented:

  • First-class agent integrations — beyond the generic folder export, native targets for Claude, Cursor, and Codex that drop skills where each tool expects them.
  • MCP server — expose tracked vaults and their skills to agents over the Model Context Protocol instead of (or alongside) file export.
  • Registry support — add a vault by name instead of a raw Git URL, with public/private registries and vault search.
  • Vault manifests — declared metadata per vault (description, version, tags, and which skills it provides).
  • Skill dependencies — let a skill declare other skills or vaults it builds on, so agents can pull in the full context a skill needs.

The architecture intentionally keeps Git (git.py), config (config.py), skills (skills.py/export.py), and CLI presentation (cli.py) separate so these can be layered in without rewrites. No AI vendor is hardcoded as the core model — claude is just one export target among future others.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tana-0.1.0.tar.gz (61.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tana-0.1.0-py3-none-any.whl (16.8 kB view details)

Uploaded Python 3

File details

Details for the file tana-0.1.0.tar.gz.

File metadata

  • Download URL: tana-0.1.0.tar.gz
  • Upload date:
  • Size: 61.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for tana-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c17cd550c5715a98bf30bce975b4bc6456998c14f766b6c99b1f4fb641cd11b5
MD5 512a416cb8d428014e7397c6f74be2cb
BLAKE2b-256 ded1b312d95c377813b4ee7d0a6f832087eb4bf8824fd6b67361ee72bd38890e

See more details on using hashes here.

File details

Details for the file tana-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tana-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for tana-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 17ba8eece28b7ea17aec24d1765f2eb872d7bb00edb0b1b563294591547901fa
MD5 c5998b8885169f217a1b96d25a87ce0d
BLAKE2b-256 392715d89b67a716391d831aa40a8abb19dfce79a4f27b1614f91aa19e870117

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page