> For the complete documentation index, see [llms.txt](https://docs.gitloom.cloud/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gitloom.cloud/documentation/content/cli.md).

# CLI

The CLI keeps memory in a git repository on your machine. Same engine as the hosted API, no network on the read path, and every operation is also available to an assistant over MCP.

### Install

```bash
curl -fsSL https://gitloom.cloud/install.sh | sh
```

One static binary, no runtime dependency. The installer verifies a checksum and puts it in `/usr/local/bin` if that is writable, `~/.local/bin` otherwise — override with `GITLOOM_PREFIX`.

Or take an archive directly from `https://gitloom.cloud/dl/`: builds exist for macOS (Apple silicon and Intel), Linux (x86-64 and arm64) and Windows, with `SHA256SUMS` alongside them.

:::note\[macOS quarantine] The binaries are not code-signed yet. A browser download will be quarantined — `xattr -d com.apple.quarantine /path/to/gitloom` clears it. The `curl | sh` route is normally exempt. :::

The local CLI is licensed software. Create a licence key at [app.gitloom.cloud](https://app.gitloom.cloud/) and activate once:

```bash
gitloom license activate gll_...
```

Activation exchanges the key for a signed token that is verified **offline**, so day-to-day use needs no network. It renews itself when you are online and nearing expiry. `version`, `license` and `--help` work without a licence.

### Which memory?

You will have more than one — personal, per-project, a scratch one. A command resolves its memory in this order, and `gitloom repo where` tells you which and why:

1. `--repo <path>`
2. `GITLOOM_REPO`
3. a memory at or above the working directory — the way `git` finds a repository
4. the one selected with `gitloom repo use`

```bash
gitloom init ~/memories/work        # creates, registers and selects it
gitloom init ~/memories/personal
gitloom repo list
#   personal  ~/memories/personal
# * work      ~/memories/work

gitloom repo use personal           # change the default
gitloom repo where                  # which one would this command use?
```

Standing anywhere inside a memory selects it, so a project that keeps its memory alongside the code needs no flags and no configuration.

:::note\[A wrong path is an error, not a new memory] Earlier versions created a repository wherever `--repo` pointed. That turned a typo into an empty memory in a surprising place, with no sign anything was wrong. A path that is not a memory is now refused, and `gitloom init` is the only thing that creates one. :::

### Writing and reading

```bash
# store a memory (body on stdin)
echo "Maya moved to Lisbon in March 2026." |
  gitloom write -p facts/people/maya.md --tags person -m "maya moved"

# ranked search over structure and full text
gitloom search "where does maya live"

# one memory, or one section of one
gitloom get facts/people/maya.md
gitloom section facts/people/maya.md#housing
```

Every command takes `--json` when you want to pipe it somewhere.

### Navigating instead of retrieving

A memory's `##` headers are indexed as their own nodes, which makes the store a navigable table of contents rather than a pile of files. That is the PageIndex loop: descend the tree, then pull only the section you decided you wanted.

```bash
gitloom tree                       # whole table of contents
gitloom tree facts/db --depth 2    # one subtree
gitloom section facts/db/replication.md#failover
```

It matters at scale. Retrieving whole documents and hoping the answer is inside them costs context and buries the sentence you needed; descending to a section costs two cheap calls.

### Following relationships

Memories link to each other with `[[wikilinks]]` and labelled relations.

```bash
gitloom related facts/people/maya.md
gitloom related facts/people/maya.md --label spouse
gitloom related facts/db/replication.md --direction in --depth 2
```

`--direction in` finds what points *at* a memory — the question "what else depends on this?" that a search cannot answer. Depth beyond 1 pulls a cluster rather than a neighbour list; useful deliberately, expensive as a habit.

### Semantic search

Semantic search only sees memories whose retrieval cues have been embedded. Writing a memory queues its cues; draining that queue is explicit:

```bash
gitloom embed --stats     # how much is covered
gitloom embed             # embed what is pending
```

### Querying the index directly

The index is a SQLite database derived entirely from git — nodes, the section tree, an FTS5 table, cue vectors, the link graph. `gitloom rebuild` recreates it from scratch, so reading it is safe and writing to it is refused by the database itself.

```bash
gitloom index stats
gitloom index schema nodes
gitloom index query "SELECT tier, count(*) FROM nodes WHERE kind='file' GROUP BY tier"
```

:::note\[Read-only is enforced, not checked] The connection is opened in SQLite's read-only mode. Matching on the word `INSERT` would be trivially defeated and would give false comfort. :::

### Ingestion and answering

`ingest` turns conversations into memories: it extracts what is durable, places it in a tier, folds it into an existing memory where it updates one rather than repeating it, and attaches retrieval cues.

```bash
gitloom ingest sessions.json
cat chat.jsonl | gitloom ingest --provider openai --model gpt-5
```

Input is a JSON array of sessions, or one per line:

```json
{"id":"s1","date":"2026-03-04T10:00:00Z","turns":[
  {"role":"user","content":"I moved to Lisbon"},
  {"role":"assistant","content":"How is it?"}]}
```

`answer` retrieves and has a model write the sentence:

```bash
gitloom answer "where does Maya live?" --evidence
```

Both need a model, and both use **your** provider key — `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and so on, or `--base-url` for a local server. Your licence is a flat fee; inference is between you and your provider.

### MCP server

Every operation above is exposed to an assistant over the Model Context Protocol. The tools are generated from the same definitions the CLI dispatches through, so the two cannot drift apart.

```bash
gitloom mcp --repo ~/memory              # stdio: what editors launch
gitloom mcp --read-only                  # search and recall, no writes
gitloom mcp --http 127.0.0.1:7000 --token "$(openssl rand -hex 16)"
```

#### Connecting an agent

`gitloom install` writes the configuration in each host's own shape:

```bash
gitloom install claude-code      # print it
gitloom install codex --write    # write it
gitloom install opencode --project
```

Supported: `claude-code`, `openclaw`, `opencode`, `codex`, `hermes`. All of them speak MCP, so there is no plugin to install — GitLoom already serves the protocol and this just points them at it.

To use a hosted namespace instead of a memory on this machine, add `--cloud`. That points the host at [`@gitloomhq/mcp`](https://www.npmjs.com/package/@gitloomhq/mcp) via `npx`, which needs `GITLOOM_API_KEY` and no local repository at all:

```bash
export GITLOOM_API_KEY=gl_live_...
gitloom install claude-code --cloud --write
```

Claude Desktop, in `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "gitloom": {
      "command": "gitloom",
      "args": ["mcp", "--repo", "/absolute/path/to/memory"]
    }
  }
}
```

:::caution\[Do not serve this to a network without a token] The tools include `remember`, which commits, and `index_query`, which reads everything. Binding a public address without `--token` is refused outright. :::

Model-driven tools (`ingest`, `answer`) appear only when a model is configured via `GITLOOM_MODEL` and a provider key, so a client listing tools sees what will actually work rather than operations that fail on every call.

### Working with the cloud

The local CLI and the hosted API are separate memories. `gitloom cloud` reaches the hosted one, authenticated with an API key in `GITLOOM_API_KEY` — separate from your licence, so either can be rotated without disturbing the other.

```bash
gitloom cloud whoami
gitloom cloud namespaces --create staging
gitloom cloud recall "where does maya live" --namespace staging
gitloom cloud push --namespace staging --dry-run
```

`push` uploads finished memories as they are — ingestion is not re-run, no model is called, and the text you curated locally is what lands.

### Environment

| Variable           | Purpose                                                        |
| ------------------ | -------------------------------------------------------------- |
| `GITLOOM_API_KEY`  | API key for `gitloom cloud`                                    |
| `GITLOOM_MODEL`    | model for `ingest`, `answer`, and the MCP tools that need one  |
| `GITLOOM_PROVIDER` | provider name (default `anthropic`)                            |
| `GITLOOM_BASE_URL` | OpenAI-compatible endpoint, overrides the provider             |
| `GITLOOM_API`      | API base URL, for pointing at a different deployment           |
| `GITLOOM_REPO`     | which memory to use, when not passing `--repo`                 |
| `GITLOOM_HOME`     | where the licence and registry live (default: your config dir) |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.gitloom.cloud/documentation/content/cli.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
