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.

ToolStrengthWeakness
zoxideFast, Rust, clean UXNo project awareness, no pinning, no AI, cold start
z.luaContext-aware jumpsSlower, Lua dependency, no project scoping
fasdTracks files & dirsUnmaintained since 2015
fastTravelCLIManual waypointsNo 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 matchingtp foo bar matches paths containing both tokens
  • Project awareness — auto-detection via .git, Cargo.toml, package.json, go.mod, and more
  • Project-scoped searchtp -p tests stays inside your project boundaries
  • Cross-project switchingtp @payments-service jumps to a known project root
  • Waypointstp --mark deploy pins a directory; tp :deploy teleports 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 cd compatibility — 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.

PhaseStatusShipping
AlphaCompleteCore binary: frecency, project detection, waypoints, 6-shell integration, bootstrap, zoxide import
BetaCompleteAI reranking (BYOK), TUI picker, session recall, query/remove/doctor commands. 95 tests, CI on 3 platforms.
v1.0PlannedSemantic project indexing, workflow prediction, natural language nav, VS Code extension.
ProPlannedCloud 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:

  1. Imports your zoxide database (if zoxide is installed)
  2. Parses your shell history (~/.zsh_history, ~/.bash_history, fish history) for cd targets
  3. 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

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

VariableDefaultDescription
TP_DATA_DIR$XDG_DATA_HOME/tpDatabase and config location
TP_API_KEYAnthropic API key for AI features
TP_AI_MODELclaude-haiku-4-5-20251001AI model override
TP_AI_TIMEOUT2000AI request timeout (ms)
TP_EXCLUDE_DIRSComma-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):

  1. Exact/relative path — if the query is a valid path, cd directly
  2. Waypoint lookup: prefix triggers a pin lookup
  3. Project lookup@ prefix triggers a project root lookup
  4. Frecency + fuzzy match — the local scoring engine handles ~95% of queries 4b. Typo tolerance — Damerau-Levenshtein fallback when fuzzy matching returns nothing
  5. AI reranking — fires only when local scores are ambiguous (~150 tokens, <300ms)
  6. 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 visitedWeight
< 5 minutes4.0×
< 1 hour2.0×
< 1 day1.0×
< 1 week0.5×
older0.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:

TierScoreExample (querypath)
Exact last component1.0api/home/user/projects/api
Suffix of last component0.9api/home/user/projects/my-api
Substring anywhere0.7proj/home/user/projects/api
Multi-word (all tokens present)0.6user api/home/user/projects/api
No match0.0zzz/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. projetcsprojects).

Query lengthMax allowed edits
< 5 chars(skipped — too many false positives)
5–8 chars1
9+ chars2

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, tp navigates 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 code
  • bench/ — Benchmark scripts and chart generation
  • docs/ — 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.