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:
- Verifies the vault directory exists and is a Git repository.
- Detects local modifications (
git status --porcelain). - Skips any vault with local changes — you commit or stash manually.
- 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:
- Wraps the CLI as skills — each
tanacommand 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"). - 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 theskills/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 language — add, 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c17cd550c5715a98bf30bce975b4bc6456998c14f766b6c99b1f4fb641cd11b5
|
|
| MD5 |
512a416cb8d428014e7397c6f74be2cb
|
|
| BLAKE2b-256 |
ded1b312d95c377813b4ee7d0a6f832087eb4bf8824fd6b67361ee72bd38890e
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
17ba8eece28b7ea17aec24d1765f2eb872d7bb00edb0b1b563294591547901fa
|
|
| MD5 |
c5998b8885169f217a1b96d25a87ce0d
|
|
| BLAKE2b-256 |
392715d89b67a716391d831aa40a8abb19dfce79a4f27b1614f91aa19e870117
|