> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognee.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Hosted AI Companion

> Chat with a companion that knows your notes and remembers every earlier chat

Tell it something today, and a new chat next week still knows it.

## What You'll Build

You point cognee at a folder of notes: a journal, an Obsidian vault, any folder of text files. cognee remembers them, then you chat with a companion that answers from those notes. When the chat ends, cognee writes the chat itself into memory, so the next chat knows what you said. cognee's databases are local files on your machine; the LLM is the one your `.env` configures.

Building the memory takes one `cognee.remember` call. Each message is answered with one `cognee.recall` call, and one `cognee.improve` call saves the chat when it ends.

The complete cookbook is
[`examples/cookbooks/self_hosted_companion/`](https://github.com/topoteretes/cognee/tree/dev/examples/cookbooks/self_hosted_companion).

## Try It on Sample Data

The sample is three journal entries from the last three weeks. In one, you called your sister Lena: her birthday is on 4 October, and you plan to give her a pottery class voucher. The sample run asks the companion about it. You need only an [LLM key](/setup-configuration/llm-providers).

```bash theme={null}
git clone https://github.com/topoteretes/cognee.git && cd cognee
uv sync
echo 'LLM_API_KEY="your-key"' >> .env
```

`LLM_API_KEY` alone is enough for OpenAI, cognee's default for both the LLM and the embeddings. Other providers, such as Anthropic, Gemini, Azure OpenAI, AWS Bedrock or a local model through Ollama, need a few more lines in the same `.env`: [LLM Providers](/setup-configuration/llm-providers#provider-setup-guides) and [Embedding Providers](/setup-configuration/embedding-providers#provider-setup-guides) list them for each provider. Set both, because embeddings you leave at the default still need an OpenAI key.

<Tabs>
  <Tab title="Terminal">
    ```bash theme={null}
    uv run python examples/cookbooks/self_hosted_companion/self_hosted_companion.py --sample
    ```
  </Tab>

  <Tab title="Coding agent">
    The cognee repo ships a skill for this cookbook, [`.agents/skills/self-hosted-companion/SKILL.md`](https://github.com/topoteretes/cognee/blob/dev/.agents/skills/self-hosted-companion/SKILL.md). Claude Code and Codex find it on their own when you open them in the cognee folder. Ask in plain words, or type `/self-hosted-companion` in Claude Code:

    ```text theme={null}
    Ask my notes companion when my sister's birthday is, and what I was planning to get her.
    ```

    With no notes folder given, it answers from the sample notes and says so. Tell it the path to your own notes folder to chat with those instead. The agent sends each message as its own chat session, saved to memory, so a later message knows what an earlier one said.
  </Tab>
</Tabs>

```text theme={null}
[setup] CLEAR: the cookbook's dataset is forgotten before this run.
[setup] Wrote the sample from setup.py.
[clear] Nothing to forget: the dataset self_hosted_companion does not exist yet.
[ingest_notes] Remembered the notes in .../examples/cookbooks/self_hosted_companion/sample/notes
...
[chat] you> When is my sister's birthday, and what was I planning to get her?
[chat] companion> Your sister Lena’s birthday is **October 4**. You were planning to get her a **voucher for the ceramics studio on Linden Street**.
[chat] Saved this chat to memory.
```

The question never names Lena, the date or the studio. The companion found all three in a note from three weeks ago. Now tell it something no note contains, then ask about it in a new chat:

```bash theme={null}
uv run python examples/cookbooks/self_hosted_companion/scripts/chat.py --ask "Lena adopted a beagle called Pepper last weekend."
uv run python examples/cookbooks/self_hosted_companion/scripts/chat.py --ask "What is the name of Lena's dog?"
```

These call the chat script alone, because the notes are already remembered. Running the entry script with `--sample` again would first forget the dataset, chats included.

```text theme={null}
...
[chat] you> Lena adopted a beagle called Pepper last weekend.
[chat] companion> The provided context does not mention Lena adopting a beagle named Pepper last weekend.
[chat] Saved this chat to memory.
...
[chat] you> What is the name of Lena's dog?
[chat] companion> Lena’s dog is named Pepper.
[chat] Saved this chat to memory.
```

In the first chat, no note mentions Pepper, so the companion says so. That chat is saved to memory, and the second chat, a new session, answers from it.

## Run It on Your Data

* A folder of notes, such as `.md` or `.txt` files, at any depth. Every file in it is remembered, so keep only notes there. Pass its path to the entry script.

```bash theme={null}
uv run python examples/cookbooks/self_hosted_companion/self_hosted_companion.py --check ~/Documents/journal
uv run python examples/cookbooks/self_hosted_companion/self_hosted_companion.py ~/Documents/journal
uv run python examples/cookbooks/self_hosted_companion/self_hosted_companion.py ~/Documents/journal --ui
```

`--check` reports what is missing without doing any work. Without `--ask`, the chat waits for your messages until you type `/bye`. Running it again adds new notes and skips unchanged ones; add `--clear` to forget the dataset first and start over from your notes as they are now, which also forgets the earlier chats. Each script also runs alone, for example `uv run python examples/cookbooks/self_hosted_companion/scripts/chat.py`.

## How It Works

### Step 1: Start From an Empty Memory

Source: [`scripts/clear.py`](https://github.com/topoteretes/cognee/blob/dev/examples/cookbooks/self_hosted_companion/scripts/clear.py)

This step forgets what an earlier run remembered, so old copies never mix with new ones. It runs only with `--clear`, which a sample run turns on by default; `--no-clear` keeps the dataset.

```python theme={null}
await clear()
```

The sample notes are named after dates relative to today, so each day's sample differs from yesterday's. cognee's part is one call: [`cognee.forget(dataset="self_hosted_companion")`](/core-concepts/main-operations/forget), which deletes the dataset and everything extracted from it. That includes the earlier chats saved into it, so on your own notes use `--clear` only to start over.

### Step 2: Remember Your Notes Folder

Source: [`scripts/ingest_notes.py`](https://github.com/topoteretes/cognee/blob/dev/examples/cookbooks/self_hosted_companion/scripts/ingest_notes.py)

This step saves your notes so the companion can answer from them. It reads every file in the folder and its subfolders; there is no limit option, so point it at the folder you want the companion to know.

```python theme={null}
await ingest_notes(args.notes_folder)
```

With `--sample`, `args.notes_folder` is the sample folder. cognee's part is one call: [`cognee.remember`](/core-concepts/main-operations/remember) with the folder path, into the [*dataset*](/core-concepts/further-concepts/datasets) `self_hosted_companion`. A dataset is the named memory everything goes into. `remember` turns each file into a knowledge graph of people, plans and dates. Running it again skips notes it already holds; an edited note is added as a new document.

### Step 3: Chat With Your Companion

Source: [`scripts/chat.py`](https://github.com/topoteretes/cognee/blob/dev/examples/cookbooks/self_hosted_companion/scripts/chat.py)

This step runs the chat. Type messages, and `/bye` ends it; with `--ask`, it answers one message and ends.

```python theme={null}
await chat(args.ask)
```

Each message is one [`cognee.recall`](/core-concepts/main-operations/recall) with `HYBRID_COMPLETION`, which answers from the matching note passages and the graph around them, and a `session_id`. A [*session*](/guides/sessions) is short-term memory for one chat, so each answer sees the turns before it. `PROMPT` keeps the companion warm, brief, and honest when it does not know. When the chat ends, `cognee.improve(dataset="self_hosted_companion", session_ids=[session_id])` writes the chat into the graph. [`improve`](/core-concepts/main-operations/improve) is what lets the next chat know what you said in this one.

### Step 4: Browse the Graph

Source: [`scripts/ui.py`](https://github.com/topoteretes/cognee/blob/dev/examples/cookbooks/self_hosted_companion/scripts/ui.py)

This step opens cognee's UI so you can see what the companion remembers. It runs only when you pass `--ui`.

```python theme={null}
await open_ui()
```

The script starts cognee's API server in the same process, next to the databases the chat already has open, then `cognee.start_ui` starts the UI. Open [http://localhost:3000](http://localhost:3000) to browse the graph built from your notes and chats. The server listens on localhost only. Ctrl+C stops both.

## Make It Yours

* **Run it fully on your machine.** Point the LLM and the embeddings in `.env` at [Ollama](/guides/local-ollama), and your notes and chats never leave your computer; the scripts need no change. The README's [Run fully local](https://github.com/topoteretes/cognee/blob/dev/examples/cookbooks/self_hosted_companion/README.md#run-fully-local) section has the exact `.env`. Use the bare `LLM_ENDPOINT=http://localhost:11434` (with `/v1`, calls return 404), and set `AUTO_FEEDBACK=false` to skip a second LLM call per message that is slow on a local model.
* **Give it a different personality.** Edit `PROMPT` in `scripts/chat.py`: a coach that asks one follow-up question, or a study partner that quizzes you on your notes.
* **Point it at your team's wiki.** Pass a folder of exported Markdown pages instead of a journal, and you have a companion that answers from your team's docs and remembers what you asked it.
* **Start each chat with a check-in.** Before the chat loop in `scripts/chat.py`, call `reply("What did I say I'd do this week?", session_id)` and print the answer, so the companion opens the conversation.

## Clean Up

```bash theme={null}
uv run cognee-cli forget --dataset self_hosted_companion
```

To start over completely, also delete `sample/` in the cookbook folder.

<Columns cols={2}>
  <Card title="Sessions" icon="message-square" href="/guides/sessions">
    How a session keeps the turns of one chat together.
  </Card>

  <Card title="Improve" icon="sparkles" href="/core-concepts/main-operations/improve">
    How a finished chat becomes long-term memory.
  </Card>

  <Card title="Personalized Email" icon="mail-check" href="/cookbooks/personalized-email">
    Build another one: email replies that know your meetings.
  </Card>

  <Card title="Follow-Up Agent" icon="list-checks" href="/cookbooks/follow-up-agent">
    Build another one: next steps from your latest call, posted to Slack.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.