Introduction
tp — Teleport anywhere in your codebase.
Most navigation tools treat your filesystem like a flat list of places you've been. tp actually pays attention. It knows which project you're in, remembers your patterns, and — when it's truly stumped — quietly consults an oracle to figure out where you meant to go.
Built in Rust. Works in six shells. Learns from day one. No config required, but every knob is there if you want it.
Why tp?
Existing tools make you choose: fast-but-dumb or precise-but-manual. tp refuses to choose.
| Tool | Strength | Weakness |
|---|---|---|
| zoxide | Fast, Rust, clean UX | No project awareness, no pinning, no AI, cold start |
| z.lua | Context-aware jumps | Slower, Lua dependency, no project scoping |
| fasd | Tracks files & dirs | Unmaintained since 2015 |
| fastTravelCLI | Manual waypoints | No learning, fully manual |
tp is what happens when you give zoxide a sense of place, a memory, and a mild case of precognition.
Features at a Glance
Core Navigation
Free, open source, works entirely offline. No accounts, no cloud, no strings.
- Frecency scoring — frequency + recency with time-decay weighting
- Multi-token fuzzy matching —
tp foo barmatches paths containing both tokens - Project awareness — auto-detection via
.git,Cargo.toml,package.json,go.mod, and more - Project-scoped search —
tp -p testsstays inside your project boundaries - Cross-project switching —
tp @payments-servicejumps to a known project root - Waypoints —
tp --mark deploypins a directory;tp :deployteleports there instantly - Smart cold start — bootstraps from shell history, git repos, and existing zoxide databases
- Built-in TUI picker — interactive fuzzy finder showing project name, last modified, and git branch
- Full
cdcompatibility — relative paths,..,-,~, absolute paths all just work - 6 shells — bash, zsh, fish, PowerShell, Nushell, Elvish
AI Features (BYOK)
Bring your own API key. The tool never phones home unless you ask it to. See the AI Features chapter for full details.
Pro Tier
For teams. Cloud sync, shared waypoints, onboarding mode, and navigation analytics.
How It Works
Six steps from query to destination. Most trips end at step four.
Query
│
▼
┌─────────────────────┐
│ 1. Exact/relative? │──▶ cd directly
└──────────┬──────────┘
│ no
┌──────────▼──────────┐
│ 2. Waypoint (:)? │──▶ jump to pin
└──────────┬──────────┘
│ no
┌──────────▼──────────┐
│ 3. Project (@)? │──▶ project root
└──────────┬──────────┘
│ no
┌──────────▼──────────┐
│ 4. Frecency + fuzzy │──▶ score > 0.8 → go ← 95% of jumps
└──────────┬──────────┘
│ too close to call
┌──────────▼──────────┐
│ 5. AI reranking │──▶ ~150 tokens, <300ms
└──────────┬──────────┘
│ still unsure
┌──────────▼──────────┐
│ 6. TUI picker │──▶ you choose
└─────────────────────┘
The design principle: AI is a tiebreaker, not a crutch. Your navigation should never wait on a network request unless it genuinely doesn't know where you want to go.
Development Status
tp is in beta. Core navigation, frecency scoring, project detection, waypoints, shell integration, AI reranking, TUI picker, and session recall are all implemented and working.
| Phase | Status | Shipping |
|---|---|---|
| Alpha | Complete | Core binary: frecency, project detection, waypoints, 6-shell integration, bootstrap, zoxide import |
| Beta | Complete | AI reranking (BYOK), TUI picker, session recall, query/remove/doctor commands. 95 tests, CI on 3 platforms. |
| v1.0 | Planned | Semantic project indexing, workflow prediction, natural language nav, VS Code extension. |
| Pro | Planned | Cloud sync, team waypoints, onboarding mode, analytics. |
Installation
From crates.io
cargo install tp-nav
Via Homebrew
brew install pattynextdoor/tap/tp
From Source
git clone https://github.com/pattynextdoor/tp.git
cd tp
cargo install --path .
Shell Setup
Add one line to your shell configuration file. This sets up the shell function that wraps tp so it can actually change your working directory.
Bash
Add to ~/.bashrc:
eval "$(tp init bash)"
Zsh
Add to ~/.zshrc:
eval "$(tp init zsh)"
Fish
Add to ~/.config/fish/config.fish:
tp init fish | source
PowerShell
Add to $PROFILE:
Invoke-Expression (& { tp init powershell } | Out-String)
Nushell
Add to ~/.config/nushell/env.nu:
tp init nushell | save -f ~/.cache/tp/init.nu; source ~/.cache/tp/init.nu
Elvish
Add to ~/.config/elvish/rc.elv:
eval (tp init elvish | slurp)
Custom Command Name
If you prefer a different command name (e.g., j instead of tp), use the --cmd flag:
eval "$(tp init bash --cmd j)"
This works with any shell.
Bootstrap
tp auto-bootstraps on first run. The first time you navigate with an empty database, tp silently:
- Imports your zoxide database (if zoxide is installed)
- Parses your shell history (
~/.zsh_history,~/.bash_history, fish history) forcdtargets - Scans common code directories (
~/code,~/projects,~/repos, etc.) for project roots
This takes <500ms and means your first tp command already has context.
You can also trigger it manually or import from a specific source:
tp init --bootstrap # re-run auto-discovery
tp import --from=zoxide # import from zoxide
tp import --from=zoxide ~/.local/share/zoxide/db.zo # import from file
tp is useful from the first command. On first run, it automatically indexes your shell history, imports from zoxide (if installed), and discovers projects under your home directory. No cold start, no manual setup.
Usage
Quick Start
After installing and setting up your shell, you can start navigating immediately:
tp myproject # jump to best match
tp -p tests # find tests/ within the current project
tp @payments-service # switch to a project by name
tp :deploy # teleport to a pinned waypoint
tp -i # interactive fuzzy picker
Command Reference
Navigation
tp <query> Navigate to best match
tp -i [query] Interactive picker
tp -p <query> Search within current project
tp @<project> Jump to project root by name
tp :<waypoint> Jump to pinned waypoint
tp also supports full cd compatibility — relative paths, .., -, ~, and absolute paths all just work.
Waypoints
Pin frequently used directories for instant access:
tp --mark <name> [path] Pin a directory (defaults to cwd)
tp --unmark <name> Remove a pin
tp --waypoints List all waypoints
Then jump to any pin with the : prefix:
tp :deploy # teleport to the pinned "deploy" directory
Database Management
tp add <path> Manually add a directory
tp remove <path> Remove from database
tp query <query> Print matches (for scripting)
Shell Integration & Import
tp init <shell> Shell integration code
tp init --bootstrap Bootstrap from history
tp import --from=zoxide Import from zoxide
Smart Aliasing
Suggest waypoint names based on your most-visited directories:
tp suggest Show suggested waypoint names
tp suggest --apply Interactively apply suggestions
tp suggest --ai Use AI for creative names (requires API key)
tp suggest -n 20 Show more suggestions
AI Commands
These commands require an API key. See AI Features for setup.
tp index [path] Semantic index a project
tp analyze Extract workflow patterns
tp --recall "Where was I?" session digest
tp --setup-ai Configure API key for AI features
Other
tp ls [-n COUNT] List top directories by frecency
tp back [STEPS] Jump back in navigation history
tp completions <shell> Generate shell completions
tp sync Force cloud sync (Pro)
tp doctor Diagnose configuration issues
Project Markers
tp uses project markers to detect project boundaries for project-scoped search (tp -p) and cross-project switching (tp @). It walks up the directory tree looking for these files:
.git Cargo.toml package.json go.mod pyproject.toml setup.py Gemfile pom.xml build.gradle CMakeLists.txt Makefile .project composer.json mix.exs deno.json flake.nix
Configuration
All configuration is via environment variables. tp ships with sane defaults and requires zero configuration to use, but every knob is exposed if you want to tune it.
Environment Variables
| Variable | Default | Description |
|---|---|---|
TP_DATA_DIR | $XDG_DATA_HOME/tp | Database and config location |
TP_API_KEY | — | Anthropic API key for AI features |
TP_AI_MODEL | claude-haiku-4-5-20251001 | AI model override |
TP_AI_TIMEOUT | 2000 | AI request timeout (ms) |
TP_EXCLUDE_DIRS | — | Comma-separated path prefixes to ignore (supports ~) |
Project Markers
tp walks up the directory tree looking for these files to detect project boundaries:
.git Cargo.toml package.json go.mod pyproject.toml setup.py Gemfile pom.xml build.gradle CMakeLists.txt Makefile .project composer.json mix.exs deno.json flake.nix
AI Configuration
To enable AI features, set your API key:
tp --setup-ai
Or set the environment variable directly:
export TP_API_KEY="your-anthropic-api-key"
You can override the model or adjust the timeout:
export TP_AI_MODEL="claude-haiku-4-5-20251001"
export TP_AI_TIMEOUT="3000"
See AI Features for more details on what the AI layer provides.
AI Features
tp includes an optional AI layer that enhances navigation when the local frecency engine is uncertain. All AI features follow the BYOK (Bring Your Own Key) model — the tool never phones home unless you explicitly configure it to.
Setup
Run the interactive setup command to configure your API key:
tp --setup-ai
Or set the environment variable directly:
export TP_API_KEY="your-anthropic-api-key"
Once configured, AI features activate automatically when needed. You can fine-tune behavior with additional environment variables — see Configuration for the full list.
How AI Fits In
AI is a tiebreaker, not a crutch. The resolution pipeline (described in the Introduction) only reaches the AI reranking step when local frecency scoring produces ambiguous results (roughly 5% of queries). When it does fire, a typical request uses ~150 tokens and completes in under 300ms.
Implemented Features
AI Reranking
When frecency scores are tied between candidates, AI considers your current working directory and candidate paths to break the tie intelligently. A typical request uses ~150 tokens and completes in under 300ms.
Session Recall
Lost track of what you were working on? The --recall command produces a digest of your recent navigation session:
tp --recall
This answers the Monday morning question: "where was I?"
Coming Soon (Stubbed)
These features are stubbed and under active development:
Semantic Project Indexing
tp index [path]
Indexes a project by concept, enabling searches like:
tp the service that handles webhook retries
Workflow Prediction
tp analyze
Spots recurring navigation sequences and nudges you toward the next likely destination. For example, if you frequently go from src/api to tests/api to docs/api, it learns that pattern and suggests optimizations (e.g., waypoints you should create, projects you frequently switch between).
Smart Aliasing
Analyzes your visit history and suggests waypoint names for frequently visited directories:
tp suggest # show suggestions
tp suggest --apply # interactively apply them
tp suggest --ai # use AI for creative names
Names are generated deterministically from path structure — generic components like src/ are combined with their parent. With --ai, Claude Haiku suggests more memorable names. Suggestions are always presented for confirmation.
Planned
Natural Language Navigation
Navigate using descriptive phrases even when no tokens match the path:
tp the auth service terraform module
The AI layer will resolve intent by considering your project structure, not just string matching.
Privacy
- AI features are opt-in via API key configuration
- No data is sent anywhere unless you set
TP_API_KEY - Queries go directly to the Anthropic API — there is no intermediary server
Architecture
tp is built as a lean Rust binary with optional compile-time feature flags for AI and TUI capabilities.
Overview
- Core — Rust, <5MB static binary, <5ms local navigation
- Database — SQLite with WAL mode, automatic migrations, index optimization
- AI & TUI — compile-time feature flags (
--features ai,tui), both on by default - Local-first — fully functional offline; AI is the fallback, never the hot path
The architecture diagram is available in the GitHub repository.
Resolution Pipeline
When you type tp <query>, the binary runs through a six-step pipeline (see Introduction for the full diagram):
- Exact/relative path — if the query is a valid path,
cddirectly - Waypoint lookup —
:prefix triggers a pin lookup - Project lookup —
@prefix triggers a project root lookup - Frecency + fuzzy match — the local scoring engine handles ~95% of queries 4b. Typo tolerance — Damerau-Levenshtein fallback when fuzzy matching returns nothing
- AI reranking — fires only when local scores are ambiguous (~150 tokens, <300ms)
- TUI picker — last resort, the user picks from a ranked list
Under the Hood: Scoring Algorithm
Every query that reaches step 4 of the pipeline goes through a multi-layered scoring system. Understanding how it works helps explain why tp picks the paths it does.
Frecency
Frecency combines frequency (how often you visit) with recency (how recently you visited). The formula:
frecency = access_count × time_weight(seconds_since_last_visit)
Time weights decay in buckets:
| Last visited | Weight |
|---|---|
| < 5 minutes | 4.0× |
| < 1 hour | 2.0× |
| < 1 day | 1.0× |
| < 1 week | 0.5× |
| older | 0.25× |
When total frecency across all entries exceeds 10,000, scores are recalculated and entries older than 30 days with near-zero scores are pruned automatically.
Fuzzy Matching
The query is matched against each candidate path in descending tiers:
| Tier | Score | Example (query → path) |
|---|---|---|
| Exact last component | 1.0 | api → /home/user/projects/api |
| Suffix of last component | 0.9 | api → /home/user/projects/my-api |
| Substring anywhere | 0.7 | proj → /home/user/projects/api |
| Multi-word (all tokens present) | 0.6 | user api → /home/user/projects/api |
| No match | 0.0 | zzz → /home/user/projects/api |
Matching is case-insensitive throughout.
Typo Tolerance
When fuzzy matching returns zero results, a fallback pass uses Damerau-Levenshtein distance on the last path component. This catches the four most common typo types: insertions, deletions, substitutions, and transpositions (e.g. projetcs → projects).
| Query length | Max allowed edits |
|---|---|
| < 5 chars | (skipped — too many false positives) |
| 5–8 chars | 1 |
| 9+ chars | 2 |
Typo matches score 0.4 — below all fuzzy tiers, so a real substring match always wins. This is strictly a "last resort before returning nothing" layer.
Final Score
The final score for each candidate combines all signals:
score = frecency × fuzzy_score × proximity_boost
proximity_boost= 1.5× if the candidate is in the same project as your current working directory, 1.0× otherwise.- The candidate with the highest score wins. If that score exceeds 0.8,
tpnavigates immediately. Otherwise, the results flow into AI reranking (step 5) or the TUI picker (step 6).
Design Principles
- Local-first, always. Every navigation is instant by default. The network is a luxury, not a dependency.
- Invisible intelligence. Frecency, project context, and AI blend seamlessly. No "modes" to think about.
- Zero-config magic, full-config power. Works the moment you install it. Everything overridable for the curious.
- Respect the developer. No telemetry without consent. No nagging. No forced accounts. The free tier is the real product.
Database
tp uses SQLite with WAL (Write-Ahead Logging) mode for concurrent reads and fast writes. The database stores:
- Directory entries — paths with frecency scores and visit metadata
- Project roots — detected project boundaries and their markers
- Waypoints — user-pinned directory aliases
- Session data — navigation history for AI session recall
The database location defaults to $XDG_DATA_HOME/tp and can be overridden with TP_DATA_DIR (see Configuration).
Feature Flags
AI and TUI features are controlled by compile-time Cargo feature flags:
# Build with all features (default)
cargo build --release
# Build without AI
cargo build --release --no-default-features --features tui
# Build without TUI
cargo build --release --no-default-features --features ai
# Minimal build (no AI, no TUI)
cargo build --release --no-default-features
This keeps the core binary small and dependency-free for environments where AI or TUI support isn't needed.
Benchmarks
All benchmarks measured with hyperfine on a MacBook Pro M4 Pro, 200+ runs each. The benchmark suite tests four scenarios to give a fair picture of performance.
Interactive SVG charts are available in the GitHub README.
Core Queries (500 entries, flat seeding)
Raw query speed with 1 visit per path — the simplest comparison between tp and zoxide.
This scenario tests the baseline overhead of the frecency lookup engine with a uniform visit distribution.
Realistic Visit Patterns (hot/warm/cold)
300 directories with varied visit counts:
- 50 "hot" paths — 20 visits each
- 100 "warm" paths — 5 visits each
- 150 "cold" paths — 1 visit each
This exercises frecency ranking under real-world conditions, where some paths are visited far more often than others.
Stale Path Handling
200 directories, 40% deleted after seeding. tp checks Path::exists() on every candidate and self-heals stale entries — this costs extra I/O but keeps your results clean. Stale paths are pruned automatically so they don't pollute future results.
Scale (5,000 entries)
Tests whether performance holds at larger database sizes. With 5,000 tracked directories, tp exercises its SQLite indexes and fuzzy matching at a scale that approximates a power user's database after months of use.
Note on add Performance
tp's add command does more work than zoxide's equivalent — it detects project roots by walking up the directory tree for .git, Cargo.toml, etc., and logs session data. This is the cost of project-scoped search and session recall. Query performance is where it matters most, and tp matches or exceeds zoxide there.
Running Benchmarks Yourself
cargo build --release
./bench/bench.sh
python3 bench/chart.py # generate SVG charts
The benchmark scripts are in the bench/ directory. bench.sh runs hyperfine comparisons and outputs JSON results. chart.py reads those results and generates the SVG charts.
Contributing
Contributions to tp are welcome! Here's how to get started.
Setup
Clone the repository and build:
git clone https://github.com/pattynextdoor/tp.git
cd tp
cargo build
Running Tests
cargo test
To run tests with all feature flags:
cargo test --all-features
Running Benchmarks
Build a release binary first, then run the benchmark suite:
cargo build --release
./bench/bench.sh
python3 bench/chart.py # generate SVG charts
Project Structure
src/— Rust source codebench/— Benchmark scripts and chart generationdocs/— Documentation (this mdbook site and architecture diagrams)tests/— Integration tests
Code Style
The project uses standard Rust formatting and linting:
cargo fmt --check
cargo clippy
License
tp is licensed under MIT. By contributing, you agree that your contributions will be licensed under the same terms.