Getting started with inkentry

Install inkentry, understand an unfamiliar codebase in the first five minutes, then add memory, agents, and team sharing as you need them. No API keys or servers required to start.

inkentry is a single binary that helps you understand an unfamiliar codebase fast: find the code behind a concept, trace how a symbol connects across files, and assemble the context around a change, all from the CLI with no infrastructure to stand up. Run inkentry init once and the first search and context already tell you how the code fits together. As you keep working, it also records the decisions behind the code, so a later session (yours or a teammate's) does not re-derive them.

Where grep and code search tell you where a thing is, inkentry is built to tell you why it was decided. On a fresh repo there is no memory yet, so the first retrieval delivers fast code understanding; the why-layer fills in as you record decisions and, later, as an agent captures them for you.

Read this page in order the first time. Reach for the CLI reference and config reference for lookup afterwards.


Install

Install script (macOS and Linux) - recommended

Detects your OS and architecture, resolves the latest release, and installs both inkentry and inkentry-server to your $PATH:

curl -fsSL https://get.inkentry.com/install.sh | sh
inkentry --version

Homebrew (macOS and Linux)

Installs both binaries from the tap:

brew install inkentries/inkentry/inkentry
inkentry --version

Windows (PowerShell)

The script downloads the latest release and installs inkentry.exe and inkentry-server.exe under %LOCALAPPDATA%\Programs\inkentry, adding it to your user PATH:

iex ((New-Object Net.WebClient).DownloadString('https://get.inkentry.com/install.ps1'))
inkentry --version

Scoop, Debian and Ubuntu .deb packages, manual tarballs, and build-from-source instructions are on the releases page.


First commands

Open a terminal inside any git repository and run init once. That one command is the whole setup: it registers the project, parses and chunks the source tree, starts the bundled inkentry-server in the background when run interactively (if one is not already running), and hands the embedding pass to that server — so the prompt comes back after parsing rather than after the full embed:

cd /path/to/your/project
inkentry init

# 1. Find the code behind a concept — any phrase, not just an identifier
inkentry search "error handling"

# 2. Take an exact symbol name from those results and trace how it connects
inkentry search "<SymbolName>" --graph

The server bundles a native embedding model (codefuse-ai/F2LLM-v2-330M, an 896-dimension Q8_0 GGUF run through the candle runtime; it uses Metal or the GPU on macOS and the CPU elsewhere). The weights (~339 MB) download once on first use and are cached under your platform's local data directory, in an inkentry/models subfolder. There is no LM Studio, Ollama, or other external inference server to run by default.

init also writes .inkentry/.gitignore so the machine-specific SQLite files (index.db*, memory.db*) stay out of version control, while leaving .inkentry/config.toml tracked so it can be committed and shared. An existing .inkentry/.gitignore is never overwritten, so re-running init is safe.

Output looks like:

inkentry initialised for my-project

  Index:   142 files, 1840 chunks
  DB:      /path/to/my-project/.inkentry/index.db
  Project: my-project  (written to .inkentry/config.toml)
  Hook:    not installed  (run `inkentry hooks install` to add)
  Server:  http://127.0.0.1:7777  ✓  (auto-started)
  Memory:  configured notes fetch refspec on 'origin' (teammates' memory arrives on fetch)
           your memory stays local until you install the pre-push hook: inkentry hooks install --pre-push
           configured notes.rewriteRef (memory survives `git commit --amend` and `git rebase`)

Next steps:
  inkentry search "your query"
  inkentry context

The embed pass is handed to a background worker, so init returns before it finishes and prints no vector count; check progress later with inkentry status. The Memory: block appears only inside a git repository with an origin remote; outside one, init prints the reason it skipped and the command to configure it by hand.

Start with search: it takes a concept or a keyword, so it works on a repo you have never opened before. Full-text results are available the moment init has parsed the tree; semantic ranking improves them as embeddings land in the background. --only-text is explicit about wanting the no-server path.

--graph is the natural next step, and it resolves an exact symbol name rather than a concept phrase — feed it an identifier you just saw in your results, a function, type or method name.

Every command operates on a local project. In a directory with no .inkentry/ project they fail closed with a no inkentry project here error rather than falling back to a machine-global store.

Manage the background server

inkentry server start     # start the local daemon (idempotent; auto-binds 127.0.0.1)
inkentry server status    # PID, port, instance id, uptime
inkentry server logs      # last 50 lines of the server log
inkentry server stop      # stop the daemon

In non-interactive contexts (CI, agent harnesses) inkentry init does not auto-spawn the server. Run inkentry server start first if you want semantic search there, or set INKENTRY_NO_SERVER=1 to stay fully offline.

Troubleshooting: semantic search is not working

If inkentry search returns only text matches, the background server probably is not reachable and every command has fallen back to offline (text-only) search. Check the current tier:

inkentry server status    # is it running, and on what port?
inkentry status           # index statistics for the project
inkentry server logs      # last 50 lines of the server log

Windows: the first time inkentry-server starts, Windows Defender Firewall may prompt to allow it. Accept the prompt. If it was dismissed, the server is blocked on its loopback port, and every command silently falls back to offline search. Allow inkentry-server through the firewall, then re-run inkentry index ..

First run is slow: the embedding model (~339 MB) downloads once on first use. Give the server a moment to become healthy before you search, and watch progress with inkentry server logs.

Full-text results are available as soon as init has parsed the tree, so inkentry search "..." returns something useful while embeddings are still building. --only-text asks for that path explicitly and needs no server.

# Find code by meaning
inkentry search "error handling in the HTTP layer"

# Memory only, when you want the decision rather than the code
inkentry search "authentication" --only-memory

# With call-graph enrichment
inkentry search "authentication" --graph

# Fit results within a token budget
inkentry search "database layer" --budget 4000

Check index health at any time:

inkentry status          # index statistics, including an "Embedding in progress" line while the embed pass runs

Search and memory together

With your project indexed, code search and memory work together: search answers how and where, memory answers why.

# Record a decision as you make it
inkentry memory add --kind decision \
  --title "Chose token bucket for rate limiting" \
  --body "Simpler than sliding window; sufficient for low RPS"

# Read your decisions back
inkentry memory list --kind decision

# Find code by text (uses the full-text index inkentry init built)
inkentry search "handleRequest" --only-text

# Trace a symbol's call graph
inkentry search "Database" --graph

# Search memory for the reasoning behind the code
inkentry search "why did we choose this" --only-memory

# JSON output for agents
AGENT=true inkentry memory list --kind decision

Memory is stored in the project's local .inkentry/memory.db and, by default, mirrored to git notes so it travels with the repository. Passed together to a reasoning model, code and memory give a complete picture.


Configure your agent

This is where the payoff lands. If you code with an AI agent, you connect it to inkentry once and the why-layer starts filling itself: as the agent works, the reasoning behind each change is captured for you, with no time set aside to sit down and write it up. Every later inkentry context or inkentry search then hands those decisions back.

The mechanism is the agent itself. Wired to inkentry through a skill (the Claude Code skill, or a drop-in AGENT.md), it records each decision as it makes it, so the why-layer accrues as a by-product of the work. A git hook complements this: a post-commit step runs inkentry harvest to catch any reasoning left in commit messages, so nothing slips through.

Install the git hook once:

inkentry hooks install

Other developers without inkentry installed are unaffected: the hook is a no-op when inkentry is not on PATH. Remove it at any time:

inkentry hooks uninstall

At the start of a session, pull all prior context in one command:

# Start-of-session context - decisions, requirements, questions, handoffs
inkentry context

# JSON for machine processing
AGENT=true inkentry context

See the memory guide for how decisions, requirements, and handoffs are stored and retrieved.


Capability tiers: where inference and memory live

inkentry works at several capability tiers, and the team-memory tier can be a server you host yourself or the managed inkentry cloud (both are shown as rows below). You do not pick a tier by hand; inkentry uses the best one available and degrades cleanly when a server is not reachable. The load-bearing distinction is that a local server does inference only and never stores memory. Your memory always lives in the project's local memory.db until you explicitly configure a team server or point at inkentry cloud.

TierWhat runs itWhat it addsWhere memory lives
Built-in (zero infra)just the inkentry binarygit-notes memory, full-text search, code graphlocal memory.db
Local semantic servera loopback inkentry-server, auto-started on demandsemantic ranking for searchstill local memory.db: the server is inference only, never a memory store
Team memory servera shared inkentry-server you deploy, set via an explicit server_urlone shared memory index for the teamthe shared server you run: memory leaves your machine, your code stays local
inkentry cloud (hosted)a managed service: nothing to deploy or maintainthe same shared-team memory as a self-hosted server, without running onethe hosted service: memory leaves your machine, your code stays local

The local semantic server is auto-discovered on loopback (127.0.0.1) and started for you the first time a command needs it. It embeds queries and runs LLM calls, but a project's memory stays in memory.db regardless of whether it is running. Memory moves off the local machine only when you point at a team server: a self-hosted one via an explicit server_url, or the hosted inkentry cloud (see Share memory across a team below). Either way, each developer's code still stays local.

To stay fully offline (CI, air-gapped, or you just do not want a background process), set INKENTRY_NO_SERVER=1: inkentry then runs built-in only, and inference-only commands exit with a clear message instead of starting anything.


Share memory across a team

Working with a team? Point everyone at a shared server so they share decisions, requirements, and context instead of siloing them locally. This is a different server from the local one inkentry auto-starts for inference: it is a long-lived, shared instance the whole team reads and writes. Each developer's code stays local; only memory travels.

There are two ways to run it, and a project uses one or the other: the hosted inkentry cloud, or a self-hosted inkentry-server behind your own firewall.

inkentry cloud

The hosted option: nothing to deploy, patch, or keep running. Sign in, flip one switch, and the team shares memory.

Sign in once per machine (this opens your browser to approve the sign-in):

inkentry login

Then add .inkentry/config.toml at your repo root and commit it (it holds no secrets):

# .inkentry/config.toml - commit this
cloud = true
project_id = "github.com/my-org/my-awesome-project"

cloud = true is the whole switch. There is no URL to set: cloud is a fixed service and inkentry already knows where it lives. If you belong to more than one organisation, pin this repo to one with org = "your-org", or switch the active one with inkentry org switch.

Bring the memory already on your machine up to the cloud, then keep recording decisions as usual:

inkentry sync   # reconcile your local memory with the cloud

With cloud, the hosted service is the team's memory home.

Self-hosted team server

Prefer to run the server yourself? Deploy an inkentry-server (see the server setup guide) and point everyone at it with server_url instead of cloud:

# .inkentry/config.toml - commit this
server_url = "https://inkentry.internal.example.com"
project_id = "github.com/my-org/my-awesome-project"

server_url must be https:// unless it points at loopback (127.0.0.1, ::1, or localhost). A non-loopback http:// URL is rejected at startup, with no opt-out, because the CLI attaches your bearer token to these requests. See the server setup guide for putting TLS in front of a deployed server.

cloud and server_url are mutually exclusive: set one or the other, never both. inkentry stops at startup with an error explaining the conflict if it finds both.

Each developer provides their own API key. Set it with inkentry auth set-key --server <url>, which stores the key in your OS keychain (macOS Keychain, Linux Secret Service, Windows Credential Manager) rather than in plaintext, keyed by the server's origin. For CI or headless use, the INKENTRY_SERVER_KEY environment variable works everywhere and takes precedence:

export INKENTRY_SERVER_KEY="your-shared-api-key"

Bring your existing local memory up to the server, then keep recording decisions as usual:

inkentry sync   # reconcile your local memory with the server (usually not needed; see below)

In the default local_first mode you rarely run inkentry sync by hand. Your writes commit to the local memory.db immediately and never block on the network; from an interactive terminal a background reconciler then drains what you recorded up to the server and pulls teammates' entries down, so the shared memory converges on its own. inkentry sync is the explicit escape hatch for when you want that reconcile to happen synchronously now rather than in the background, such as a CI job that needs entries pushed before it exits. Code never travels; only memory does.


What's next

On this page