khoj Documentation

Your AI second brain. Self-hostable. Get answers from the web or your docs. Build custom agents, schedule automations, do deep research.

37,779 stars Python Python 1 file · ~49,096 tokens #agent#ai#assistant#chat#chatgpt#emacs#image-generation#llama3
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy khoj on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name khoj -p 5900:5900 --restart always ghcr.io/khoj-ai/khoj-computer:latest
Configured Services & Ports
⚙️ database
image: docker.io/pgvector/pgvector:pg15
⚙️ sandbox
image: ghcr.io/khoj-ai/terrarium:latest
⚙️ search
image: docker.io/searxng/searxng:latest
⚙️ computer
image: ghcr.io/khoj-ai/khoj-computer:latest
🔌 Ports: 5900:5900
⚙️ server
image: ghcr.io/khoj-ai/khoj:latest
🔌 Ports: 42110:42110
docker-compose.yml
yaml (docker-compose.yml)
services:
  database:
    image: docker.io/pgvector/pgvector:pg15
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
    volumes:
      - khoj_db:/var/lib/postgresql/data/
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 30s
      timeout: 10s
      retries: 5
  sandbox:
    image: ghcr.io/khoj-ai/terrarium:latest
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 2
  search:
    image: docker.io/searxng/searxng:latest
    volumes:
      - khoj_search:/etc/searxng
    environment:
      - SEARXNG_BASE_URL=http://localhost:8080/
  # Creates Computer for Khoj to use.
  # Set KHOJ_OPERATOR_ENABLED=True in the server service environment variable to enable.
  computer:
    container_name: khoj-computer
    image: ghcr.io/khoj-ai/khoj-computer:latest
    # build:
    #   context: .
    #   dockerfile: computer.Dockerfile
    ports:
      - "5900:5900"
    volumes:
      - khoj_computer:/home/operator
  server:
    depends_on:
      database:
        condition: service_healthy
    # Use the following line to use the latest version of khoj. Otherwise, it will build from source. Set this to ghcr.io/khoj-ai/khoj-cloud:latest if you want to use the prod image.
    image: ghcr.io/khoj-ai/khoj:latest
    # Uncomment the following line to build from source. This will take a few minutes. Comment the next two lines out if you want to use the official image.
    # build:
      # context: .
    ports:
      # If changing the local port (left hand side), no other changes required.
      # If changing the remote port (right hand side),
      #   change the port in the args in the build section,
      #   as well as the port in the command section to match
      - "42110:42110"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    working_dir: /app
    volumes:
      - khoj_config:/root/.khoj/
      - khoj_models:/root/.cache/torch/sentence_transformers
      - khoj_models:/root/.cache/huggingface
      # uncomment line below to mount docker socket to allow khoj to use its computer.
      # - /var/run/docker.sock:/var/run/docker.sock
    # Use 0.0.0.0 to explicitly set the host ip for the service on the container. https://pythonspeed.com/articles/docker-connection-refused/
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_HOST=database
      - POSTGRES_PORT=5432
      - KHOJ_DJANGO_SECRET_KEY=secret
      - KHOJ_DEBUG=False
      - [email protected]
      - KHOJ_ADMIN_PASSWORD=password
      # Default URL of Terrarium, the default Python sandbox used by Khoj to run code. Its container is specified above
      - KHOJ_TERRARIUM_URL=http://sandbox:8080
      # Uncomment line below to have Khoj run code in remote E2B code sandbox instead of the self-hosted Terrarium sandbox above. Get your E2B API key from https://e2b.dev/.
      # - E2B_API_KEY=your_e2b_api_key
      # Default URL of SearxNG, the default web search engine used by Khoj. Its container is specified above
      - KHOJ_SEARXNG_URL=http://search:8080
      # Uncomment line below to use with Ollama running on your local machine at localhost:11434.
      # Change URL to use with other OpenAI API compatible providers like VLLM, LMStudio, DeepInfra, DeepSeek etc.
      # - OPENAI_BASE_URL=http://host.docker.internal:11434/v1/
      # - KHOJ_DEFAULT_CHAT_MODEL=qwen3
      #
      # Uncomment appropriate lines below to use chat models by OpenAI, Anthropic, Google.
      # Ensure you set your provider specific API keys.
      # ---
      # - OPENAI_API_KEY=your_openai_api_key
      # - GEMINI_API_KEY=your_gemini_api_key
      # - ANTHROPIC_API_KEY=your_anthropic_api_key
      #
      # Uncomment line below to enable Khoj to use its computer.
      # - KHOJ_OPERATOR_ENABLED=True
      # Uncomment appropriate lines below to enable web results with Khoj
      # Ensure you set your provider specific API keys.
      # ---
      # Paid, Fast API. Only does web search. Get API key from https://serper.dev/
      # - SERPER_DEV_API_KEY=your_serper_dev_api_key
      # Paid, Higher Read Success API. Only does webpage read. Get API key from https://olostep.com/
      # - OLOSTEP_API_KEY=your_olostep_api_key
      # Paid, Open API. Does both web search and webpage read. Get API key from https://firecrawl.dev/
      # - FIRECRAWL_API_KEY=your_firecrawl_api_key
      # Paid, Fast API. Does both web search and webpage read. Get API key from https://exa.ai/
      # - EXA_API_KEY=your_exa_api_key
      #
      # Uncomment the necessary lines below to make your instance publicly accessible.
      # Proceed with caution, especially if you are using anonymous mode.
      # ---
      # - KHOJ_NO_HTTPS=True
      # Replace the KHOJ_DOMAIN with the server's externally accessible domain or I.P address from a remote machie (no http/https prefix).
      # Ensure this is set correctly to avoid CSRF trusted origin or unset cookie issue when trying to access the admin panel.
      # - KHOJ_DOMAIN=192.168.0.104
      # - KHOJ_DOMAIN=khoj.example.com
      # Replace the KHOJ_ALLOWED_DOMAIN with the server's internally accessible domain or I.P address on the host machine (no http/https prefix).
      # Only set if using a load balancer/reverse_proxy in front of your Khoj server. If unset, it defaults to KHOJ_DOMAIN.
      # For example, if the load balancer service is added to the khoj docker network, set KHOJ_ALLOWED_DOMAIN to khoj's docker service name: `server'.
      # - KHOJ_ALLOWED_DOMAIN=server
      # - KHOJ_ALLOWED_DOMAIN=127.0.0.1
      # Uncomment the line below to disable telemetry.
      # Telemetry helps us prioritize feature development and understand how people are using Khoj
      # Read more at https://docs.khoj.dev/miscellaneous/telemetry
      # - KHOJ_TELEMETRY_DISABLE=True
    # Comment out this line when you're using the official ghcr.io/khoj-ai/khoj-cloud:latest prod image.
    command: --host="0.0.0.0" --port=42110 -vv --anonymous-mode --non-interactive

volumes:
  khoj_config:
  khoj_db:
  khoj_models:
  khoj_search:
  khoj_computer:

File: README.md


🎁 New

  • Meet 🌶️ Pipali - our open-source AI coworker that runs on your computer.
  • Read about Khoj's excellent performance on modern retrieval and reasoning benchmarks.

Overview

Khoj is a personal AI app to extend your capabilities. It smoothly scales up from an on-device personal AI to a cloud-scale enterprise AI.

  • Chat with any local or online LLM (e.g llama3, qwen, gemma, mistral, gpt, claude, gemini, deepseek).
  • Get answers from the internet and your docs (including image, pdf, markdown, org-mode, word, notion files).
  • Access it from your Browser, Obsidian, Emacs, Desktop, Phone or Whatsapp.
  • Create agents with custom knowledge, persona, chat model and tools to take on any role.
  • Automate away repetitive research. Get personal newsletters and smart notifications delivered to your inbox.
  • Find relevant docs quickly and easily using our advanced semantic search.
  • Generate images, talk out loud, play your messages.
  • Khoj is open-source, self-hostable. Always.
  • Run it privately on your computer or try it on our cloud app.

See it in action

Go to https://app.khoj.dev to see Khoj live.

Full feature list

You can see the full feature list here.

Self-Host

To get started with self-hosting Khoj, read the docs.

Enterprise

Khoj is available as a cloud service, on-premises, or as a hybrid solution. To learn more about Khoj Enterprise, visit our website.

Frequently Asked Questions (FAQ)

Q: Can I use Khoj without self-hosting?

Yes! You can use Khoj right away at https://app.khoj.dev — no setup required.

Q: What kinds of documents can Khoj read?

Khoj supports a wide variety: PDFs, Markdown, Notion, Word docs, org-mode files, and more.

Q: How can I make my own agent?

Check out this blog post for a step-by-step guide to custom agents.
For more questions, head over to our Discord!

Contributors

Cheers to our awesome contributors! 🎉

Made with contrib.rocks.

Interested in Contributing?

Khoj is open source. It is sustained by the community and we’d love for you to join it! Whether you’re a coder, designer, writer, or enthusiast, there’s a place for you.

Why Contribute?

  • Make an Impact: Help build, test and improve a tool used by thousands to boost productivity.
  • Learn & Grow: Work on cutting-edge AI, LLMs, and semantic search technologies.

You can help us build new features, improve the project documentation, report issues and fix bugs. If you're a developer, please see our Contributing Guidelines and check out good first issues to work on.


File: docker-compose.yml

services:
database:
image: docker.io/pgvector/pgvector:pg15
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
volumes:
- khoj_db:/var/lib/postgresql/data/
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 30s
timeout: 10s
retries: 5
sandbox:
image: ghcr.io/khoj-ai/terrarium:latest
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 2
search:
image: docker.io/searxng/searxng:latest
volumes:
- khoj_search:/etc/searxng
environment:
- SEARXNG_BASE_URL=http://localhost:8080/

Creates Computer for Khoj to use.

Set KHOJ_OPERATOR_ENABLED=True in the server service environment variable to enable.

computer:
container_name: khoj-computer
image: ghcr.io/khoj-ai/khoj-computer:latest
# build:
# context: .
# dockerfile: computer.Dockerfile
ports:
- "5900:5900"
volumes:
- khoj_computer:/home/operator
server:
depends_on:
database:
condition: service_healthy
# Use the following line to use the latest version of khoj. Otherwise, it will build from source. Set this to ghcr.io/khoj-ai/khoj-cloud:latest if you want to use the prod image.
image: ghcr.io/khoj-ai/khoj:latest
# Uncomment the following line to build from source. This will take a few minutes. Comment the next two lines out if you want to use the official image.
# build:
# context: .
ports:
# If changing the local port (left hand side), no other changes required.
# If changing the remote port (right hand side),
# change the port in the args in the build section,
# as well as the port in the command section to match
- "42110:42110"
extra_hosts:
- "host.docker.internal:host-gateway"
working_dir: /app
volumes:
- khoj_config:/root/.khoj/
- khoj_models:/root/.cache/torch/sentence_transformers
- khoj_models:/root/.cache/huggingface
# uncomment line below to mount docker socket to allow khoj to use its computer.
# - /var/run/docker.sock:/var/run/docker.sock
# Use 0.0.0.0 to explicitly set the host ip for the service on the container. https://pythonspeed.com/articles/docker-connection-refused/
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_HOST=database
- POSTGRES_PORT=5432
- KHOJ_DJANGO_SECRET_KEY=secret
- KHOJ_DEBUG=False
- KHOJ_ADMIN_EMAIL=[email protected]
- KHOJ_ADMIN_PASSWORD=password
# Default URL of Terrarium, the default Python sandbox used by Khoj to run code. Its container is specified above
- KHOJ_TERRARIUM_URL=http://sandbox:8080
# Uncomment line below to have Khoj run code in remote E2B code sandbox instead of the self-hosted Terrarium sandbox above. Get your E2B API key from https://e2b.dev/.
# - E2B_API_KEY=your_e2b_api_key
# Default URL of SearxNG, the default web search engine used by Khoj. Its container is specified above
- KHOJ_SEARXNG_URL=http://search:8080
# Uncomment line below to use with Ollama running on your local machine at localhost:11434.
# Change URL to use with other OpenAI API compatible providers like VLLM, LMStudio, DeepInfra, DeepSeek etc.
# - OPENAI_BASE_URL=http://host.docker.internal:11434/v1/
# - KHOJ_DEFAULT_CHAT_MODEL=qwen3
#
# Uncomment appropriate lines below to use chat models by OpenAI, Anthropic, Google.
# Ensure you set your provider specific API keys.
# ---
# - OPENAI_API_KEY=your_openai_api_key
# - GEMINI_API_KEY=your_gemini_api_key
# - ANTHROPIC_API_KEY=your_anthropic_api_key
#
# Uncomment line below to enable Khoj to use its computer.
# - KHOJ_OPERATOR_ENABLED=True
# Uncomment appropriate lines below to enable web results with Khoj
# Ensure you set your provider specific API keys.
# ---
# Paid, Fast API. Only does web search. Get API key from https://serper.dev/
# - SERPER_DEV_API_KEY=your_serper_dev_api_key
# Paid, Higher Read Success API. Only does webpage read. Get API key from https://olostep.com/
# - OLOSTEP_API_KEY=your_olostep_api_key
# Paid, Open API. Does both web search and webpage read. Get API key from https://firecrawl.dev/
# - FIRECRAWL_API_KEY=your_firecrawl_api_key
# Paid, Fast API. Does both web search and webpage read. Get API key from https://exa.ai/
# - EXA_API_KEY=your_exa_api_key
#
# Uncomment the necessary lines below to make your instance publicly accessible.
# Proceed with caution, especially if you are using anonymous mode.
# ---
# - KHOJ_NO_HTTPS=True
# Replace the KHOJ_DOMAIN with the server's externally accessible domain or I.P address from a remote machie (no http/https prefix).
# Ensure this is set correctly to avoid CSRF trusted origin or unset cookie issue when trying to access the admin panel.
# - KHOJ_DOMAIN=192.168.0.104
# - KHOJ_DOMAIN=khoj.example.com
# Replace the KHOJ_ALLOWED_DOMAIN with the server's internally accessible domain or I.P address on the host machine (no http/https prefix).
# Only set if using a load balancer/reverse_proxy in front of your Khoj server. If unset, it defaults to KHOJ_DOMAIN.
# For example, if the load balancer service is added to the khoj docker network, set KHOJ_ALLOWED_DOMAIN to khoj's docker service name: `server'.
# - KHOJ_ALLOWED_DOMAIN=server
# - KHOJ_ALLOWED_DOMAIN=127.0.0.1
# Uncomment the line below to disable telemetry.
# Telemetry helps us prioritize feature development and understand how people are using Khoj
# Read more at https://docs.khoj.dev/miscellaneous/telemetry
# - KHOJ_TELEMETRY_DISABLE=True
# Comment out this line when you're using the official ghcr.io/khoj-ai/khoj-cloud:latest prod image.
command: --host="0.0.0.0" --port=42110 -vv --anonymous-mode --non-interactive

volumes:
khoj_config:
khoj_db:
khoj_models:
khoj_search:
khoj_computer:


File: manifest.json

{
"id": "khoj",
"name": "Khoj",
"version": "2.0.0-beta.28",
"minAppVersion": "0.15.0",
"description": "Your Second Brain",
"author": "Khoj Inc.",
"authorUrl": "https://github.com/khoj-ai",
"isDesktopOnly": false
}


File: versions.json

{
"0.2.1": "0.15.0",
"0.2.5": "0.15.0",
"0.2.6": "0.15.0",
"0.3.0": "0.15.0",
"0.4.0": "0.15.0",
"0.5.0": "0.15.0",
"0.6.0": "0.15.0",
"0.6.1": "0.15.0",
"0.6.2": "0.15.0",
"0.7.0": "0.15.0",
"0.7.1": "0.15.0",
"0.8.0": "0.15.0",
"0.8.1": "0.15.0",
"0.8.2": "0.15.0",
"0.9.0": "0.15.0",
"0.10.0": "0.15.0",
"0.10.1": "0.15.0",
"0.11.0": "0.15.0",
"0.11.1": "0.15.0",
"0.11.2": "0.15.0",
"0.11.3": "0.15.0",
"0.11.4": "0.15.0",
"0.12.0": "0.15.0",
"0.12.1": "0.15.0",
"0.12.2": "0.15.0",
"0.12.3": "0.15.0",
"0.13.0": "0.15.0",
"0.14.0": "0.15.0",
"1.0.0": "0.15.0",
"1.0.1": "0.15.0",
"1.1.0": "0.15.0",
"1.2.0": "0.15.0",
"1.2.1": "0.15.0",
"1.3.0": "0.15.0",
"1.4.0": "0.15.0",
"1.5.0": "0.15.0",
"1.5.1": "0.15.0",
"1.6.0": "0.15.0",
"1.6.1": "0.15.0",
"1.6.2": "0.15.0",
"1.7.0": "0.15.0",
"1.8.0": "0.15.0",
"1.9.0": "0.15.0",
"1.10.0": "0.15.0",
"1.10.1": "0.15.0",
"1.10.2": "0.15.0",
"1.11.0": "0.15.0",
"1.11.1": "0.15.0",
"1.11.2": "0.15.0",
"1.12.0": "0.15.0",
"1.12.1": "0.15.0",
"1.13.0": "0.15.0",
"1.14.0": "0.15.0",
"1.15.0": "0.15.0",
"1.16.0": "0.15.0",
"1.17.0": "0.15.0",
"1.20.0": "0.15.0",
"1.20.1": "0.15.0",
"1.20.2": "0.15.0",
"1.20.3": "0.15.0",
"1.20.4": "0.15.0",
"1.21.0": "0.15.0",
"1.21.1": "0.15.0",
"1.21.2": "0.15.0",
"1.21.3": "0.15.0",
"1.21.4": "0.15.0",
"1.21.5": "0.15.0",
"1.21.6": "0.15.0",
"1.22.0": "0.15.0",
"1.22.1": "0.15.0",
"1.22.2": "0.15.0",
"1.22.3": "0.15.0",
"1.23.0": "0.15.0",
"1.23.1": "0.15.0",
"1.23.2": "0.15.0",
"1.23.3": "0.15.0",
"1.24.0": "0.15.0",
"1.24.1": "0.15.0",
"1.25.0": "0.15.0",
"1.26.0": "0.15.0",
"1.26.1": "0.15.0",
"1.26.2": "0.15.0",
"1.26.3": "0.15.0",
"1.26.4": "0.15.0",
"1.27.0": "0.15.0",
"1.27.1": "0.15.0",
"1.28.0": "0.15.0",
"1.28.1": "0.15.0",
"1.28.2": "0.15.0",
"1.28.3": "0.15.0",
"1.29.0": "0.15.0",
"1.29.1": "0.15.0",
"1.30.0": "0.15.0",
"1.30.1": "0.15.0",
"1.30.2": "0.15.0",
"1.30.3": "0.15.0",
"1.30.4": "0.15.0",
"1.30.5": "0.15.0",
"1.30.6": "0.15.0",
"1.30.7": "0.15.0",
"1.30.8": "0.15.0",
"1.30.9": "0.15.0",
"1.30.10": "0.15.0",
"1.31.0": "0.15.0",
"1.32.0": "0.15.0",
"1.32.1": "0.15.0",
"1.32.2": "0.15.0",
"1.33.0": "0.15.0",
"1.33.1": "0.15.0",
"1.33.2": "0.15.0",
"1.34.0": "0.15.0",
"1.35.0": "0.15.0",
"1.35.1": "0.15.0",
"1.35.2": "0.15.0",
"1.35.3": "0.15.0",
"1.36.0": "0.15.0",
"1.36.1": "0.15.0",
"1.36.2": "0.15.0",
"1.36.3": "0.15.0",
"1.36.4": "0.15.0",
"1.36.5": "0.15.0",
"1.36.6": "0.15.0",
"1.37.0": "0.15.0",
"1.37.1": "0.15.0",
"1.37.2": "0.15.0",
"1.38.0": "0.15.0",
"1.39.0": "0.15.0",
"1.40.0": "0.15.0",
"1.41.0": "0.15.0",
"1.42.0": "0.15.0",
"1.42.1": "0.15.0",
"1.42.2": "0.15.0",
"1.42.3": "0.15.0",
"1.42.4": "0.15.0",
"1.42.5": "0.15.0",
"1.42.6": "0.15.0",
"1.42.7": "0.15.0",
"1.42.8": "0.15.0",
"2.0.0-beta.1": "0.15.0",
"2.0.0-beta.2": "0.15.0",
"2.0.0-beta.3": "0.15.0",
"2.0.0-beta.4": "0.15.0",
"2.0.0-beta.5": "0.15.0",
"2.0.0-beta.6": "0.15.0",
"2.0.0-beta.7": "0.15.0",
"2.0.0-beta.8": "0.15.0",
"2.0.0-beta.9": "0.15.0",
"2.0.0-beta.10": "0.15.0",
"2.0.0-beta.11": "0.15.0",
"2.0.0-beta.12": "0.15.0",
"2.0.0-beta.13": "0.15.0",
"2.0.0-beta.14": "0.15.0",
"2.0.0-beta.15": "0.15.0",
"2.0.0-beta.16": "0.15.0",
"2.0.0-beta.17": "0.15.0",
"2.0.0-beta.18": "0.15.0",
"2.0.0-beta.19": "0.15.0",
"2.0.0-beta.20": "0.15.0",
"2.0.0-beta.21": "0.15.0",
"2.0.0-beta.22": "0.15.0",
"2.0.0-beta.23": "0.15.0",
"2.0.0-beta.24": "0.15.0",
"2.0.0-beta.25": "0.15.0",
"2.0.0-beta.26": "0.15.0",
"2.0.0-beta.27": "0.15.0",
"2.0.0-beta.28": "0.15.0"
}


File: .pre-commit-config.yaml

repos:


File: documentation/README.md

Website

This website is built using Docusaurus, a modern static website generator.

Installation

text
$ yarn

Local Development

text
$ yarn start

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

Build

text
$ yarn build

This command generates static content into the build directory and can be served using any static contents hosting service.

Deployment

Using SSH:

text
$ USE_SSH=true yarn deploy

Not using SSH:

text
$ GIT_USER=<Your GitHub username> yarn deploy

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the gh-pages branch.


File: documentation/package.json

{
"name": "documentation",
"version": "0.0.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "^3.9.2",
"@docusaurus/plugin-sitemap": "^3.9.2",
"@docusaurus/preset-classic": "^3.9.2",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"webpack-dev-server": "^5.2.4"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.9.2",
"@docusaurus/types": "^3.9.2"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 3 chrome version",
"last 3 firefox version",
"last 5 safari version"
]
},
"engines": {
"node": ">=18.0"
},
"resolutions": {
"picomatch": ">=2.3.2",
"serialize-javascript": "^7.0.5",
"webpack-dev-server": "^5.2.4"
}
}


File: documentation/docs/advanced/_category_.json

{
"label": "Advanced Self Hosting",
"position": 6,
"link": {
"type": "generated-index",
"description": "Advanced setup for Self Hosting Khoj server"
}
}


File: documentation/docs/advanced/admin.md

Admin Panel

Describes the Khoj settings configurable via the admin panel

By default, your admin panel is available at http://localhost:42110/server/admin/. You can access the admin panel by logging in with your admin credentials (this would be your KHOJ_ADMIN_EMAIL and KHOJ_ADMIN_PASSWORD). The admin panel allows you to configure various settings for your Khoj server.

App Settings

Agents

Add all the agents you want to use for your different use-cases like Writer, Researcher, Therapist etc.

  • Personality: This is a prompt to tell the chat model how to tune the personality of the agent.
  • Chat model: The chat model to use for the agent.
  • Name: The name of the agent. This field helps give the agent a unique identity across the app.
  • Avatar: Url to the agents profile picture. It helps give the agent a unique visual identity across the app.
  • Style color, Style icon: These fields help give the agent a unique, visually identifiable identity across the app.
  • Slug: This is the agent name to use in urls.
  • Public: Check this if the agent is expected to be visible to all users on this Khoj server.
  • Managed by admin: Check this if the agent is managed by admin, not by any user.
  • Creator: The user who created the agent.
  • Tools: The list of tools available to this agent. Tools include notes, image, online. This field is not currently configurable and only supports all tools (i.e ["*"])

Chat Model Options

Add all the chat models you want to try, use and switch between for your different use-cases. For each chat model you add:

  • Chat model: The name of an OpenAI, Anthropic, Gemini or Offline chat model.
  • Model type: The chat model provider like OpenAI, Google.
  • Vision enabled: Set to true if your model supports vision. This is currently only supported for vision capable OpenAI models like gpt-4o
  • Max prompt size, Subscribed max prompt size: These are optional fields. They are used to truncate the context to the maximum context size that can be passed to the model. This can help with accuracy and cost-saving.
  • Tokenizer: This is an optional field. It is used to accurately count tokens and truncate context passed to the chat model to stay within the models max prompt size.

Server Chat Settings

The server chat settings are used as:

  1. The default chat models for subscribed (Advanced field) and unsubscribed (Default field) users.
  2. The chat model for all intermediate steps like intent detection, web search etc. during chat response generation.

If a server chat setting is not added the first ChatModelOption in your config is used as the default chat model.

To add a server chat setting:

  • Set your preferred default chat models in the Default fields of your ServerChatSettings
  • The Advanced field doesn't need to be set when self-hosting. When unset, the Default chat model is used for all users and the intermediate steps.

AI Model API

These settings configure APIs to interact with AI models.
For each AI Model API you add:

  • Api key: Set to your OpenAI, Anthropic or Gemini API keys.
  • Name: Give the configuration any friendly name like OpenAI, Gemini, Anthropic.
  • Api base url: Set the API base URL. This is only relevant to set if you're using another OpenAI-compatible proxy server like Ollama or LMStudio.

Search Model Configs

Search models are used to generate vector embeddings of your documents for natural language search and chat. You can choose any embeddings models on HuggingFace to create vector embeddings of your documents for natural language search and chat.

Text to Image Model Options

Add text to image generation models with these settings. Khoj currently supports text to image models available via OpenAI, Google or Replicate API

  • api-key: Set to your OpenAI, Google AI or Replicate API key
  • model: Set the model name available over the selected model provider
  • model-type: Set to the appropriate model provider
  • openai-config: For image generation models available via OpenAI (compatible) API you can set the appropriate OpenAI Processor Conversation Settings instead of specifying the api-key field above

Speech to Text Model Options

Add speech to text models with these settings. Khoj currently only supports whisper speech to text model via OpenAI API or Offline

Voice Model Options

Add text to speech models with these settings. Khoj currently supports models from ElevenLabs.

Reflective Questions

This is a static list of starter question suggestions for each user. It is not currently used in any client app. It used to be shown on the web app home page. We may turn it into a dynamic list of starter questions personalized to each users, say based on their recent conversations or synced knowledge base.

User Data

  • Users, Entrys, Conversations, Subscriptions, Github configs, Notion configs, User search configs, User conversation configs, User voice configs

Miscellaneous Data

  • Process Locks: Persistent Locks for Automations

  • Client Applications:

    Client applications allow you to setup third party applications that can query your Khoj server using a client application ID + secret. The secret would go in a bearer token.


File: documentation/docs/advanced/authentication.mdx

Authenticate (Multi-User Setup)

mdx-code-block
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

By default, most of the instructions for self-hosting Khoj assume a single user, and so the default configuration is to run in anonymous mode. However, if you want to enable authentication, you can do so either with with Magic Links or Google OAuth as shown below. This can be helpful to make Khoj securely accessible to you and your team.

:::tip[Note]
Remove the --anonymous-mode flag from your khoj start up command or docker-compose file to enable authentication.
:::

The most secure way to do this is to integrate with Resend.

  1. Setup your account at https://resend.com
  2. Set an environment variable for RESEND_API_KEY. You can get your API key here.
  3. Set an environment variable for RESEND_EMAIL. This is the email address that will show up in your from field when sending magic links.

This will allow you to automatically send sign-in links to users who want to log in.

It's still possible to use the magic links feature without Resend, but you'll need to manually send the magic links to users who want to log in.

  1. The user will have to enter their email address in the login popup shown at http://localhost:42110/?v=app.

    They'll click Get Login Link. Without the Resend API key, this will just create an unverified account for them in the backend

  2. You can get their magic link using the admin panel

    Go to the admin panel. You'll see a list of users. Search for the user you want to send a magic link to. Tick the checkbox next to their row, and use the action drop down at the top to 'Get email login URL'. This will generate a magic link that you can send to the user, which will appear at the top of the admin interface.

    Get email login URL Retrieved login URL
  3. Send the magic link to the user. They can click on it to log in.

    Once they click on the link, they'll automatically be logged in. They'll have to repeat this process for every new device they want to log in from, but they shouldn't have to repeat it on the same device.

    A given magic link can only be used once. If the user tries to use it again, they'll be redirected to the login page to get a new magic link.

Using Google OAuth

For this method, you'll need to use the prod version of the Khoj package. You can install it as below:

Update your `docker-compose.yml` to use the prod image ```bash image: ghcr.io/khoj-ai/khoj-cloud:latest ``` ```bash pip install khoj[prod] ```

To set up your self-hosted Khoj with Google Auth, you need to create a project in the Google Cloud Console and enable the Google Auth API.

To implement this, you'll need to:

  1. Create authorization credentials for your application.

  2. Open your Google cloud console and create a configuration like below for the relevant OAuth 2.0 Client IDs project:

  3. Configure these environment variables: GOOGLE_CLIENT_SECRET, and GOOGLE_CLIENT_ID. You can find these values in the Google cloud console, in the same place where you configured the authorized origins and redirect URIs.

That's it! That should be all you have to do. Now, when you reload Khoj without --anonymous-mode, you should be able to use your Google account to sign in.


File: documentation/docs/advanced/gcp-vertex.md

Google Vertex AI

:::info
This is only helpful for self-hosted users. If you're using Khoj Cloud, you can directly use any of the pre-configured AI models.
:::

Khoj can use Google's Gemini and Anthropic's Claude family of AI models from Vertex AI on Google Cloud. Explore Anthropic and Gemini AI models available on Vertex AI's Model Garden.

Setup

  1. Follow these instructions to use models on GCP Vertex AI.
  2. Create Service Account credentials.
    • Download the credentials keyfile in json format.
    • Base64 encode the credentials json keyfile. For example by running the following command from your terminal:
      base64 -i <service_account_credentials_keyfile.json>
  3. Create a new API Model API on your Khoj admin panel.
    • Name: Google Vertex (or whatever friendly name you prefer).
    • Api Key: base64 encoded json keyfile from step 2.
    • Api Base Url: https://{MODEL_GCP_REGION}-aiplatform.googleapis.com/v1/projects/{YOUR_GCP_PROJECT_ID}
      • MODEL_GCP_REGION: A region the AI model is available in. For example us-east5 works for Claude.
      • YOUR_GCP_PROJECT_ID: Get your project id from the Google cloud dashboard
  4. Create a new Chat Model on your Khoj admin panel.
    • Name: claude-3-7-sonnet@20250219. Any Claude or Gemini model on Vertex's Model Garden should work.
    • Model Type: Anthropic or Google
    • Ai Model API: the Google Vertex Ai Model API you created in step 3
    • Max prompt size: 60000 (replace with the max prompt size of your model)
    • Tokenizer: Do not set
  5. Select the chat model on your settings page and start a conversation.

Troubleshooting & gcp AI Tips

  • Permission Denied?
    Ensure your service account has the Vertex AI User role and that the API is enabled in your GCP project.

  • Region Errors?
    Double-check that the model you're trying to use is supported in your selected region. Some Claude or Gemini models are restricted to specific zones like us-east5 or us-central1.

  • Prompt Size Limitations
    The "Max prompt size" should align with the limits defined in the model documentation. Exceeding it can silently fail or truncate inputs.

  • Testing the API Key
    Before adding it to Khoj, you can verify that your key works by making a simple curl request to Vertex AI. This helps debug auth issues early.

  • Use Environment Variables
    For better security, consider using environment variables to manage sensitive keys and inject them at runtime during base64 encoding.

If you encounter any issues, the Khoj Discord is a great place to ask for help!


File: documentation/docs/advanced/litellm.md

LiteLLM

:::info
This is only helpful for self-hosted users. If you're using Khoj Cloud, you're limited to our first-party models.
:::

:::info
Khoj natively supports local LLMs available on HuggingFace in GGUF format. Using an OpenAI API proxy with Khoj maybe useful for ease of setup, trying new models or using commercial LLMs via API.
:::

LiteLLM exposes an OpenAI compatible API that proxies requests to other LLM API services. This provides a standardized API to interact with both open-source and commercial LLMs.

Using LiteLLM with Khoj makes it possible to turn any LLM behind an API into your personal AI agent.

Setup

  1. Install LiteLLM
    bash
    pip install litellm[proxy]
  2. Start LiteLLM and use Mistral tiny via Mistral API
    text
    export MISTRAL_API_KEY=<MISTRAL_API_KEY>
    litellm --model mistral/mistral-tiny --drop_params
  3. Create a new API Model API on your Khoj admin panel
    • Name: litellm
    • Api Key: any string
    • Api Base Url: ``
  4. Create a new Chat Model on your Khoj admin panel.
    • Name: llama3.1 (replace with the name of your local model)
    • Model Type: Openai
    • Ai Model Api: the litellm Ai Model API you created in step 3
    • Max prompt size: 20000 (replace with the max prompt size of your model)
    • Tokenizer: Do not set for OpenAI, Mistral, Llama3 based models
  5. Go to your config and select the model you just created in the chat model dropdown.

File: documentation/docs/advanced/lmstudio.md

LM Studio

:::warning[Unsupported]
Khoj does not work with LM Studio anymore. Khoj leverages json mode extensively but LMStudio's API seems to have dropped support for json mode. 1, 2
:::

:::info
This is only helpful for self-hosted users. If you're using Khoj Cloud, you're limited to our first-party models.
:::

:::info
Khoj natively supports local LLMs available on HuggingFace in GGUF format. Using an OpenAI API proxy with Khoj maybe useful for ease of setup, trying new models or using commercial LLMs via API.
:::

LM Studio is a desktop app to chat with open-source LLMs on your local machine. LM Studio provides a neat interface for folks comfortable with a GUI.

LM Studio can expose an OpenAI API compatible server. This makes it possible to turn chat models from LM Studio into your personal AI agents with Khoj.

Setup

  1. Install LM Studio and download your preferred Chat Model
  2. Go to the Server Tab on LM Studio, Select your preferred Chat Model and Click the green Start Server button
  3. Create a new AI Model API on your Khoj admin panel
    • Name: lmstudio
    • Api Key: any string
    • Api Base Url: http://localhost:1234/v1/ (default for LMStudio)
  4. Create a new Chat Model on your Khoj admin panel.
    • Name: llama3.1 (replace with the name of your local model)
    • Model Type: Openai
    • Ai Model Api: the lmstudio Ai Model Api you created in step 3
    • Max prompt size: 20000 (replace with the max prompt size of your model)
    • Tokenizer: Do not set for OpenAI, mistral, llama3 based models
  5. Go to your config and select the model you just created in the chat model dropdown.

File: documentation/docs/advanced/ollama.mdx

Ollama

mdx-code-block
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

:::info
This is only helpful for self-hosted users. If you're using Khoj Cloud, you can use our first-party supported models.
:::

:::info
Khoj can directly run local LLMs available on HuggingFace in GGUF format. The integration with Ollama is useful to run Khoj on Docker and have the chat models use your GPU or to try new models via CLI.
:::

Ollama allows you to run many popular open-source LLMs locally from your terminal.
For folks comfortable with the terminal, Ollama's terminal based flows can ease setup and management of chat models.

Ollama exposes a local OpenAI API compatible server. This makes it possible to use chat models from Ollama with Khoj.

Setup

:::info
Restart your Khoj server after first run or update to the settings below to ensure all settings are applied correctly.
:::

1. Setup Ollama: https://ollama.com/ 2. Download your preferred chat model with Ollama. For example, ```bash ollama pull llama3.1 ``` 3. Uncomment `OPENAI_BASE_URL` environment variable in your downloaded Khoj [docker-compose.yml](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml#:~:text=OPENAI_BASE_URL) 4. Start Khoj docker for the first time to automatically integrate and load models from the Ollama running on your host machine ```bash # run below command in the directory where you downloaded the Khoj docker-compose.yml docker-compose up ```
text
<TabItem value="pip" label="Pip">
  1. Setup Ollama: https://ollama.com/
  2. Download your preferred chat model with Ollama. For example,
     ```bash
     ollama pull llama3.1
     ```
  3. Set `OPENAI_BASE_URL` environment variable to `http://localhost:11434/v1/` in your shell before starting Khoj for the first time
     ```bash
     export OPENAI_BASE_URL="http://localhost:11434/v1/"
     khoj --anonymous-mode
     ```
  </TabItem>
1. Setup Ollama: https://ollama.com/ 2. Download your preferred chat model with Ollama. For example, ```bash ollama pull llama3.1 ``` 3. Create a new [AI Model API](http://localhost:42110/server/admin/database/aimodelapi/add) on your Khoj admin panel - **Name**: `ollama` - **Api Key**: `any string` - **Api Base Url**: `http://localhost:11434/v1/` (default for Ollama) 4. Create a new [Chat Model](http://localhost:42110/server/admin/database/chatmodel/add) on your Khoj admin panel. - **Name**: `llama3.1` (replace with the name of your local model) - **Model Type**: `Openai` - **AI Model API**: *the ollama AI Model API you created in step 3* - **Max prompt size**: `20000` (replace with the max prompt size of your model) 5. Go to [your config](http://localhost:42110/settings) and select the model you just created in the chat model dropdown.

If you want to add additional models running on Ollama, repeat step 4 for each model.

That's it! You should now be able to chat with your Ollama model from Khoj.


File: documentation/docs/advanced/remote.md

Remote Access

By default self-hosted Khoj is only accessible on the machine it is running. To securely access it from a remote machine:

  • Set the KHOJ_DOMAIN environment variable to your remotely accessible ip or domain via shell or docker-compose.yml.
    Examples: KHOJ_DOMAIN=my.khoj-domain.com, KHOJ_DOMAIN=192.168.0.4.
  • Ensure the Khoj Admin password and KHOJ_DJANGO_SECRET_KEY environment variable are securely set.
  • Setup Authentication.
  • Open access to the Khoj port (default: 42110) from your OS and Network firewall.

:::warning[Use HTTPS certificate]
To expose Khoj on a custom domain over the public internet, use of an SSL certificate is strongly recommended. You can use Let's Encrypt to get a free SSL certificate for your domain.

To disable HTTPS, set the KHOJ_NO_HTTPS environment variable to True. This can be useful if Khoj is only accessible behind a secure, private network.
:::

:::info[Try Tailscale]
You can use Tailscale for easy, secure access to your self-hosted Khoj over the network.

  1. Set KHOJ_DOMAIN to your machines tailscale ip or fqdn on tailnet. E.g KHOJ_DOMAIN=100.4.2.0 or KHOJ_DOMAIN=khoj.tailfe8c.ts.net
  2. Access Khoj by opening http://tailscale-ip-of-server:42110 or http://fqdn-of-server:42110 from any device on your tailscale network
    :::

File: documentation/docs/advanced/support-multilingual-docs.md

Support Multilingual Docs

Khoj uses an embedding model to understand documents. Multilingual embedding models improve the search quality for documents not in English. This affects both search and chat with docs experiences across Khoj.

To improve search and chat quality for non-english documents you can use a multilingual model.
For example, the paraphrase-multilingual-MiniLM-L12-v2 supports 50+ languages, has decent search quality and speed for a consumer machine.
To use it:

  1. Open the search config on your server's admin settings page. Either create a new search model, if none exists, or update the existing one. For example,
    • Set the bi_encoder field to sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2
    • Set the cross_encoder field to mixedbread-ai/mxbai-rerank-xsmall-v1
  2. Regenerate your content index from all the relevant clients. This step is very important, as you'll need to re-encode all your content with the new model.

:::info[Note]
Modern search/embedding model like mixedbread-ai/mxbai-embed-large-v1 expect a prefix to the query (or docs) string to improve encoding. Update the bi_encoder_query_encode_config field of your embedding model with {prompt: } to improve the search quality of these models.

E.g. {prompt: "Represent this query for searching documents"}. You can pass any valid JSON object that the SentenceTransformer encode function accepts

:::


File: documentation/docs/advanced/tailscale.md

Tailscale

:::info
This is only helpful for secure cross-device access to self-hosted Khoj. You do not need this if you're using Khoj Cloud.
:::

Tailscale simplifies creating a private VPN using Wireguard and OAuth. So you can host and access services on your devices from anywhere.
The instructions below are one way to simply and securely access your self-hosted Khoj from your phone, laptop etc.

Minimal Setup

  1. Setup khoj on your preferred machine following the standard steps
  2. Sign-up to Tailscale and install the app on machines you want to access Khoj from. This usually includes your khoj server, your phone, laptop. Note the tailscale i.p of your khoj server.
  3. Start khoj on your server by including the flag --host <your_server_tailscale_ip>
  4. Open http://<your_server_tailscale_ip>:42110 to access khoj from any device on your tailscale network!

HTTPS Certificate

:::info
Tailscale uses Wireguard to encrypt and route traffic between your machines. So HTTPS isn't required with Tailscale for secure access. HTTPS with Tailscale is only useful for browsers to not complain about security and block certain features like clipboard access unless HTTPS is enabled.
:::

  1. Enable MagicDNS and HTTPS toggle on your tailscale admin console DNS page. Note your unique tailscale domain name (usually ends with .ts.net)
  2. Create an https certificate for your Khoj server by running the following command:
    bash
    # Assuming the server is named, `server` and your tailnet is `black-forest.ts.net`
    # Note path of the .crt and .key files generated
    
    tailscale cert server.black-forest.ts.net
  3. Start khoj to be served via https on standard port
    bash
    sudo KHOJ_DOMAIN=server.black-forest.ts.net \
    khoj \
    --sslcert /path/to/your/tailscale.crt \
    --sslkey path/to/your/tailscale.key \
    --host=server.black-forest.ts.net \
    --port 443
  4. You should now be able to access khoj on https://server.black-forest.ts.net from any device on your private tailscale network!

File: documentation/docs/advanced/use-openai-proxy.md


Use OpenAI Proxy

:::info
This is only helpful for self-hosted users. If you're using Khoj Cloud, you're limited to our first-party models.
:::

:::info
Khoj natively supports local LLMs available on HuggingFace in GGUF format. Using an OpenAI API proxy with Khoj maybe useful for ease of setup, trying new models or using commercial LLMs via API.
:::

Khoj can use any OpenAI API compatible server including local providers like Ollama, LMStudio and LiteLLM and commercial providers like HuggingFace, OpenRouter etc.
Configuring this allows you to use non-standard, open or commercial, local or hosted LLM models for Khoj.

Combine them with Khoj can turn your favorite LLM into an AI agent. Allowing you to chat with your docs, find answers from the internet, build custom agents and run automations.

For specific integrations, see our Ollama, LMStudio and LiteLLM setup docs. For general instructions to setup Khoj with an OpenAI API proxy see below.

General Setup

  1. Start your preferred OpenAI API compatible app locally or get API keys from commercial AI model providers.
  2. Create a new API Model API on your Khoj admin panel
    • Name: any name
    • Api Key: any string
    • Api Base Url: The URL of your Openai Compatible API
  3. Create a new Chat Model on your Khoj admin panel.
    • Name: llama3 (replace with the name of your local model)
    • Model Type: Openai
    • Ai Model Api: The AI Model API you created in step 2
    • Max prompt size: 2000 (replace with the max prompt size of your model)
    • Tokenizer: Do not set for OpenAI, mistral, llama3 based models
  4. Go to your config and select the model you just created in the chat model dropdown.

File: documentation/docs/clients/_category_.json

{
"label": "Clients",
"position": 4,
"link": {
"type": "generated-index",
"description": "Different ways for indexing data with the Khoj backend. To see online data sources, go to https://docs.khoj.dev/category/data-sources"
}
}


File: documentation/docs/clients/desktop.md


Desktop

Upload your knowledge base to Khoj and chat with your whole corpus

Companion App

Share your files, folders with Khoj using the app.
Khoj will keep these files in sync to provide contextual responses when you search or chat.

Setup

:::info[Self Hosting]
If you are self-hosting the Khoj server, update the Settings page on the Khoj Desktop app to:

  • Set the Khoj URL field to your Khoj server URL. By default, use http://127.0.0.1:42110.
  • Do not set the Khoj API Key field if your Khoj server runs in anonymous mode. For example, khoj --anonymous-mode
    :::
  1. Install the Khoj Desktop app for your OS
  2. Generate an API key on the Khoj Web App
  3. Set your Khoj API Key on the Settings page of the Khoj Desktop app
  4. [Optional] Add any files, folders you'd like Khoj to be aware of on the Settings page and Click Save.
    These files and folders will be automatically kept in sync for you

Main App

You can also install the Khoj application on your desktop as a progressive web app.

  1. Open the Khoj Web App in Chrome.
  2. Click on the install button in the address bar to install the app. You must be logged into your Chrome browser for this to work.

Alternatively, you can also install using this route:

  1. Open the three-dot menu in the top right corner of the browser.
  2. Go to 'Cast, Save, and Share' option.
  3. Click on the "Open in Khoj" option.

File: documentation/docs/clients/emacs.md


Emacs

Query your Second Brain from Emacs

Features

  • Chat
    • Faster answers: Find answers quickly, from your private notes or the public internet
    • Assisted creativity: Smoothly weave across retrieving answers and generating content
    • Iterative discovery: Iteratively explore and re-discover your notes
  • Search
    • Natural: Advanced natural language understanding using Transformer based ML Models
    • Incremental: Incremental search for a fast, search-as-you-type experience

Interface

Search Chat

Setup

:::info[Self Hosting]
If you are self-hosting the Khoj server modify the install steps below:

  • Set khoj-server-url to your Khoj server URL. By default, use http://127.0.0.1:42110.
  • Do not set khoj-api-key if your Khoj server runs in anonymous mode. For example, khoj --anonymous-mode
    :::
  1. Generate an API key on the Khoj Web App
  2. Add below snippet to your Emacs config file, usually at ~/.emacs.d/init.el

**Direct Install**

Khoj will index your org-agenda files, by default

elisp
;; Install Khoj.el
M-x package-install khoj

; Set your Khoj API key
(setq khoj-api-key "YOUR_KHOJ_CLOUD_API_KEY")
(setq khoj-server-url "https://app.khoj.dev")

**Minimal Install**

Khoj will index your org-agenda files, by default

elisp
;; Install Khoj client from MELPA Stable
(use-package khoj
  :ensure t
  :pin melpa-stable
  :bind ("C-c s" . 'khoj)
  :config (setq khoj-api-key "YOUR_KHOJ_CLOUD_API_KEY"
                khoj-server-url "https://app.khoj.dev"))

**Standard Install**

Configures the specified org files, directories to be indexed by Khoj

elisp
;; Install Khoj client from MELPA Stable
(use-package khoj
  :ensure t
  :pin melpa-stable
  :bind ("C-c s" . 'khoj)
  :config (setq khoj-api-key "YOUR_KHOJ_CLOUD_API_KEY"
                khoj-server-url "https://app.khoj.dev"
                khoj-index-directories '("~/docs/org-roam" "~/docs/notes")
                khoj-index-files '("~/docs/todo.org" "~/docs/work.org")))

**Straight.el**

Configures the specified org files, directories to be indexed by Khoj

elisp
;; Install Khoj client using Straight.el
(use-package khoj
  :after org
  :straight (khoj :type git :host github :repo "khoj-ai/khoj" :files (:defaults "src/interface/emacs/khoj.el"))
  :bind ("C-c s" . 'khoj)
  :config (setq khoj-api-key "YOUR_KHOJ_CLOUD_API_KEY"
                khoj-server-url "https://app.khoj.dev"
                khoj-org-directories '("~/docs/org-roam" "~/docs/notes")
                khoj-org-files '("~/docs/todo.org" "~/docs/work.org")))

Use

See Khoj Search for details

  1. Hit C-c s s (or M-x khoj RET s) to open khoj search
  2. Enter your query in natural language
    E.g. "What is the meaning of life?", "My life goals for 2023"

Chat

See Khoj Chat for details

  1. Hit C-c s c (or M-x khoj RET c) to open khoj chat
  2. Ask questions in a natural, conversational style
    E.g. "When did I file my taxes last year?"

Find Similar Entries

This feature finds entries similar to the one you are currently on.

  1. Move cursor to the org-mode entry, markdown section or text paragraph you want to find similar entries for
  2. Hit C-c s f (or M-x khoj RET f) to find similar entries

Advanced Usage

  • Add query filters during search to narrow down results further
    e.g. What is the meaning of life? -"god" +"none" dt>"last week"

  • Use C-c C-o 2 to open the current result at cursor in its source org file

    • This calls M-x org-open-at-point on the current entry and opens the second link in the entry.
    • The second link is the entries org-id, if set, or the heading text.
      The first link is the line number of the entry in the source file. This link is less robust to file changes.
    • Note: If you have speed keys enabled, o 2 will also work

Khoj Menu

Hit C-c s (or M-x khoj) to open the khoj menu above. Then:

  • Hit t until you preferred content type is selected in the khoj menu
    Content Type specifies the content to perform Search, Update or Find Similar actions on
  • Hit n twice and then enter number of results you want to see
    Results Count is used by the Search and Find Similar actions
  • Hit -f u to force update the khoj content index
    The Force Update switch is only used by the Update action

Upgrade

Use your Emacs package manager to upgrade khoj.el

**With MELPA**

  1. Run M-x package-refresh-content
  2. Run M-x package-reinstall khoj

**With Straight.el**

  • Run M-x straight-pull-package khoj

File: documentation/docs/clients/obsidian.md


Obsidian

Query your Second Brain from Obsidian

Features

  • Chat
    • Faster answers: Find answers quickly, from your private notes or the public internet
    • Assisted creativity: Smoothly weave across retrieving answers and generating content
    • Iterative discovery: Iteratively explore and re-discover your notes
  • Search
    • Natural: Advanced natural language understanding using Transformer based ML Models
    • Incremental: Incremental search for a fast, search-as-you-type experience
  • Similar
    • Discover: Find similar notes to the current one

Setup

:::info[Self Hosting]
If you are self-hosting the Khoj server, update the Khoj Obsidian plugin settings step below:

  • Set the Khoj URL field to your Khoj server URL. By default, use http://127.0.0.1:42110.
  • Do not set the Khoj API Key field if your Khoj server runs in anonymous mode. For example, khoj --anonymous-mode
    :::
  1. Open Khoj from the Community plugins tab in Obsidian settings panel
  2. Click Install, then Enable on the Khoj plugin page in Obsidian
  3. Generate an API key on the Khoj Web App
  4. Set your Khoj API Key in the Khoj plugin settings on Obsidian
  5. (Optional) Click Force Sync in the Khoj plugin settings on Obsidian to immediately sync your Obsidian vault.
    By default, your Obsidian vault is automatically synced periodically.

See the official Obsidian Plugin Docs for more details on installing Obsidian plugins.

Use

Chat

Click the Khoj chat icon 💬 on the Ribbon or run Khoj: Chat from the Command Palette and ask questions in a natural, conversational style.
E.g. "When did I file my taxes last year?"

See Khoj Chat for more details

Find Similar Notes

To see other notes similar to the current one, run Khoj: Find Similar Notes from the Command Palette

Run Khoj: Search from the Command Palette

See Khoj Search for more details. Use query filters to limit entries to search

search_demo

Upgrade

  1. Open Community plugins tab in Obsidian settings
  2. Click the Check for updates button
  3. Click the Update button next to Khoj, if available

Troubleshooting

  • Open the Khoj plugin settings pane, to configure Khoj
  • Toggle Enable/Disable Khoj, if setting changes have not applied
  • Click Update button to force index to refresh, if results are failing or stale

File: documentation/docs/clients/web.md


Web

Query your Second Brain from your Web Browser

Without any desktop clients, you can start chatting with Khoj on the web. Bear in mind you do need one of the desktop clients in order to share and sync your data with Khoj.

Go see it here --> Khoj Cloud.

Features

  • Chat
    • Faster answers: Find answers quickly, from your private notes or the public internet
    • Assisted creativity: Smoothly weave across retrieving answers and generating content
    • Iterative discovery: Iteratively explore and re-discover your notes
  • Search
    • Natural: Advanced natural language understanding using Transformer based ML Models
    • Incremental: Incremental search for a fast, search-as-you-type experience

Setup

No setup required. The Khoj web app is the default Khoj client. You can access it from any web browser. Try it on Khoj Cloud

Upload Documents

You can upload documents to Khoj from the web interface, one at a time. This is useful for uploading documents from your phone or tablet. To upload a document:

  1. You can drag and drop the document into the chat window.
  2. Or click the paperclip icon in the chat window and select the document from your file system.

Install on Phone

You can optionally install Khoj as a Progressive Web App (PWA). This makes it quick and easy to access Khoj on your phone.

  1. Login to Khoj Cloud or your self-hosted Khoj server from the web browser (prefer Chrome/Edge) on your phone
  2. Open the 3 dot menu on the browser and click the "Add to Home screen" option
  3. Click "Install" on the next screen to add the Khoj icon to your phone Home screen

Process via Screenshots

Step 1 Step 2 Step 3

File: documentation/docs/clients/whatsapp.md


WhatsApp

Query your Second Brain from WhatsApp

Text +1 (848) 800 4242 or scan the QR code below on your phone to chat with Khoj on WhatsApp.

Without any desktop clients, you can start chatting with Khoj on WhatsApp. Bear in mind you do need one of the desktop clients in order to share and sync your data with Khoj. The WhatsApp AI bot will work right away for answering generic queries and using Khoj in default mode.

In order to use Khoj on WhatsApp with your own data, you need to setup a Khoj Cloud account and connect your WhatsApp account to it. This is a one time setup and you can do it from the Khoj Cloud config page.

If you hit usage limits for the WhatsApp bot, upgrade to a paid plan on Khoj Cloud.

Features

  • Slash Commands: Use slash commands to quickly access Khoj features
    • /online: Get responses from Khoj powered by online search.
    • /dream: Generate an image in response to your prompt.
    • /notes: Explicitly force Khoj to retrieve context from your notes. Note: You'll need to connect your WhatsApp account to a Khoj Cloud account for this to work.

We have more commands under development, including /share to uploading documents directly to your Khoj account from WhatsApp, and /speak in order to get a speech response from Khoj. Feel free to raise an issue if you have any suggestions for new commands.

Source Code

You can find all of the code for the WhatsApp bot in the flint repository. As all of our code, it is open source and you can contribute to it.


File: documentation/docs/contributing/_category_.json

{
"label": "Contributing",
"position": 2,
"link": {
"type": "generated-index",
"description": "Development Setup"
}
}


File: documentation/docs/contributing/development.mdx


Development

Welcome to the development docs of Khoj! Thanks for your interest in being a contributor ❤️. Open source contributors are a cornerstone of the Khoj community. We welcome all contributions, big or small.

To get started with contributing, check out the official GitHub docs on contributing to an open-source project.

Join the Discord server and click the ✅ for the question "Are you interested in becoming a contributor?" in the #welcome-and-rules channel. This will give you access to the #contributors channel where you can ask questions and get help from other contributors.

If you're looking for a place to get started, check out the list of Github Issues with the tag good first issue to find issues that are good for first-time contributors.

Local Server Installation

Using Pip

1. Khoj Installation

mdx-code-block
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
```shell # Get Khoj Code git clone https://github.com/khoj-ai/khoj && cd khoj

Create, Activate Virtual Environment

python3 -m venv .venv && source .venv/bin/activate

For MacOS or zsh users run this

uv sync --all-extras
</TabItem> <TabItem value="windows" label="Windows"> shell

Get Khoj Code

git clone https://github.com/khoj-ai/khoj && cd khoj

Create, Activate Virtual Environment

python3 -m venv .venv && .venv\Scripts\activate

Install Khoj for Development

uv sync --all-extras
</TabItem> <TabItem value="linux" label="Linux"> shell
# Get Khoj Code
git clone https://github.com/khoj-ai/khoj && cd khoj

Create, Activate Virtual Environment

python3 -m venv .venv && source .venv/bin/activate

Install Khoj for Development

uv sync --all-extras
```

2. Postgres Installation & Setup

Khoj uses the pgvector package to store embeddings of your index in a Postgres database. To use this, you need to have Postgres installed.

Install [Postgres.app](https://postgresapp.com/). This comes pre-installed with `pgvector` and relevant dependencies. 1. Use the [recommended installer](https://www.postgresql.org/download/windows/). 2. Follow instructions to [Install PgVector](https://github.com/pgvector/pgvector#windows) in case you need to manually install it. Windows support is experimental for pgvector currently, so we recommend using Docker. Refer to Windows Installation Notes below if there are errors. From [official instructions](https://wiki.postgresql.org/wiki/Apt) 1. Follow instructions to [Install Postgres](https://www.postgresql.org/download/) 2. Follow instructions to [Install PgVector](https://github.com/pgvector/pgvector#installation) in case you need to manually install it.

Create the Khoj database

Make sure to update your environment variables to match your Postgres configuration if you're using a different name. The default values should work for most people. When prompted for a password, you can use the default password postgres, or configure it to your preference. Make sure to set the environment variable POSTGRES_PASSWORD to the same value as the password you set here.

```shell createdb khoj -U postgres --password ``` ```shell createdb -U postgres khoj --password ``` ```shell sudo -u postgres createdb khoj --password ```

3. Build the front-end assets

shell
cd src/interface/web/
bun install
bun export

You can optionally use bun dev to start a development server for the front-end which will be available at http://localhost:3000. This is especially useful if you're making changes to the front-end code, but not necessary for running Khoj. Note that streaming does not work on the dev server due to how it is handled with SSR in Next.js.

Always run bun export to test your front-end changes on http://localhost:42110 before creating a PR.

4. Run

  1. Start Khoj
    bash
    khoj -vv
  2. Configure Khoj
    • Via the Desktop application: Add files, directories to index using the settings page of your desktop application. Click "Save" to immediately trigger indexing.

Note: Wait after configuration for khoj to Load ML model, generate embeddings and expose API to query notes, images, documents etc specified in config YAML

Windows Installation Notes

  1. Command khoj Not Recognized
    • Try reactivating the virtual environment and rerunning the khoj command.
    • If it still doesn't work repeat the installation process.
  2. Python Package Missing
    • Use uv add xxx and try running the khoj command.
  3. Command createdb Not Recognized
    • make sure path to postgres binaries is included in environment variables. It usually looks something like
    text
    C:\Program Files\PostgreSQL\16\bin
  4. Connection Refused on port xxxx
    • Locate the pg_hba.conf file in the location where postgres was installed.
    • Edit the file to have trust as the method for user postgres, local, and host connections.
    • Below is an example:
text
host    all             postgres        127.0.0.1/32            trust
# "local" is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust
  1. Errors with installing pgvector
    • Reinstall Visual Studio 2022 Build Tools with:
      1. desktop development with c++ selected in workloads
      2. MSVC (C++ Build Tools), Windows 10/11 SDK, and C++/CLI support for build tools selected in individual components.
    • Open the x64 Native Tools Command Prompt as an Administrator
    • Follow the pgvector windows installation instructions in this command prompt.

Using Docker

Make sure you install the latest version of Docker and Docker Compose.

1. Clone

shell
git clone https://github.com/khoj-ai/khoj && cd khoj

2. Configure

  1. Update docker-compose.yml to use relevant environment variables.
  2. Comment out the image line and uncomment the build line in the server service

3. Run

This will start the Khoj server, and the database.

shell
docker-compose up -d

4. Upgrade

If you've made changes to the codebase, you'll need to rebuild the Docker image before running the container again.

shell
docker-compose build --no-cache

Update clients

In whichever clients you're using for testing, you'll need to update the server URL to point to your local server. By default, the local server URL should be http://127.0.0.1:42110.

Validate

Before Making Changes

  1. Install Khoj. Setup Git Hooks for Validation
    shell
    ./scripts/dev_setup.sh
    • Installs the khoj server and web app by default. Use the --full flag to install the Khoj Desktop and Obsidian client apps as well.
    • Git hooks format code, check types automatically on every commit and push respectively.
    • Note 1: If pre-commit didn't already get installed, install it via pip install pre-commit
    • Note 2: To run the pre-commit changes manually, use pre-commit run --hook-stage manual --all before creating PR

Before Creating PR

:::tip[Note]
You should be in an active virtual environment for Khoj in order to run the unit tests and linter. The dev_setup.sh script will automatically create and activate it for you.
:::

  1. Ensure that you have a Github Issue that can be linked to the PR. If not, create one. Make sure you've tagged one of the maintainers to the issue. This will ensure that the maintainers are notified of the PR and can review it. It's best to discuss the code design on an existing issue or Discord thread before creating a PR. This helps get your PR merged faster.
  2. Run unit tests.
    shell
    pytest
  3. Run the linter.
    shell
    mypy
  4. Think about how to add unit tests to verify the functionality you're adding in the PR. If you're not sure how to do this, ask for help in the Github issue or on Discord's #contributors channel.

After Creating PR

  1. Automated validation workflows should run for every PR. Tag one of the maintainers in the PR to trigger it.

Obsidian Plugin Development

Plugin development setup

The core code for the Obsidian plugin is under src/interface/obsidian. The file main.ts is a good place to start.

  1. In your CLI, go to the directory src/interface/obsidian in the Khoj repository.
  2. Run yarn install to install the dependencies.
  3. Run yarn dev to start the development server. This will continually rebuild the plugin as you make changes to the code.
    • Your code changes will be outputted to a file called main.js in the obsidian directory.

Loading your development plugin in Obsidian

  1. Make sure you have the Khoj plugin installed in Obsidian. See the plugin page.
  2. Open Obsidian and go to your settings (gear icon in the bottom left corner)
  3. Click on 'Community Plugins' in the left panel
  4. Next to the 'Installed Plugins' heading, click on the folder icon to open the folder with the plugin's source code.
  5. Open the khoj folder in the file explorer that opens. You'll see a file called main.js in this folder. To test your changes, replace this file with the main.js file that was generated by the development server in the previous section.

Create Khoj Release (Only for Maintainers)

Follow the steps below to release Khoj. This will create a stable release of Khoj on Pypi, Melpa and Obsidian. It will also create desktop apps of Khoj and attach them to the latest release.

  1. Create and tag release commit by running the bump_version script. The release commit sets version number in required metadata files.
shell
./scripts/bump_version.sh -c "<release_version>"
  1. Push commit and then the tag to trigger the release workflow to create Release with auto generated release notes.
shell
git push origin master  # push release commit to khoj repository
git push origin <release_version>  # push release tag to khoj repository
  1. [Optional] Update the Release Notes to highlight new features, fixes and updates

Architecture

Visualize Codebase

Interactive Visualization

Visualize Khoj Obsidian Plugin Codebase


File: documentation/docs/data-sources/_category_.json

{
"label": "Data Sources",
"position": 5,
"link": {
"type": "generated-index",
"description": "Online data sources for indexing via Khoj"
}
}


File: documentation/docs/data-sources/github_integration.md

Github integration

:::warning[Unmaintained]
The Github integration is not maintained. We are considering deprecating it. It doesn't seem used by many folks and its cumbersome for us to maintain.
:::

The Github integration allows you to index as many repositories as you want. It's currently default configured to index all Markdown/Org/Text files in each repository. For large repositories, this takes a fairly long time, but it works well for smaller projects.

Configure your settings

  1. Go to https://app.khoj.dev/settings and enter in settings for the data sources you want to index. You'll have to specify the file paths.

Use the Github plugin

  1. Generate a classic PAT (personal access token) from Github with repo and admin:org scopes at least.
  2. Navigate to https://app.khoj.dev/settings#github to configure your Github settings. Enter in your PAT, along with details for each repository you want to index.
  3. Click Save. Go back to the settings page and click Configure.
  4. Go to https://app.khoj.dev/ and start searching!

File: documentation/docs/data-sources/notion_integration.md

Notion Integration

The Notion integration allows you to search/chat with your Notion workspaces. Notion is a platform people use for taking notes, especially for collaboration.

Go to https://app.khoj.dev/settings to connect your Notion workspace(s) to Khoj.

Self-Hosted Setup

  1. Go to https://www.notion.so/my-integrations and create a new integration called Khoj to get an API key.

  2. Share all the workspaces that you want to integrate with the Khoj integration you just made in the previous step

  3. In the first step, you generated an API key. Use the newly generated API Key in your Khoj settings, by default at http://localhost:42110/settings#notion. Click Save.

  4. Click Configure in http://localhost:42110/settings to index your Notion workspace(s).

That's it! You should be ready to start searching and chatting. Make sure you've configured your chat settings.


File: documentation/docs/data-sources/share_your_data.md


sidebar_position: 0
keywords: ["upload data", "upload files", "share data", "share files", "pdf ai", "ai for pdf", "ai for documents", "ai for files", "local ai pdf", "local ai documents", "local ai files"]


Upload your data

There are several ways you can get started with sharing your data with the Khoj AI.

  • Drag and drop your documents via the web UI. This is best if you have a one-off document you need to interact with.
  • You can use the search page to upload documents that become indexed & searchable by your second brain. Click on "Add Documents" to get started.
  • Use the desktop app to upload and sync your documents. This is best if you have a lot of documents on your computer or you need the docs to stay in sync.
  • Setup the sync options for either Obsidian or Emacs to automatically sync your documents with Khoj. This is best if you are already using these tools and want to leverage Khoj's AI capabilities.
  • Configure your Notion or Github to sync with Khoj. By providing your credentials, you can keep the data synced in the background.

File: documentation/docs/features/_category_.json

{
"label": "Features",
"position": 3,
"link": {
"type": "generated-index",
"description": "Features supported by Khoj"
}
}


File: documentation/docs/features/agents.md


Agents

You can use agents to setup custom system prompts with Khoj. The server host can setup their own agents, which are accessible to all users. You can see ours at https://app.khoj.dev/agents.

Creating an Agent (Self-Hosted)

Go to server/admin/database/agent on your server and click Add Agent to create a new one. You have to set it to public in order for it to be accessible to all the users on your server. To limit access to a specific user, do not set the public flag and add the user in the Creator field.

Set your custom prompt in the personality field.


File: documentation/docs/features/all-features.md


Overview

Khoj supports a variety of features, including search and chat with a wide range of data sources and interfaces.

  • Local: Your personal data stays local. All search and indexing is done on your machine when you self-host
  • Incremental: Incremental search for a fast, search-as-you-type experience

[Chat](/features/chat)

  • Faster answers: Find answers faster, smoother than search. No need to manually scan through your notes to find answers.
  • Iterative discovery: Iteratively explore and (re-)discover your notes
  • Assisted creativity: Smoothly weave across answers retrieval and content generation
  • Works online or offline: Chat using online or offline AI chat models

General

  • Cloud or Self-Host: Use cloud to use Khoj anytime from anywhere or self-host for privacy
  • Natural: Advanced natural language understanding using Transformer based ML Models
  • Pluggable: Modular architecture makes it easy to plug in new data sources, frontends and ML models
  • Multiple Sources: Index your Org-mode, Markdown, PDF, plaintext files, Github repos and Notion pages
  • Multiple Interfaces: Interact from your Web Browser, Emacs, Obsidian, Desktop app or even Whatsapp

Supported Interfaces

Khoj is available as a Desktop app, Emacs package, Obsidian plugin, Web app and a Whatsapp AI.

Supported Data Sources

Khoj can understand your word, PDF, org-mode, markdown, plaintext files, and Notion pages.


File: documentation/docs/features/automations.md

Automations

Automations are a powerful feature within Khoj to schedule repeated jobs for Khoj to do on your behalf. Automations allow you run your query automatically at a scheduled time and frequency. Khoj will send its research to you as an email.
You can ask Khoj to create custom newsletters, summarize news, notify you of world events etc.

Khoj uses your local time zone for scheduling. You can configure, share and delete your automations from the automations page.

:::info[Self Hosting]
Self hosting users need to setup Resend and Authentication setup to have Khoj send automation emails.
:::

Create Automation Receive Automation Email

File: documentation/docs/features/chat.md


Chat

You can configure Khoj to chat with you about anything. When relevant, it'll use any notes or documents you shared with it to respond. It acts as an excellent research assistant, search engine, or personal tutor.

Overview

  • Creates a personal assistant for you to inquire and engage with your notes or online information as needed
  • You can choose to use Online or Offline Chat depending on your requirements
  • Supports multi-turn conversations with the relevant notes for context
  • Shows reference notes used to generate a response

Setup (Self-Hosting)

See the setup guide to configure your chat models.

Use

  1. Open Khoj Chat
    • On Web: Open /chat in your web browser
    • On Obsidian: Search for Khoj: Chat in the Command Palette
    • On Emacs: Run M-x khoj
  2. Enter your queries to chat with Khoj. Use slash commands and query filters to change what Khoj uses to respond

Details

  1. Your query is used to retrieve the most relevant notes, if any, using Khoj search using RAG.
  2. These notes, the last few messages and associated metadata is passed to the enabled chat model along with your query to generate a response

Conversation File Filters

You can use conversation file filters to limit the notes used in the chat response. To do so, use the left panel in the web UI. Alternatively, you can also use query filters to limit the notes used in the chat response.

Commands

Slash commands allows you to change what Khoj uses to respond to your query

  • /notes: Limit chat to only respond using your notes, not just Khoj's general world knowledge as reference
  • /general: Limit chat to only respond using Khoj's general world knowledge, not using your notes as reference
  • /default: Allow chat to respond using your notes or it's general knowledge as reference. It's the default behavior when no slash command is used
  • /online: Use online information and incorporate it in the prompt to the LLM to send you a response.
  • /image: Generate an image in response to your query.
  • /help: Use /help to get all available commands and general information about Khoj
  • /diagram: Generate a diagram in response to your query. This is built on Excalidraw.
  • /code: Generate and run very simple Python code snippets. Refer to Code Execution for details.
  • /research: Go deeper in a topic for more accurate, in-depth responses.

File: documentation/docs/features/code_execution.md



Code Execution

Khoj can generate and run simple Python code as well. This is useful if you want to have Khoj do some data analysis, generate plots and reports. LLMs by default aren't skilled at complex quantitative tasks. Code generation & execution can come in handy for such tasks.

Khoj automatically infers when to use the code tool. You can also tell it explicitly to use the code tool or use the /code slash command in your chat.

Setup (Self-Hosting)

Terrarium Sandbox

Use Cohere's Terrarium to host the code sandbox locally on your machine for free.

To run with Docker, use our docker-compose.yml to automatically setup the Terrarium code sandbox, or start it manually like this:

bash
docker pull ghcr.io/khoj-ai/terrarium:latest
docker run -d -p 8080:8080 ghcr.io/khoj-ai/terrarium:latest

To run from source, check these instructions.

Verify

Verify that it's running, by evaluating a simple Python expression:

bash
curl -X POST -H "Content-Type: application/json" \
--url http://localhost:8080 \
--data-raw '{"code": "1 + 1"}' \
--no-buffer

E2B Sandbox

E2B allows Khoj to run code on a remote but versatile sandbox with support for more python libraries. This is not free.

To have Khoj use E2B as the code sandbox:

  1. Generate an API key on their dashboard.
  2. Set the E2B_API_KEY environment variable to it on the machine running your Khoj server.
    • When using our docker-compose.yml, uncomment and set the E2B_API_KEY env var in the docker-compose.yml file.
  3. Now restart your Khoj server to switch to using the E2B code sandbox.

File: documentation/docs/features/image_generation.md

Image Generation

You can use Khoj to generate images from text prompts. You can get deeper into the details of our image generation flow in this blog post: https://blog.khoj.dev/posts/how-khoj-generates-images/.

To generate images, you just need to provide a prompt to Khoj in which the image generation is in the instructions. Khoj will automatically detect the image generation intent, augment your generation prompt, and then create the image. Here are some examples:

Prompt Image
Paint a picture of the plants I got last month, pixar-animation
Create a picture of my dream house, based on my interests

Setup (Self-Hosting)

You have a couple of image generation options.

Image Generation Models

We support most state of the art image generation models, including Ideogram, Flux, and Stable Diffusion. These will run using Replicate. Here's how to set them up:

  1. Get a Replicate API key here.
  2. Create a new Text to Image Model. Set the type to Replicate. Use any of the model names you see on this list. We recommend the model name black-forest-labs/flux-1.1-pro from Replicate.

OpenAI

  1. Get an OpenAI API key.
  2. Setup your OpenAI API key, if you haven't already. See instructions here
  3. Create a text to image config at http://localhost:42110/server/admin/database/texttoimagemodelconfig/. Use model name dall-e-3 to use openai for image generation. Make sure to set the Ai model api field to the OpenAI AI model api you setup in step 2.

File: documentation/docs/features/keyboard_shortcuts.md

Keyboard Shortcuts

Oftentimes, having to leave your keyboard to move the mouse can break your flow. We want to make it as easy as possible for AI to flow with you as you are, so we've added some keyboard shortcuts to facilitate that.

Obsidian

Up/Down Arrow Keys (Chat Input)

  • Up Arrow Key: Move up in the list of most recent messages in your chat window.
  • Down Arrow Key: Move down in the list of most recent messages in your chat window.

You can watch the demo to see how it works on this sample conversation.

Enter (Chat Input)

Press 'Enter' to send the message you've typed in the chat window.


File: documentation/docs/features/khoj_mini.md

Desktop Quick Chat (Khoj Mini)

Once you have the Khoj desktop application installed, you can use the desktop shortcut to quickly pull up a mini chat module for quicker answers. See the desktop setup instructions in the docs for more information.

To use it, you just have to copy the text you want to inject into your query, and then run Ctrl + Shift + K (or Cmd + Shift + K on Mac) to open the mini chat module. The text you copied will be automatically pasted into the chat module, and you can then hit enter to get the answer. You can edit the text before hitting enter if you want to refine your query.

The desktop shortcut is a great way to quickly get answers to your questions without having to switch between windows or tabs. It's especially useful when you're working on a project and need to quickly look up something without losing your focus.


File: documentation/docs/features/online_search.md

Khoj will research on the internet to ground its responses, when it determines that it would need fresh information outside its existing knowledge to answer the query. It will always show any online references it used to respond to your requests.

By default, Khoj will try to infer which information sources, it needs to read to answer your question. This can include reading your documents or researching information online. You can also explicitly trigger an online search by adding the /online prefix to your chat query.

Example queries that should trigger an online search:

Try it out yourself! https://app.khoj.dev

Self-Hosting

Online search can work even with self-hosting! You have a few options:

  • If you're using Docker, online search should work out of the box with searxng using our standard docker-compose.yml.
  • To get production-grade, fast online search, set the SERPER_DEV_API_KEY environment variable to your Serper.dev API key. These search results include additional context like answer box, knowledge graph etc.
  • To use open, self-hostable search provider, set the FIRECRAWL_API_KEY environment variable to your Firecrawl API key. These search results do not scrape social media results.
  • To use Exa search provider, set the EXA_API_KEY environment variable to your Exa API key.

Webpage Reading

Out of the box, you don't have to do anything to enable webpage reading. Khoj will automatically read webpages by using the requests library. To get faster, more readable webpages for Khoj, you can use the following options:

  • For open, self-hostable webpage reader, you can use Firecrawl. Create a new Webscraper. Set your Firecrawl API key to the Api Key field, and set the type to Firecrawl.
  • For advanced webpage reading, you can use Olostep. This can read a wider variety of webpages. Create a new Webscraper. Set your Olostep API key to the Api Key field, and set the type to Olostep.
  • For fast webpage reading, you can use Exa. Create a new Webscraper. Set your Exa API key to the Api Key field, and set the type to Exa.

File: documentation/docs/features/search.md


Take advantage of super fast search to find relevant notes and documents from your Second Brain.

Use

  1. Open Khoj Search
  1. Query using natural language to find relevant entries from your knowledge base. Use query filters to limit entries to search

Demo

Implementation Overview

A bi-encoder models is used to create meaning vectors (aka vector embeddings) of your documents and search queries.

  1. When you sync you documents with Khoj, it uses the bi-encoder model to create and store meaning vectors of (chunks of) your documents
  2. When you initiate a natural language search the bi-encoder model converts your query into a meaning vector and finds the most relevant document chunks for that query by comparing their meaning vectors.
  3. The slower but higher-quality cross-encoder model is than used to re-rank these documents for your given query.

Setup (Self-Hosting)

You are not required to configure the search model config when self-hosting. Khoj sets up decent default local search model config for general use.

You may want to configure this if you need better multi-lingual search, want to experiment with different, newer models or the default models do not work for your use-case.

You can use bi-encoder models downloaded locally from Huggingface, served via the HuggingFace Inference API, OpenAI API, Azure OpenAI API or any OpenAI Compatible API like Ollama, LiteLLM etc. Follow the steps below to configure your search model:

  1. Open the SearchModelConfig page on your Khoj admin panel.
  2. Hit the Plus button to add a new model config or click the id of an existing model config to edit it.
  3. Set the biencoder field to the name of the bi-encoder model supported locally or via the API you configure.
  4. Set the Embeddings inference endpoint api key to your OpenAI API key and Embeddings inference endpoint type to OpenAI to use an OpenAI embedding model.
  5. Also set the Embeddings inference endpoint to your Azure OpenAI or OpenAI compatible API URL to use the model via those APIs.
  6. Ensure the search model config you want to use is the only one that has name field set to default[^1].
  7. Save the search model configs and restart your Khoj server to start using your new, updated search config.

:::info
You will need to re-index all your documents if you want to use a different bi-encoder model.
:::

:::info
You may need to tune the Bi encoder confidence threshold field for each bi-encoder to get appropriate number of documents for chat with your Knowledge base.

Confidence here is a normalized measure of semantic distance between your query and documents. The confidence threshold limits the documents returned to chat that fall within the distance specified in this field. It can take values between 0.0 (exact overlap) and 1.0 (no meaning overlap).
:::

[^1]: Khoj uses the first search model config named default it finds on startup as the search model config for that session


File: documentation/docs/features/share.md

Shareable Chat

You can share any of your conversations by going to the three dot menu on the conversation and selecting 'Share'. This will create a public link that you can share with anyone. The link will open the conversation in the same state it was when you shared it, so your future messages will not be visible to the person you shared it with.

This means you can easily share a conversation with someone to show them how you solved a problem, or to get help with something you're working on.


File: documentation/docs/features/voice-chat.md

Voice

You can talk to Khoj using your voice. Khoj will respond to your queries using the same models as the chat feature. You can use voice chat on the web, Desktop, and Obsidian apps.

Click on the little mic icon to send your voice message to Khoj. It will send back what it heard via text. You can edit the message before sending it, if required. Try it at https://app.khoj.dev/.

Voice Response

If you send a voice message, Khoj will automatically respond back with a voice message.
You can also click on the speaker icon next to any message to hear it out loud. The voice response feature is available only on the web view right now.

Setup (Self-Hosting)

Voice chat will automatically be configured when you initialize the application. The default configuration will run locally. If you want to use the OpenAI whisper API for voice chat, you can set it up by following these steps:

  1. Setup your OpenAI API key. See instructions here.
  2. Create a new configuration at http://localhost:42110/server/admin/database/speechtotextmodeloptions/. We recommend the value whisper-1 and model type Openai.

If you want to use the Text to Speech feature, you can set it up by following these steps:

  1. Setup your account on ElevenLabs.io.
  2. Configure your API key in your environment variables with the key ELEVEN_LABS_API_KEY.
  3. (Optional) Create a new Voice model option with a specific voice ID from whichever voice you want to use. You can explore the options here.

File: documentation/docs/get-started/_category_.json

{
"label": "Get Started",
"position": 1,
"link": {
"type": "generated-index",
"description": "Learn how to get started with using Khoj"
}
}


File: documentation/docs/get-started/overview.md


Overview

Introduction

Welcome to the Khoj Docs! This is the best place to get setup and explore Khoj's features.

  • Khoj is an open source, personal AI
  • You can chat with it about anything. It'll use files you shared with it to respond, when relevant. It can also access information from the public internet.
  • Quickly find relevant notes and documents using natural language
  • It understands pdf, plaintext, markdown, org-mode files, and notion pages.
  • Access it from your Emacs, Obsidian, the Khoj desktop app, or any web browser
  • Use our cloud instance to access your Khoj anytime from anywhere, self-host on consumer hardware for privacy

Quickstart


File: documentation/docs/get-started/privacy-security.md


Privacy

If you're using Khoj to index you personal data, it's almost certain you'll have sensitive and private information you'd like to index.

Khoj is designed to be a personal AI, so one of our cornerstone principles is to make it as privacy-friendly as possible. That's why, you can always choose to run Khoj on your own hardware, and never share your data outside of your device. You can generate your embeddings directly on your machine, and then use an offline chat client so that your data never leaves your machine. You'll find the instructions to self-hosting here.

Here's what to consider if you're using Khoj, whether self-hosted or on our cloud:

  1. Some of your relevant indexed data may be included as context when you chat with Khoj. This means that it may be sent to OpenAI, if you use one of the OpenAI models.
  2. We collect completely anonymized usage telemetry and send it to PostHog. This includes data like unique chat requests, unique search requests, unique requests to index data. Usage data is collected to help us understand how people are using Khoj, and to help us prioritize features.
    • We do not log your IP address, nor upload any of your personal data to PostHog.
    • You can see our telemetry aggregation code here and see our telemetry server here.
    • If you're self-hosting, you can opt out of telemetry by following these instructions.

Self-hosting isn't for everyone, so we've still taken steps to make Khoj privacy-friendly, even if you choose to use our cloud offering. Here's what to consider when using Khoj Cloud:

  1. Your embeddings are generated by an open source model within our own dedicated endpoint hosted on AWS with Huggingface. There's zero persistent memory to the Huggingface Inference endpoints (it's stateless).
  2. Your embeddings and the associated raw text are stored in a secure Postgres DB in our private AWS cloud. Your data is sharded on a unique user ID. We store the raw text in your files to improve file syncing and provide context when you chat with Khoj.
  3. When you use the single-sign-on option with Google, we only receive your name, a link to your profile photo, and your email address.

You can see our full privacy policy here.

:::tip[Info]
Your data is yours. We do not sell your data or use it for training models. Khoj is a sustainable, open-source alternative to closed-source, commercial personal AI. We have no interest in selling your data to make a quick buck.
:::

We have lots of ideas of how to make Khoj really robust as a personal AI and cloud offering, but also trust-less and privacy-centric. Please reach out if this is important to you, and you'd like to help us build it.


File: documentation/docs/get-started/setup.mdx


Self-Host

Learn about how to self-host Khoj on your own machine.

Benefits to self-hosting:

  1. Privacy: Your data will never have to leave your private network. You can even use Khoj without an internet connection if deployed on your personal computer.
  2. Customization: You can customize Khoj to your liking, from models, to host URL, to feature enablement.
mdx-code-block
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Setup Khoj

These are the general setup instructions for self-hosted Khoj.
You can install the Khoj server using either Docker or Pip.

:::info[First Run]
Restart your Khoj server after the first run to ensure all settings are applied correctly.
:::

Prerequisites

Docker

- *Option 1*: Click here to install [Docker Desktop](https://docs.docker.com/desktop/install/mac-install/). Make sure you also install the [Docker Compose](https://docs.docker.com/desktop/install/mac-install/) tool.
text
- *Option 2*: Use [Homebrew](https://brew.sh/) to install Docker and Docker Compose.
      ```shell
      brew install --cask docker
      brew install docker-compose
      ```
    <h3>Setup</h3>
    1. Download the Khoj docker-compose.yml file [from Github](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml)
       ```shell
       mkdir ~/.khoj && cd ~/.khoj
       wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml
       ```
    2. Configure the environment variables in the `docker-compose.yml`
       - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel.
       - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini commercial chat models respectively.
       - Uncomment `OPENAI_BASE_URL` to use [Ollama](/advanced/ollama?type=first-run&server=docker#setup) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio).
    3. Start Khoj by running the following command in the same directory as your docker-compose.yml file.
       ```shell
       cd ~/.khoj
       docker-compose up
       ```
  </TabItem>
  <TabItem value="windows" label="Windows">
  <h3>Prerequisites</h3>
  1. Install [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) and restart your machine
     ```shell
     # Run in PowerShell
     wsl --install
     ```
  2. Install [Docker Desktop](https://docs.docker.com/desktop/install/windows-install/) with **[WSL2 backend](https://docs.docker.com/desktop/wsl/#turn-on-docker-desktop-wsl-2)** (default)

  <h3>Setup</h3>
  1. Download the Khoj docker-compose.yml file [from Github](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml)
     ```shell
     # Windows users should use their WSL2 terminal to run these commands
     mkdir ~/.khoj && cd ~/.khoj
     wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml
     ```
  2. Configure the environment variables in the `docker-compose.yml`
     - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel.
     - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini commercial chat models respectively.
     - Uncomment `OPENAI_BASE_URL` to use [Ollama](/advanced/ollama) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio).
  3. Start Khoj by running the following command in the same directory as your docker-compose.yml file.
     ```shell
     # Windows users should use their WSL2 terminal to run these commands
     cd ~/.khoj
     docker-compose up
     ```
  </TabItem>
  <TabItem value="linux" label="Linux">
    <h3>Prerequisites</h3>
    Install [Docker Desktop](https://docs.docker.com/desktop/install/linux/).
    You can also use your package manager to install Docker Engine & Docker Compose.

    <h3>Setup</h3>
    1. Download the Khoj docker-compose.yml file [from Github](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml)
       ```shell
       mkdir ~/.khoj && cd ~/.khoj
       wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml
       ```
    2. Configure the environment variables in the `docker-compose.yml`
       - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel.
       - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini commercial chat models respectively.
       - Uncomment `OPENAI_BASE_URL` to use [Ollama](/advanced/ollama) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio).
    3. Start Khoj by running the following command in the same directory as your docker-compose.yml file.
       ```shell
       cd ~/.khoj
       docker-compose up
       ```
  </TabItem>
</Tabs>

:::info[Remote Access]
By default Khoj is only accessible on the machine it is running. To access Khoj from a remote machine see Remote Access Docs.
:::

Your setup is complete once you see 🌖 Khoj is ready to engage in the server logs on your terminal.

1. Install Khoj Server

- Make sure [python](https://realpython.com/installing-python/) and [pip](https://pip.pypa.io/en/stable/installation/) are installed on your machine - Check [llama-cpp-python setup](https://github.com/abetlen/llama-cpp-python?tab=readme-ov-file#supported-backends) if you hit any llama-cpp issues with the installation

Run the following command in your terminal to install the Khoj server.

```shell CMAKE_ARGS="-DGGML_METAL=on" python -m pip install 'khoj[local]' ``` ```shell python -m pip install 'khoj[local]' ``` Run the following command in PowerShell on Windows ```shell # Install Khoj py -m pip install 'khoj[local]' ``` ```shell # 1. To use NVIDIA (CUDA) GPU $env:CMAKE_ARGS = "-DGGML_CUDA=on" # 2. Install Khoj py -m pip install 'khoj[local]' ``` ```shell # 1. To use AMD (ROCm) GPU $env:CMAKE_ARGS = "-DGGML_HIPBLAS=on" # 2. Install Khoj py -m pip install 'khoj[local]' ``` ```shell # 1. To use VULCAN GPU $env:CMAKE_ARGS = "-DGGML_VULKAN=on" # 2. Install Khoj py -m pip install 'khoj[local]' ``` ```shell python -m pip install 'khoj[local]' ``` ```shell CMAKE_ARGS="-DGGML_CUDA=on" FORCE_CMAKE=1 python -m pip install 'khoj[local]' ``` ```shell CMAKE_ARGS="-DGGML_HIPBLAS=on" FORCE_CMAKE=1 python -m pip install 'khoj[local]' ``` ```shell CMAKE_ARGS="-DGGML_VULKAN=on" FORCE_CMAKE=1 python -m pip install 'khoj[local]' ```

2. Start Khoj Server

Run the following command from your terminal to start the Khoj service.

shell
USE_EMBEDDED_DB="true" khoj --anonymous-mode

--anonymous-mode allows access to Khoj without requiring login. This is usually fine for local only, single user setups. If you need authentication follow the authentication setup docs.

First Run

On the first run of the above command, you will be prompted to: 1. Create an admin account with an email and secure password 2. Customize the chat models to enable - Keep your [OpenAI](https://platform.openai.com/api-keys), [Anthropic](https://console.anthropic.com/account/keys), [Gemini](https://aistudio.google.com/app/apikey) API keys and [OpenAI](https://platform.openai.com/docs/models), [Anthropic](https://docs.anthropic.com/en/docs/about-claude/models#model-names), [Gemini](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#gemini-models), [Offline](https://huggingface.co/models?pipeline_tag=text-generation&library=gguf) chat model names handy to set any of them up during first run. 3. Your setup is complete once you see `🌖 Khoj is ready to engage` in the server logs on your terminal!

:::tip[Auto Start]
To start Khoj automatically in the background use Task scheduler on Windows or Cron on Mac, Linux (e.g. with @reboot khoj)
:::

Use Khoj

You can now open the web app at http://localhost:42110 and start interacting!
Nothing else is necessary, but you can customize your setup further by following the steps below.

Add Chat Models

Login to the Khoj Admin Panel

Go to http://localhost:42110/server/admin and login with the admin credentials you setup during installation.

:::info[CSRF Error]
Ensure you are using localhost, not 127.0.0.1, to access the admin panel to avoid the CSRF error.
:::

:::info[CSRF Trusted Origin or Unset Cookie Error]
If using a load balancer/reverse_proxy in front of your Khoj server: Set the environment variable KHOJ_ALLOWED_DOMAIN=your-internal-ip-or-domain to avoid this error.
If unset, it defaults to KHOJ_DOMAIN.
:::

:::info[DISALLOWED HOST or Bad Request (400) Error]
You may hit this if you try access Khoj exposed on a custom domain (e.g. 192.168.12.3 or example.com) or over HTTP.
Set the environment variables KHOJ_DOMAIN=your-external-ip-or-domain and KHOJ_NO_HTTPS=True if required to avoid this error.
:::

:::tip[Note]
Using Safari on Mac? You might not be able to login to the admin panel. Try using Chrome or Firefox instead.
:::

Configure Chat Model

Setup which chat model you'd want to use. Khoj supports local and online chat models.

:::info[Ollama Integration]
Using Ollama? See the Ollama Integration section for more custom setup instructions.
:::

  1. Create a new AI Model Api in the server admin settings.

    • Add your OpenAI API key
    • Give the configuration a friendly name like OpenAI
    • (Optional) Set the API base URL. It is only relevant if you're using another OpenAI-compatible proxy server like Ollama or LMStudio.
  2. Create a new chat model

    • Set the chat-model field to an OpenAI chat model. Example: gpt-4o.
    • Make sure to set the model-type field to OpenAI.
    • If your model supports vision, set the vision enabled field to true. This is currently only supported for OpenAI models with vision capabilities.
    • The tokenizer and max-prompt-size fields are optional. Set them only if you're sure of the tokenizer or token limit for the model you're using. Contact us if you're unsure what to do here.
1. Create a new [AI Model API](http://localhost:42110/server/admin/database/aimodelapi/add) in the server admin settings. - Add your [Anthropic API key](https://console.anthropic.com/account/keys) - Give the configuration a friendly name like `Anthropic`. Do not configure the API base url. 2. Create a new [chat model](http://localhost:42110/server/admin/database/chatmodel/add) - Set the `chat-model` field to an [Anthropic chat model](https://docs.anthropic.com/en/docs/about-claude/models#model-names). Example: `claude-3-5-sonnet-20240620`. - Set the `model-type` field to `Anthropic`. - Set the `ai model api` field to the Anthropic AI Model API you created in step 1. 1. Create a new [AI Model API](http://localhost:42110/server/admin/database/aimodelapi/add) in the server admin settings. - Add your [Gemini API key](https://aistudio.google.com/app/apikey) - Give the configuration a friendly name like `Gemini`. Do not configure the API base url. 2. Create a new [chat model](http://localhost:42110/server/admin/database/chatmodel/add) - Set the `chat-model` field to a [Google Gemini chat model](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#gemini-models). Example: `gemini-2.5-flash`. - Set the `model-type` field to `Google`. - Set the `ai model api` field to the Gemini AI Model API you created in step 1. Offline chat stays completely private and can work without internet using any open-weights model.

:::tip[System Requirements]

  • Minimum 8 GB RAM. Recommend 16Gb VRAM
  • Minimum 5 GB of Disk available
  • A Nvidia, AMD GPU or a Mac M1+ machine would significantly speed up chat responses
    :::
  1. Install any Openai API compatible local ai model server like llama-cpp-server, Ollama, vLLM etc.
  2. Add an ai model api on the admin panel
    • Set the api url field to the url of your local ai model provider like http://localhost:11434/v1/ for Ollama
  3. Restart the Khoj server to load models available on your local ai model provider
    • If that doesn't work, you'll need to manually add available chat model in the admin panel.
  4. Set the newly added chat model as your preferred model in your User chat settings
  5. Start chatting with your local AI!

:::tip[Multiple Chat Models]
Set your preferred default chat model in the Default, Advanced fields of your ServerChatSettings.
Khoj uses these chat model for all intermediate steps like intent detection, web search etc.
:::

:::info[Chat Model Fields]

  • The tokenizer and max-prompt-size fields are optional. Set them only if you're sure of the tokenizer or token limit for the model you're using. This improves context stuffing. Contact us if you're unsure what to do here.
  • Only tick the vision enabled field for OpenAI models with vision capabilities like gpt-4o. Vision capabilities in other chat models is not currently utilized.
    :::

Sync your Knowledge

  • You can chat with your notes and documents using Khoj.
  • Khoj can keep your files and folders synced using the Khoj Desktop, Obsidian or Emacs clients.
  • Your Notion workspace can be directly synced from the web app.
  • You can also just drag and drop specific files you want to chat with on the Web app.

Setup Khoj Clients

The Khoj web app is available by default to chat, search and configure Khoj.
You can also install a Khoj client to easily access it from Obsidian, Emacs, Whatsapp or your OS and keep your documents synced with Khoj.

:::info[Note]
Set the host URL on your clients settings page to your Khoj server URL. By default, use http://127.0.0.1:42110 or http://localhost:42110. Note that localhost may not work in all cases.
:::

- Read the Khoj Desktop app [setup docs](/clients/desktop#setup). - Read the Khoj Emacs package [setup docs](/clients/emacs#setup). - Read the Khoj Obsidian plugin [setup docs](/clients/obsidian#setup). - Read the Khoj Whatsapp app [setup docs](/clients/whatsapp).

Upgrade

Upgrade Server

```shell pip install --upgrade khoj ``` *Note: To upgrade to the latest pre-release version of the khoj server run below command* Run the commands below from the same directory where you have your `docker-compose.yml` file. This will fetch the latest build and upgrade your server. ```shell # Windows users should use their WSL2 terminal to run these commands cd ~/.khoj # assuming your khoj docker-compose.yml file is here docker-compose up --build ```

Upgrade Clients

- The Desktop app automatically updates to the latest released version on restart. - You can manually download the latest version from the [Khoj Website](https://khoj.dev/downloads). - Use your Emacs Package Manager to Upgrade - See [khoj.el package setup](/clients/emacs#setup) for details - Upgrade via the Community plugins tab on the settings pane in the Obsidian app - See the [khoj plugin setup](/clients/obsidian#setup) for details

Uninstall

Uninstall Server

```shell # uninstall khoj server pip uninstall khoj
text
# delete khoj postgres db
dropdb khoj -U postgres
```
</TabItem>
<TabItem value="docker" label="Docker">
Run the command below from the same directory where you have your `docker-compose` file.
This will remove the server containers, networks, images and volumes.

```shell
docker-compose down --volumes
```
</TabItem>

Uninstall Clients

Uninstall the Khoj Desktop client in the standard way from your OS. Uninstall the Khoj Emacs package in the standard way from Emacs. Uninstall via the Community plugins tab on the settings pane in the Obsidian app

Troubleshoot

Dependency conflict when trying to install Khoj python package with pip

  • Reason: When conflicting dependency versions are required by Khoj vs other python packages installed on your system
  • Fix: Install Khoj in a python virtual environment using venv or pipx to avoid this dependency conflicts
  • Process:
    1. Install pipx
    2. Use pipx to install Khoj to avoid dependency conflicts with other python packages.
      shell
      pipx install khoj
    3. Now start khoj using the standard steps described earlier

Install fails while building Tokenizer dependency

  • Details: pip install khoj fails while building the tokenizers dependency. Complains about Rust.
  • Fix: Install Rust to build the tokenizers package. For example on Mac run:
    shell
    brew install rustup
    rustup-init
    source ~/.cargo/env
  • Refer: Issue with Fix for more details

Khoj in Docker errors out with \"Killed\" in error message


File: documentation/docs/miscellaneous/_category_.json

{
"label": "Miscellaneous",
"position": 7,
"link": {
"type": "generated-index",
"description": "Additional resources for learning about Khoj"
}
}


File: documentation/docs/miscellaneous/credits.md


Credits

Many Open Source projects are used to power Khoj. Here's a few of them:


File: documentation/docs/miscellaneous/performance.md


Performance

Here are some top-level performance metrics for Khoj. These are rough estimates and will vary based on your hardware and data.

:::info
These performance metrics were last evaluated in 2022.
:::

Search performance

  • Semantic search using the default embeddings model is fairly fast at <100 ms across all content types
  • Reranking using the cross-encoder model is slower at <2s on 15 results. Tweak top_k to tradeoff speed for accuracy of results
  • Filters in query (e.g. by file, word or date) usually add <20ms to query latency

Indexing performance

  • Indexing is more strongly impacted by the size of the source data
  • Indexing 100K+ line corpus of notes takes about 10 minutes
  • Note: It should only take this long on the first run as the index is incrementally updated

Miscellaneous

  • Testing done on a Mac M1 and a >100K line corpus of notes

File: documentation/docs/miscellaneous/query-filters.md


Query Filters

Use structured query syntax to filter entries from your knowledge based used by search results or chat responses.

  • Word Filter: Get entries that include/exclude a specified term
    • Entries that contain term_to_include: +"term_to_include"
    • Entries that contain term_to_exclude: -"term_to_exclude"
  • Date Filter: Get entries containing dates in YYYY-MM-DD format from specified date (range)
    • Entries from April 1st 1984: dt:"1984-04-01"
    • Entries after March 31st 1984: dt>="1984-04-01"
    • Entries before April 2nd 1984 : dt<="1984-04-01"
  • File Filter: Get entries from a specified file
    • Entries from incoming.org file: file:"incoming.org"
  • Combined Example
    • what is the meaning of life? file:"1984.org" dt>="1984-01-01" dt<="1985-01-01" -"big" -"brother"
    • Adds all filters to the natural language query. It should return entries
      • from the file 1984.org
      • containing dates from the year 1984
      • excluding words "big" and "brother"
      • that best match the natural language query "what is the meaning of life?"

File: documentation/docs/miscellaneous/telemetry.md


Telemetry

We collect some high level, anonymized metadata about usage of self-hosted Khoj. This includes:

  • Client (Web, Emacs, Obsidian)
  • API usage (Search, Chat)
  • Configured content types (Github, Org, etc)
  • Request metadata (e.g., host, referrer)

We don't send any personal information or any information from/about your content. We only send the above metadata. This helps us prioritize feature development and understand how people are using Khoj. Don't just take our word for it -- you can see the code here.

Disable Telemetry

If you're self-hosting Khoj, you can opt out of telemetry at any time by setting the KHOJ_TELEMETRY_DISABLE environment variable to True via shell or docker-compose.yml

If you have any questions or concerns, please reach out to us on Discord.


File: src/interface/android/manifest-checksum.txt

6ee1711cf4f745dafc80c1cc13c3025342a0f5da


File: src/interface/android/twa-manifest.json

{
"packageId": "dev.khoj.app",
"host": "app.khoj.dev",
"name": "Khoj AI",
"launcherName": "Khoj",
"display": "standalone",
"themeColor": "#FFFFFF",
"themeColorDark": "#000000",
"navigationColor": "#000000",
"navigationColorDark": "#000000",
"navigationDividerColor": "#000000",
"navigationDividerColorDark": "#000000",
"backgroundColor": "#FFFFFF",
"enableNotifications": true,
"startUrl": "/",
"iconUrl": "https://assets.khoj.dev/khoj_lantern_1200x1200.png",
"splashScreenFadeOutDuration": 300,
"signingKey": {
"path": "android.keystore",
"alias": "android"
},
"appVersionName": "4",
"appVersionCode": 4,
"shortcuts": [],
"generatorApp": "bubblewrap-cli",
"webManifestUrl": "https://app.khoj.dev/static/khoj.webmanifest",
"fallbackType": "customtabs",
"features": {
"locationDelegation": {
"enabled": true
}
},
"alphaDependencies": {
"enabled": false
},
"enableSiteSettingsShortcut": true,
"isChromeOSOnly": false,
"isMetaQuest": false,
"fullScopeUrl": "https://app.khoj.dev/",
"minSdkVersion": 19,
"orientation": "natural",
"fingerprints": [
{
"name": "signing",
"value": "CC:98:4A:0A:F1:CC:84:26:AC:02:86:49:AA:69:64:B9:5E:63:A3:EF:18:56:EA:CA:13:C1:3A:15:CA:49:77:46"
},
{
"name": "upload",
"value": "D4:5A:6F:6C:18:28:D2:1C:78:27:92:C6:AC:DB:4C:12:C4:52:A1:88:9B:A1:F5:67:D1:22:FE:A0:0F:B1:AE:92"
}
],
"additionalTrustedOrigins": [],
"retainedBundles": [],
"appVersion": "4"
}


File: src/interface/android/app/src/main/res/raw/web_app_manifest.json

{"name":"Khoj","short_name":"Khoj","display":"standalone","start_url":"/","description":"The open, personal AI for your digital brain. You can ask Khoj to draft a message, paint your imagination, find information on the internet and even answer questions from your documents.","theme_color":"#ffffff","background_color":"#ffffff","icons":[{"src":"/static/assets/icons/khoj_lantern_128x128.png","sizes":"128x128","type":"image/png"},{"src":"/static/assets/icons/khoj_lantern_256x256.png","sizes":"256x256","type":"image/png"}],"screenshots":[{"src":"/static/assets/samples/phone-remember-plan-sample.png","sizes":"419x900","type":"image/png","form_factor":"narrow","label":"Remember and Plan"},{"src":"/static/assets/samples/phone-browse-draw-sample.png","sizes":"419x900","type":"image/png","form_factor":"narrow","label":"Browse and Draw"},{"src":"/static/assets/samples/desktop-remember-plan-sample.png","sizes":"1260x742","type":"image/png","form_factor":"wide","label":"Remember and Plan"},{"src":"/static/assets/samples/desktop-browse-draw-sample.png","sizes":"1260x742","type":"image/png","form_factor":"wide","label":"Browse and Draw"}]}


File: src/interface/desktop/README.md

Run it locally

Prerequisites

Install the runtime dependencies. This command should install all dev dependencies.

bash
yarn install

Run the application

bash
yarn start

Deploying the Electron App

Prerequisites

Install the ToDesktop CLI. Full documentation can be found here: https://www.npmjs.com/package/@todesktop/cli

bash
yarn global add @todesktop/cli

Configure the todesktop.json file. Fill in the id based on the application ID.

Build

This will prompt you to login. It triggers builds for all platforms.

bash
todesktop build

If you get an error saying the command is not found, make sure that your yarn global bin directory is in your PATH environment variable. You can find the location of the global bin directory by running yarn global bin. Add this line to your .bashrc or .zshrc file: export PATH="$PATH:$(yarn global bin)".


File: src/interface/desktop/package.json

{
"name": "Khoj",
"version": "2.0.0-beta.28",
"description": "Your Second Brain",
"author": "Khoj Inc. [email protected]",
"license": "GPL-3.0-or-later",
"homepage": "https://khoj.dev",
"repository": ""https://github.com/khoj-ai/khoj\"",
"productName": "Khoj",
"main": "main.js",
"private": false,
"devDependencies": {
"electron": "39.8.5"
},
"scripts": {
"start": "yarn electron ."
},
"dependencies": {
"@todesktop/runtime": "^2.0.0",
"axios": "^1.16.0",
"cron": "^2.4.3",
"electron-store": "^8.1.0"
},
"resolutions": {
"ajv": "^8.18.0",
"picomatch": ">=2.3.2"
}
}


File: src/interface/desktop/todesktop.json

{
"id": "",
"icon": "./assets/icons/favicon.icns",
"appPath": ".",
"schemaVersion": 1,
"windows": {
"icon": "./assets/icons/favicon-128x128.png"
}
}


File: src/interface/obsidian/README.md

Obsidian Development

You can use the Obsidian Khoj plugin to share your Obsidian knowledge base with your AI assistant. The plugin will index your notes and make them searchable by your AI assistant.

Development

In src/interface/obsidian, run:

bash
yarn install
yarn build

You'll want to link the built plugin to your Obsidian vault. You can do this by symlinking the built folder to your Obsidian vault's plugins folder. For example:

bash
ln -s /path/to/khoj-assistant/src/interface/obsidian /path/to/obsidian-vault/.obsidian/plugins/obsidian-assistant

Now, once you reload your Obsidian, you should see your updated plugin code running.


File: src/interface/obsidian/manifest.json

{
"id": "khoj",
"name": "Khoj",
"version": "2.0.0-beta.28",
"minAppVersion": "0.15.0",
"description": "Your Second Brain",
"author": "Khoj Inc.",
"authorUrl": "https://github.com/khoj-ai",
"isDesktopOnly": false
}


File: src/interface/obsidian/package.json

{
"name": "Khoj",
"version": "2.0.0-beta.28",
"description": "Your Second Brain",
"author": "Debanjum Singh Solanky, Saba Imran [email protected]",
"license": "GPL-3.0-or-later",
"main": "src/main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"version": "node version-bump.mjs && git add manifest.json versions.json"
},
"keywords": [
"search",
"chat",
"AI",
"assistant",
"second brain"
],
"devDependencies": {
"@types/dompurify": "3.2.0",
"@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "7.13.1",
"@typescript-eslint/parser": "7.13.1",
"builtin-modules": "3.3.0",
"esbuild": "0.14.47",
"obsidian": "^1.6.6",
"tslib": "2.4.0",
"typescript": "4.7.4"
},
"dependencies": {
"diff": "^8.0.3",
"isomorphic-dompurify": "^2.25.0"
},
"resolutions": {
"picomatch": ">=2.3.2"
}
}


File: src/interface/obsidian/tsconfig.json

{
"compilerOptions": {
"baseUrl": ".",
"inlineSourceMap": true,
"inlineSources": true,
"module": "ESNext",
"target": "ES2018",
"allowJs": true,
"noImplicitAny": true,
"moduleResolution": "node",
"importHelpers": true,
"isolatedModules": true,
"strictNullChecks": true,
"lib": [
"DOM",
"ES5",
"ES6",
"ES7",
"ES2018"
]
},
"include": [
"**/*.ts"
]
}


File: src/interface/obsidian/versions.json

{
"0.2.1": "0.15.0",
"0.2.5": "0.15.0",
"0.2.6": "0.15.0",
"0.3.0": "0.15.0",
"0.4.0": "0.15.0",
"0.5.0": "0.15.0",
"0.6.0": "0.15.0",
"0.6.1": "0.15.0",
"0.6.2": "0.15.0",
"0.7.0": "0.15.0",
"0.7.1": "0.15.0",
"0.8.0": "0.15.0",
"0.8.1": "0.15.0",
"0.8.2": "0.15.0",
"0.9.0": "0.15.0",
"0.10.0": "0.15.0",
"0.10.1": "0.15.0",
"0.11.0": "0.15.0",
"0.11.1": "0.15.0",
"0.11.2": "0.15.0",
"0.11.3": "0.15.0",
"0.11.4": "0.15.0",
"0.12.0": "0.15.0",
"0.12.1": "0.15.0",
"0.12.2": "0.15.0",
"0.12.3": "0.15.0",
"0.13.0": "0.15.0",
"0.14.0": "0.15.0",
"1.0.0": "0.15.0",
"1.0.1": "0.15.0",
"1.1.0": "0.15.0",
"1.2.0": "0.15.0",
"1.2.1": "0.15.0",
"1.3.0": "0.15.0",
"1.4.0": "0.15.0",
"1.5.0": "0.15.0",
"1.5.1": "0.15.0",
"1.6.0": "0.15.0",
"1.6.1": "0.15.0",
"1.6.2": "0.15.0",
"1.7.0": "0.15.0",
"1.8.0": "0.15.0",
"1.9.0": "0.15.0",
"1.10.0": "0.15.0",
"1.10.1": "0.15.0",
"1.10.2": "0.15.0",
"1.11.0": "0.15.0",
"1.11.1": "0.15.0",
"1.11.2": "0.15.0",
"1.12.0": "0.15.0",
"1.12.1": "0.15.0",
"1.13.0": "0.15.0",
"1.14.0": "0.15.0",
"1.15.0": "0.15.0",
"1.16.0": "0.15.0",
"1.17.0": "0.15.0",
"1.20.0": "0.15.0",
"1.20.1": "0.15.0",
"1.20.2": "0.15.0",
"1.20.3": "0.15.0",
"1.20.4": "0.15.0",
"1.21.0": "0.15.0",
"1.21.1": "0.15.0",
"1.21.2": "0.15.0",
"1.21.3": "0.15.0",
"1.21.4": "0.15.0",
"1.21.5": "0.15.0",
"1.21.6": "0.15.0",
"1.22.0": "0.15.0",
"1.22.1": "0.15.0",
"1.22.2": "0.15.0",
"1.22.3": "0.15.0",
"1.23.0": "0.15.0",
"1.23.1": "0.15.0",
"1.23.2": "0.15.0",
"1.23.3": "0.15.0",
"1.24.0": "0.15.0",
"1.24.1": "0.15.0",
"1.25.0": "0.15.0",
"1.26.0": "0.15.0",
"1.26.1": "0.15.0",
"1.26.2": "0.15.0",
"1.26.3": "0.15.0",
"1.26.4": "0.15.0",
"1.27.0": "0.15.0",
"1.27.1": "0.15.0",
"1.28.0": "0.15.0",
"1.28.1": "0.15.0",
"1.28.2": "0.15.0",
"1.28.3": "0.15.0",
"1.29.0": "0.15.0",
"1.29.1": "0.15.0",
"1.30.0": "0.15.0",
"1.30.1": "0.15.0",
"1.30.2": "0.15.0",
"1.30.3": "0.15.0",
"1.30.4": "0.15.0",
"1.30.5": "0.15.0",
"1.30.6": "0.15.0",
"1.30.7": "0.15.0",
"1.30.8": "0.15.0",
"1.30.9": "0.15.0",
"1.30.10": "0.15.0",
"1.31.0": "0.15.0",
"1.32.0": "0.15.0",
"1.32.1": "0.15.0",
"1.32.2": "0.15.0",
"1.33.0": "0.15.0",
"1.33.1": "0.15.0",
"1.33.2": "0.15.0",
"1.34.0": "0.15.0",
"1.35.0": "0.15.0",
"1.35.1": "0.15.0",
"1.35.2": "0.15.0",
"1.35.3": "0.15.0",
"1.36.0": "0.15.0",
"1.36.1": "0.15.0",
"1.36.2": "0.15.0",
"1.36.3": "0.15.0",
"1.36.4": "0.15.0",
"1.36.5": "0.15.0",
"1.36.6": "0.15.0",
"1.37.0": "0.15.0",
"1.37.1": "0.15.0",
"1.37.2": "0.15.0",
"1.38.0": "0.15.0",
"1.39.0": "0.15.0",
"1.40.0": "0.15.0",
"1.41.0": "0.15.0",
"1.42.0": "0.15.0",
"1.42.1": "0.15.0",
"1.42.2": "0.15.0",
"1.42.3": "0.15.0",
"1.42.4": "0.15.0",
"1.42.5": "0.15.0",
"1.42.6": "0.15.0",
"1.42.7": "0.15.0",
"1.42.8": "0.15.0",
"2.0.0-beta.1": "0.15.0",
"2.0.0-beta.2": "0.15.0",
"2.0.0-beta.3": "0.15.0",
"2.0.0-beta.4": "0.15.0",
"2.0.0-beta.5": "0.15.0",
"2.0.0-beta.6": "0.15.0",
"2.0.0-beta.7": "0.15.0",
"2.0.0-beta.8": "0.15.0",
"2.0.0-beta.9": "0.15.0",
"2.0.0-beta.10": "0.15.0",
"2.0.0-beta.11": "0.15.0",
"2.0.0-beta.12": "0.15.0",
"2.0.0-beta.13": "0.15.0",
"2.0.0-beta.14": "0.15.0",
"2.0.0-beta.15": "0.15.0",
"2.0.0-beta.16": "0.15.0",
"2.0.0-beta.17": "0.15.0",
"2.0.0-beta.18": "0.15.0",
"2.0.0-beta.19": "0.15.0",
"2.0.0-beta.20": "0.15.0",
"2.0.0-beta.21": "0.15.0",
"2.0.0-beta.22": "0.15.0",
"2.0.0-beta.23": "0.15.0",
"2.0.0-beta.24": "0.15.0",
"2.0.0-beta.25": "0.15.0",
"2.0.0-beta.26": "0.15.0",
"2.0.0-beta.27": "0.15.0",
"2.0.0-beta.28": "0.15.0"
}


File: src/interface/web/README.md

This is a Next.js project.

Getting Started

First, install the dependencies:

bash
bun install

In case you run into any dependency linking issues, you can try running:

bash
bun add next

Run the development server:

bash
bun dev

Make sure the rewrites in next.config.mjs are set up correctly for your environment. The rewrites are used to proxy requests to the API server.

js
rewrites: async () => {
        return [
            {
                source: '/api/:path*',
                destination: 'http://localhost:42110/api/:path*',
            },
        ];
    },

The destination should be the URL of the API server.

Open http://localhost:3000 with your browser to see the result.

You can start editing the page by modifying any of the .tsx pages. The page auto-updates as you edit the file.

Testing built files

We've setup a utility command for building and serving the built files. This is useful for testing the production build locally.

  1. Exporting code
    To build the files once and serve them, run:
bash
bun export

If you're using Windows:

bash
bun windowsexport
  1. Continuously building code

To keep building the files and serving them, run:

bash
bun watch

If you're using Windows:

bash
bun windowswatch

Now you should be able to load your custom pages from the Khoj app at http://localhost:42110/. To server any of the built files, you should update the routes in the web_client.py like so, where new_file is the new page you've added in this repo:

python
@web_client.post("/new_route", response_class=FileResponse)
@requires(["authenticated"], redirect="login_page")
def index_post(request: Request):

    return templates.TemplateResponse(
        "new_file/index.html",
        context={
            "request": request,
        },
    )

Learn More

To learn more about Next.js, take a look at the following resources:

You can check out the Next.js GitHub repository - your feedback and contributions are welcome!


File: src/interface/web/components.json

{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}


File: src/interface/web/package.json

{
"name": "khoj-ai",
"version": "2.0.0-beta.28",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"collectstatic": "bash -c 'pushd ../../../ && source .venv/bin/activate && python3 src/khoj/manage.py collectstatic --noinput && deactivate && popd'",
"cicollectstatic": "bash -c 'pushd ../../../ && uv run python src/khoj/manage.py collectstatic --noinput && popd'",
"export": "bun run build && cp -r out/ ../../khoj/interface/built && bun run collectstatic",
"ciexport": "bun run build && cp -r out/ ../../khoj/interface/built && bun run cicollectstatic",
"pypiciexport": "bun run build && mkdir -p ../../khoj/interface/compiled && cp -r out/. ../../khoj/interface/compiled && bun run cicollectstatic",
"watch": "nodemon --watch . --ext js,jsx,ts,tsx,css --ignore 'out//*' --exec 'bun run export'",
"windowswatch": "nodemon --watch . --ext js,jsx,ts,tsx,css --ignore 'out/
/' --exec 'bun run windowsexport'",
"windowscollectstatic": "cd ..\..\.. && .\.venv\Scripts\Activate.bat && py .\src\khoj\manage.py collectstatic --noinput && .\.venv\Scripts\deactivate.bat && cd ..",
"windowsexport": "bun run build && xcopy out ..\..\khoj\interface\built /E /Y && bun run windowscollectstatic",
"prepare": "husky"
},
"dependencies": {
"@excalidraw/excalidraw": "^0.17.6",
"@hookform/resolvers": "^3.10.0",
"@phosphor-icons/react": "^2.1.10",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-hover-card": "^1.1.15",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-menubar": "^1.1.16",
"@radix-ui/react-navigation-menu": "^1.2.14",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-progress": "^1.1.7",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-toast": "^1.2.15",
"@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/themes": "^3.2.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"cronstrue": "^2.61.0",
"dompurify": "^3.3.2",
"embla-carousel-autoplay": "^8.6.0",
"embla-carousel-react": "^8.6.0",
"file-saver": "^2.0.5",
"framer-motion": "^12.23.12",
"input-otp": "^1.4.2",
"intl-tel-input": "^23.9.3",
"jszip": "^3.10.1",
"katex": "^0.16.22",
"libphonenumber-js": "^1.12.17",
"lucide-react": "^0.468.0",
"markdown-it": "^14.1.0",
"markdown-it-highlightjs": "^4.2.0",
"mermaid": "^11.11.0",
"next": "15.5.18",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.62.0",
"react-use-websocket": "^4.13.0",
"swr": "^2.3.6",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
"vaul": "^0.9.9",
"zod": "^3.25.76"
},
"devDependencies": {
"@types/dompurify": "^3.2.0",
"@types/file-saver": "^2.0.7",
"@types/intl-tel-input": "^18.1.4",
"@types/katex": "^0.16.7",
"@types/markdown-it": "^14.1.2",
"@types/node": "^20.19.15",
"@types/react": "^18.3.24",
"@types/react-dom": "^18.3.7",
"autoprefixer": "^10.4.21",
"eslint": "^8.57.1",
"eslint-config-next": "15.5.18",
"eslint-config-prettier": "^9.1.2",
"eslint-plugin-prettier": "^5.5.4",
"husky": "^9.1.7",
"lint-staged": "^15.5.2",
"nodemon": "^3.1.10",
"postcss": "^8.5.6",
"prettier": "3.3.3",
"shadcn-ui": "^0.9.5",
"tailwindcss": "^3.4.17",
"typescript": "^5.9.2"
},
"prettier": {
"tabWidth": 4,
"printWidth": 100
},
"lint-staged": {
"
": "bun run lint"
},
"overrides": {
"picomatch": ">=2.3.2"
}
}


File: src/interface/web/tsconfig.json

{
"compilerOptions": {
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"downlevelIteration": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/": [
"./
"
]
},
"target": "ES2017"
},
"include": [
"next-env.d.ts",
"/*.ts",
"
/.tsx",
".next/types/**/
.ts",
"out/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}


File: src/interface/web/.eslintrc.json

{
"extends": [
"next",
"next/core-web-vitals",
"plugin:prettier/recommended"
],
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "warn"
}
}


File: src/khoj/app/README.md

Django App

Khoj uses Django as the backend framework primarily for its powerful ORM and the admin interface. The Django app is located in the src/app directory. We have one installed app, under the /database/ directory. This app is responsible for all the database related operations and holds all of our models. You can find the extensive Django documentation here 🌈.

Setup (Docker)

Prerequisites

  1. Ensure you have Docker installed.
  2. Ensure you have Docker Compose installed.

Run

Using the docker-compose.yml file in the root directory, you can run the Khoj app using the following command:

bash
docker-compose up

Setup (Local)

Install Postgres (with PgVector)

MacOS

Debian, Ubuntu

From official instructions

bash
sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
sudo apt install postgres-16 postgresql-16-pgvector

Windows

From Source

  1. Follow instructions to Install Postgres
  2. Follow instructions to Install PgVector in case you need to manually install it. Reproduced instructions below for convenience.
bash
cd /tmp
git clone --branch v0.5.1 https://github.com/pgvector/pgvector.git
cd pgvector
make
make install # may need sudo

Create the Khoj database

MacOS

bash
createdb khoj -U postgres

Debian, Ubuntu

bash
sudo -u postgres createdb khoj
  • [Optional] To set default postgres user's password
    • Execute ALTER USER postgres PASSWORD 'my_secure_password'; using psql
    • Run export $POSTGRES_PASSWORD=my_secure_password in your terminal for Khoj to use it later

Install Khoj

bash
uv sync --all-extras

Make Khoj DB migrations

This command will create the migrations for the database app. This command should be run whenever a new db model is added to the database app or an existing db model is modified (updated or deleted).

bash
python3 src/manage.py makemigrations

Run Khoj DB migrations

This command will run any pending migrations in your application.

bash
python3 src/manage.py migrate

Start Khoj Server

While we're using Django for the ORM, we're still using the FastAPI server for the API. This command automatically scaffolds the Django application in the backend.

Note: Anonymous mode bypasses authentication for local, single-user usage.

bash
python3 src/khoj/main.py --anonymous-mode

[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "dev.khoj.app",
"sha256_cert_fingerprints": [
"CC:98:4A:0A:F1:CC:84:26:AC:02:86:49:AA:69:64:B9:5E:63:A3:EF:18:56:EA:CA:13:C1:3A:15:CA:49:77:46",
"D4:5A:6F:6C:18:28:D2:1C:78:27:92:C6:AC:DB:4C:12:C4:52:A1:88:9B:A1:F5:67:D1:22:FE:A0:0F:B1:AE:92"
]
}
}]


File: src/khoj/processor/operator/README.md

Khoj Operator (Experimental)

Overview

Give Khoj its own computer to operate in a transparent, controlled manner. Accomplish tasks that require visual browsing, file editing and terminal access. Operator with research mode can work for 30+ minutes to accomplish more substantial tasks like feature development, travel planning, shopping etc.

Setup

Prerequisites

  • Docker and Docker Compose installed
  • Anthropic API key (required - only Anthropic models currently enabled)

Installation Steps

  1. Download the Khoj docker-compose.yml file

    shell
    mkdir ~/.khoj && cd ~/.khoj
    wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml
  2. Update the docker-compose.yml to enable computer operator

    • Set ANTHROPIC_API_KEY to your Anthropic API key
    • Uncomment KHOJ_OPERATOR_ENABLED=True to enable the operator tool
    • Uncomment - /var/run/docker.sock:/var/run/docker.sock to mount docker socket to allow khoj to operate its computer container.
  3. Start Khoj services

    shell
    docker-compose up
  4. Access the web app at http://localhost:42110
    Ensure you're using a claude 3.7+ models on your settings page

Usage

Use the /operator command or ask Khoj in normal or research mode to use the operator tool to have it operate its computer:

Examples:

  • /operator Find flights from Bangkok to Mexico City with no US layover
  • /research Clone the khoj repo and tell me how the operator tool is implemented

Supported Models

Currently enables only Anthropic models:

  • Claude Sonnet 4
  • Claude 3.7 Sonnet
  • Claude Opus 4

Note: OpenAI and other operator models are disabled while in development.

Capabilities

The operator can:

  • Computer Control: Take screenshots, click, type, navigate desktop
  • File Operations: Create, edit, and manage files
  • Terminal Access: Execute bash commands and scripts
  • Web Browsing: Navigate websites, documents and extract information

Architecture

  • Environments: Operator Computer and Browser environments
  • Models: Enable Vision Language Models (VLM) to operate computer
  • Execution: Containerize computer environment for security and isolation

File: src/telemetry/requirements.txt

uvicorn
fastapi
posthog
python-dotenv


File: tests/data/config.yml

content-type:
org:
compressed-jsonl: .notes.json.gz
embeddings-file: .note_embeddings.pt
index-header-entries: true
input-files:
- ~/first_from_config.org
- ~/second_from_config.org
input-filter:
- '.org'
- ~/notes/
.org
enable-offline-chat: false
search-type:
asymmetric:
cross-encoder: cross-encoder/ms-marco-MiniLM-L-6-v2
encoder: sentence-transformers/msmarco-MiniLM-L-6-v3
version: 0.15.0


File: tests/data/markdown/main_readme.md

Main Readme

Allow natural language search, chat with your documents using transformer based models

This is a test markdown file with multiple, nested child entries.

Dependencies

Installation

bash
pip install khoj

Run

Load ML model, generate embeddings and expose API to query specified org-mode files

shell
python3 main.py --input-files ~/Notes/Schedule.org ~/Notes/Incoming.org --verbose

Use

**Khoj via API**

*Khoj via Web*

Acknowledgments


File: .devcontainer/devcontainer.json

{
"name": "Khoj Development Environment",
"build": {
"dockerfile": "Dockerfile",
"context": "..", // Build context is the project root
"args": {
"PYTHON_VERSION": "3.12"
}
},
"forwardPorts": [
42110
],
"containerEnv": {
"USE_EMBEDDED_DB": "True"
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.black-formatter",
"ms-python.mypy-type-checker",
"ms-python.isort",
"esbenp.prettier-vscode",
"GitHub.copilot",
"GitHub.copilot-chat",
"GitHub.vscode-pull-request-github",
"github.vscode-github-actions",
"unifiedjs.vscode-mdx"
],
"settings": {
"python.defaultInterpreterPath": "/opt/venv/bin/python",
"python.formatting.provider": "black",
"python.linting.enabled": true,
"python.linting.mypyEnabled": true,
"python.linting.mypyArgs": [
"--config-file=pyproject.toml"
],
"mypy.configFile": "pyproject.toml",
"isort.args": [
"--profile",
"black",
"--filter-files"
],
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
}
}
},
"postCreateCommand": "scripts/dev_setup.sh --devcontainer",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {},
},
"remoteUser": "vscode"
}


File: .devcontainer/launch.json

{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Khoj",
"type": "debugpy",
"request": "launch",
"module": "src.khoj.main",
"console": "integratedTerminal",
"justMyCode": false,
"sudo": true,
"args": [
"-v",
"--anonymous-mode",
"--non-interactive",
"--port=42110"
],
"envFile": "${workspaceFolder}/.env",
"env": {
"KHOJ_ADMIN_EMAIL": "admin",
"KHOJ_ADMIN_PASSWORD": "admin",
"USE_EMBEDDED_DB": "true",
"KHOJ_DEBUG": "true",
"KHOJ_TELEMETRY_DISABLED": "true",
"PROMPTRACE_DIR": "${workspaceFolder}/promptrace"
}
}
]
}


File: .github/ISSUE_TEMPLATE/bug-report.yml

name: "🪲 Bug Report"
labels: ["fix"]
body:
- type: "markdown"
attributes:
value: |
> [!IMPORTANT]
> To save time for both you and us, try follow these guidelines before submitting a new issue:
> 1. Check if there is an existing issue tracking your bug on our Github.
> 2. When unsure if your issue is an actual bug, first discuss it on a Github discussion or the #bugs channel of our Discord server.
> These steps avoid opening issues which are duplicate or not actual bugs.

text
- type: "checkboxes"
  id: "server"
  attributes:
      label: "Server"
      options:
          - label: "Cloud (https://app.khoj.dev)"
            required: false
          - label: "Self-Hosted Docker"
            required: false
          - label: "Self-Hosted Python package"
            required: false
          - label: "Self-Hosted source code"
            required: false
  validations:
      required: true

- type: "checkboxes"
  id: "clients"
  attributes:
      label: "Clients"
      options:
          - label: "Web browser"
            required: false
          - label: "Desktop/mobile app"
            required: false
          - label: "Obsidian"
            required: false
          - label: "Emacs"
            required: false
          - label: "WhatsApp"
            required: false
  validations:
      required: true

- type: "checkboxes"
  id: "os"
  attributes:
      label: "OS"
      options:
          - label: "Windows"
            required: false
          - label: "macOS"
            required: false
          - label: "Linux"
            required: false
          - label: "Android"
            required: false
          - label: "iOS"
            required: false
  validations:
      required: true

- type: "input"
  id: "version"
  attributes:
      label: "Khoj version"
                    If using the cloud service, you can input, latest.\n
                    If self-hosting - please make sure to run the latest version of Khoj before reporting any issues as it may have already been fixed."
  validations:
      required: true

- type: "textarea"
  id: "description"
  attributes:
      label: "Describe the bug"
  validations:
      required: true

- type: "textarea"
  id: "current"
  attributes:
      label: "Current Behavior"
                    Please include full errors, uncaught exceptions, stack traces, screenshots and other relevant logs."
  validations:
      required: true

- type: "textarea"
  id: "expected"
  attributes:
      label: "Expected Behavior"
  validations:
      required: true

- type: "textarea"
  id: "reproduction"
  attributes:
      label: "Reproduction Steps"
                    code, if applicable.\n\n
                    For more complex issues, provide a link to a repository with the smallest sample that reproduces
                    the bug.\n
                    If the issue can be replicated without code, please provide a clear, step-by-step description of
                    the actions or conditions necessary to reproduce it. Any screenshots are also appreciated.\n
                    Avoid including business logic or unrelated details, as this makes diagnosis more difficult.\n\n
                    Whether it's a sequence of actions, code samples, or specific conditions, ensure that the steps
                    are clear enough to be easily followed and replicated."
  validations:
      required: true

- type: "textarea"
  id: "workaround"
  attributes:
      label: "Possible Workaround"
  validations:
      required: false

- type: "textarea"
  id: "context"
  attributes:
      label: "Additional Information"
                    Providing context helps us come up with a solution that is most useful in the real-world use case.\n
                    For example if self-hosting, provide environment details like OS versin, Docker version etc."
  validations:
      required: false
- type: "input"
  id: "discussion_link"
  attributes:
      label: "Link to Discord or Github discussion"
                    This will help to keep history of why this bug exists."
  validations:
      required: false

File: .github/ISSUE_TEMPLATE/feature-request.yml

name: "🙋 Feature Request"
labels: ["upgrade"]
body:
- type: "markdown"
attributes:
value: |
> [!IMPORTANT]
> To save time for both you and us, try follow these guidelines before submitting a feature request:
> 1. Check if there is an existing feature request that is similar to your on our Github.
> 2. We encourage you to first discuss your idea on a Github discussion or the #ideas channel of our Discord server.
> This step helps in understanding the new feature and determining if it's can be implemented at all.
Only proceed with this report if your idea was approved after the GitHub/Discord discussion.

text
- type: "textarea"
  id: "description"
  attributes:
      label: "Describe the feature"
  validations:
      required: true

- type: "textarea"
  id: "use-case"
  attributes:
      label: "Use Case"
  validations:
      required: true

- type: "textarea"
  id: "solution"
  attributes:
      label: "Proposed Solution"
  validations:
      required: false

- type: "textarea"
  id: "additional_info"
  attributes:
      label: "Additional Information"
  validations:
      required: false

- type: "input"
  id: "discussion_link"
  attributes:
      label: "Link to Discord or Github discussion"
                    This will help to keep history of why this feature request exists."
  validations:
      required: false

File: .github/workflows/build_khoj_el.yml

melpa quality checks like checkdoc, byte-compile, package-lint for khoj.el

using melpazoid: https://github.com/riscy/melpazoid

name: build khoj.el
on:
push:
branches:
- 'master'
- 'release/1.x'
paths:
- src/interface/emacs/.el
- .github/workflows/build_khoj_el.yml
pull_request:
branches:
- 'master'
- 'release/1.x'
paths:
- src/interface/emacs/
.el
- .github/workflows/build_khoj_el.yml

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.11
uses: actions/setup-python@v1
with: { python-version: 3.11 }
- name: ⏬️ Install Dependencies
run: |
python -m pip install --upgrade pip
sudo apt-get install emacs && emacs --version
git clone https://github.com/riscy/melpazoid.git ~/melpazoid
pip install ~/melpazoid
- name: 🌡️ Validate Khoj.el
env:
# Khoj recipe from https://github.com/melpa/melpa/pull/8321/files
RECIPE: (khoj :fetcher github :repo "khoj-ai/khoj" :files ("src/interface/emacs/*.el"))
EXIST_OK: true
LOCAL_REPO: ${{ github.workspace }}
run: echo $GITHUB_REF && make -C ~/melpazoid


File: .github/workflows/desktop.yml

name: desktop

on:
push:
tags:
- ""
branches:
- 'master'
- 'release/1.x'
paths:
- src/interface/desktop/
*
- .github/workflows/desktop.yml

jobs:
build:
name: 🖥️ Build, Release Desktop App
runs-on: ubuntu-latest
env:
TODESKTOP_ACCESS_TOKEN: ${{ secrets.TODESKTOP_ACCESS_TOKEN }}
TODESKTOP_EMAIL: ${{ secrets.TODESKTOP_EMAIL }}
defaults:
run:
shell: bash
working-directory: src/interface/desktop
steps:
- name: ⬇️ Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0

text
- name: ⤵️ Install Node
    uses: actions/setup-node@v3
    with:
      node-version: "lts/*"

  - name: ⚙️ Setup Desktop Build
    run: |
      yarn
      npm install @todesktop/cli
      sed -i "s/\"id\": \"\"/\"id\": \"${{ secrets.TODESKTOP_ID }}\"/g" todesktop.json

  - name: ⚙️ Build Desktop App
    run: |
      npx todesktop build

  # - name: 📦 Release Desktop App
  #   if: startsWith(github.ref, 'refs/tags/')
  #   run: |
  #     npx todesktop release --latest --force

  - name: ⤵️ Get Desktop Apps
    if: startsWith(github.ref, 'refs/tags/')
    run: |
      build_no=`npx todesktop builds --latest | tail -n 1 | awk -F'/' '{print $NF}'`
      sleep 900  # wait for 15 minutes for the build to be available
      wget https://download.khoj.dev/builds/$build_no/mac/dmg/arm64 -O khoj-${{ github.ref_name }}-arm64.dmg
      wget https://download.khoj.dev/builds/$build_no/mac/dmg/x64 -O khoj-${{ github.ref_name }}-x64.dmg
      wget https://download.khoj.dev/builds/$build_no/windows/nsis/x64 -O khoj-${{ github.ref_name }}-x64.exe
      wget https://download.khoj.dev/builds/$build_no/linux/deb/x64 -O khoj-${{ github.ref_name }}-x64.deb
      wget https://download.khoj.dev/builds/$build_no/linux/appImage/x64 -O khoj-${{ github.ref_name }}-x64.AppImage

  - name: ⏫ Upload Mac ARM App
    if: startsWith(github.ref, 'refs/tags/')
    uses: actions/upload-artifact@v4
    with:
      if-no-files-found: warn
      name: khoj-${{ github.ref_name }}-arm64.dmg
      path: src/interface/desktop/khoj-${{ github.ref_name }}-arm64.dmg

  - name: ⏫ Upload Mac x64 App
    if: startsWith(github.ref, 'refs/tags/')
    uses: actions/upload-artifact@v4
    with:
      if-no-files-found: warn
      name: khoj-${{ github.ref_name }}-x64.dmg
      path: src/interface/desktop/khoj-${{ github.ref_name }}-x64.dmg

  - name: ⏫ Upload Windows App
    if: startsWith(github.ref, 'refs/tags/')
    uses: actions/upload-artifact@v4
    with:
      if-no-files-found: warn
      name: khoj-${{ github.ref_name }}-x64.exe
      path: src/interface/desktop/khoj-${{ github.ref_name }}-x64.exe

  - name: ⏫ Upload Debian App
    if: startsWith(github.ref, 'refs/tags/')
    uses: actions/upload-artifact@v4
    with:
      if-no-files-found: warn
      name: khoj-${{ github.ref_name }}-x64.deb
      path: src/interface/desktop/khoj-${{ github.ref_name }}-x64.deb

  - name: ⏫ Upload Linux App Image
    if: startsWith(github.ref, 'refs/tags/')
    uses: actions/upload-artifact@v4
    with:
      if-no-files-found: warn
      name: khoj-${{ github.ref_name }}-x64.AppImage
      path: src/interface/desktop/khoj-${{ github.ref_name }}-x64.AppImage

File: .github/workflows/dockerize.yml

name: dockerize

on:
push:
tags:
- ""
branches:
- master
- release/1.x
paths:
- src/khoj/
*
- src/interface/web/**
- pyproject.toml
- Dockerfile
- prod.Dockerfile
- computer.Dockerfile
- docker-compose.yml
- .github/workflows/dockerize.yml
workflow_dispatch:
inputs:
tag:
default: 'dev'
khoj:
type: boolean
default: true
khoj-cloud:
type: boolean
default: true
khoj-computer:
type: boolean
default: true

env:

Tag Image with tag name on release

else with user specified tag (default 'dev') if triggered via workflow

else with run_id if triggered via a pull request

else with 'pre' (if push to master) or 'pre-1x' (if push to release/1.x)

DOCKER_IMAGE_TAG: ${{ github.ref_type == 'tag' && github.ref_name || github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name == 'release/1.x' && 'pre-1x' || 'pre' }}

jobs:
build:
name: Publish Khoj Docker Images
strategy:
fail-fast: false
matrix:
include:
- image: 'local'
platform: linux/amd64
runner: ubuntu-latest
- image: 'local'
platform: linux/arm64
runner: ubuntu-linux-arm64
- image: 'cloud'
platform: linux/amd64
runner: ubuntu-latest
- image: 'cloud'
platform: linux/arm64
runner: ubuntu-linux-arm64
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
# Get all history to correctly infer Khoj version using hatch
fetch-depth: 0

text
- name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v2

  - name: Login to GitHub Container Registry
    uses: docker/login-action@v2
    with:
      registry: ghcr.io
      username: ${{ github.repository_owner }}
      password: ${{ secrets.PAT }}

  - name: Get App Version
    id: hatch
    run: echo "version=$(pipx run hatch version)" >> $GITHUB_OUTPUT

  - name: 🧹 Delete huge unnecessary tools folder
    run: rm -rf /opt/hostedtoolcache

  - name: 📦 Build and Push Docker Image
    uses: docker/build-push-action@v4
    if: (matrix.image == 'local' && github.event_name == 'workflow_dispatch') && github.event.inputs.khoj == 'true' || (matrix.image == 'local' && github.event_name == 'push')
    with:
      context: .
      file: Dockerfile
      push: true
      tags: |
        ghcr.io/${{ github.repository }}:${{ env.DOCKER_IMAGE_TAG }}-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
      build-args: |
        VERSION=${{ steps.hatch.outputs.version }}
        PORT=42110
      cache-from: type=gha,scope=${{ matrix.image }}-${{ matrix.platform }}
      cache-to: type=gha,mode=max,scope=${{ matrix.image }}-${{ matrix.platform}}
      labels: |
        org.opencontainers.image.description=Khoj AI - Your second brain powered by LLMs and Neural Search
        org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}

  - name: 📦️⛅️ Build and Push Cloud Docker Image
    uses: docker/build-push-action@v4
    if: (matrix.image == 'cloud' && github.event_name == 'workflow_dispatch') && github.event.inputs.khoj-cloud == 'true' || (matrix.image == 'cloud' && github.event_name == 'push')
    with:
      context: .
      file: prod.Dockerfile
      push: true
      tags: |
        ghcr.io/${{ github.repository }}-cloud:${{ env.DOCKER_IMAGE_TAG }}-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
      build-args: |
        VERSION=${{ steps.hatch.outputs.version }}
        PORT=42110
      cache-from: type=gha,scope=${{ matrix.image }}-${{ matrix.platform }}
      cache-to: type=gha,mode=max,scope=${{ matrix.image }}-${{ matrix.platform}}
      labels: |
        org.opencontainers.image.description=Khoj AI Cloud - Your second brain powered by LLMs and Neural Search
        org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}

  - name: 📦️️💻 Build and Push Computer for Khoj
    uses: docker/build-push-action@v4
    if: github.event_name == 'workflow_dispatch' && github.event.inputs.khoj-computer == 'true' && matrix.image == 'local'
    with:
      context: .
      file: computer.Dockerfile
      push: true
      tags: |
        ghcr.io/${{ github.repository }}-computer:${{ env.DOCKER_IMAGE_TAG }}-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
      cache-from: type=gha,scope=computer-${{ matrix.platform }}
      cache-to: type=gha,mode=max,scope=computer-${{ matrix.platform }}
      labels: |
        org.opencontainers.image.description=Khoj AI Computer - A computer for your second brain to operate
        org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}

manifest:
needs: build
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

text
- name: Login to GitHub Container Registry
    uses: docker/login-action@v2
    with:
      registry: ghcr.io
      username: ${{ github.repository_owner }}
      password: ${{ secrets.PAT }}

  - name: Create and Push Local Manifest
    if: github.event.inputs.khoj == 'true' || github.event_name == 'push'
    run: |
      # Only put "latest.*" tag on stable releases (i.e 1.x, 2.x+)
      if [[ "${{ env.DOCKER_IMAGE_TAG }}" =~ ^[1-9]\.[0-9]+\.[0-9]+$ ]]; then
        LATEST_TAG="latest"
      else
        LATEST_TAG="${{ env.DOCKER_IMAGE_TAG }}"
      fi

      docker buildx imagetools create \
        -t ghcr.io/${{ github.repository }}:${{ env.DOCKER_IMAGE_TAG }} \
        -t ghcr.io/${{ github.repository }}:${LATEST_TAG} \
        ghcr.io/${{ github.repository }}:${{ env.DOCKER_IMAGE_TAG }}-amd64 \
        ghcr.io/${{ github.repository }}:${{ env.DOCKER_IMAGE_TAG }}-arm64

  - name: Create and Push Cloud Manifest
    if: github.event.inputs.khoj-cloud == 'true' || github.event_name == 'push'
    run: |
      # Only put "latest.*" tag on stable releases (i.e 1.x, 2.x+)
      if [[ "${{ env.DOCKER_IMAGE_TAG }}" =~ ^[1-9]\.[0-9]+\.[0-9]+$ ]]; then
        LATEST_TAG="latest"
      else
        LATEST_TAG="${{ env.DOCKER_IMAGE_TAG }}"
      fi

      docker buildx imagetools create \
        -t ghcr.io/${{ github.repository }}-cloud:${{ env.DOCKER_IMAGE_TAG }} \
        -t ghcr.io/${{ github.repository }}-cloud:${LATEST_TAG} \
        ghcr.io/${{ github.repository }}-cloud:${{ env.DOCKER_IMAGE_TAG }}-amd64 \
        ghcr.io/${{ github.repository }}-cloud:${{ env.DOCKER_IMAGE_TAG }}-arm64

  - name: Create and Push Computer Manifest
    if: github.event.inputs.khoj-computer == 'true'
    run: |
      docker buildx imagetools create \
        -t ghcr.io/${{ github.repository }}-computer:${{ env.DOCKER_IMAGE_TAG }} \
        -t ghcr.io/${{ github.repository }}-computer:${{ github.ref_type == 'tag' && 'latest' || env.DOCKER_IMAGE_TAG }} \
        ghcr.io/${{ github.repository }}-computer:${{ env.DOCKER_IMAGE_TAG }}-amd64 \
        ghcr.io/${{ github.repository }}-computer:${{ env.DOCKER_IMAGE_TAG }}-arm64

File: .github/workflows/dockerize_telemetry_server.yml

name: dockerize telemetry server

on:
push:
branches:
- master
paths:
- src/telemetry/**
- .github/workflows/dockerize_telemetry_server.yml
pull_request:
branches:
- master
paths:
- src/telemetry/**
- .github/workflows/dockerize_telemetry_server.yml
workflow_dispatch:

env:
DOCKER_IMAGE_TAG: ${{ github.ref == 'refs/heads/master' && 'latest' || github.event.pull_request.number }}

jobs:
build:
name: Build Docker Image, Push to Container Registry
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

text
- name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v2

  - name: Login to GitHub Container Registry
    uses: docker/login-action@v2
    with:
      registry: ghcr.io
      username: ${{ github.repository_owner }}
      password: ${{ secrets.PAT }}

  - name: 📦 Build and Push Docker Image
    uses: docker/build-push-action@v2
    with:
      context: src/telemetry
      file: src/telemetry/Dockerfile
      push: true
      tags: ghcr.io/${{ github.repository }}-telemetry:${{ env.DOCKER_IMAGE_TAG }}
      secrets: |
        "POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }}"

File: .github/workflows/github_pages_deploy.yml

name: deploy documentation
on:
push:
branches:
- 'master'

permissions:
contents: read
pages: write
id-token: write

jobs:
deploy:
environment:
name: github-pages
url: https://docs.khoj.dev
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
# 👇 Build steps
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: lts/*
cache: yarn
cache-dependency-path: documentation/yarn.lock
- name: Install dependencies
run: |
cd documentation
yarn install --frozen-lockfile --non-interactive
- name: Build
run: |
cd documentation
yarn build
# 👆 Build steps
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# 👇 Specify build output path
path: documentation/build
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4


File: .github/workflows/pre-commit.yml

name: pre-commit

on:
pull_request:
branches:
- master
- release/1.x
paths:
- src/**
- tests/**
- config/**
- pyproject.toml
- .pre-commit-config.yml
- .github/workflows/test.yml
push:
branches:
- master
- release/1.x
paths:
- src/khoj/**
- tests/**
- config/**
- pyproject.toml
- .pre-commit-config.yml
- .github/workflows/test.yml

jobs:
test:
name: Setup Application and Lint
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

text
- name: Install uv
    uses: astral-sh/setup-uv@v4
    with:
      version: "latest"

  - name: Set up Python 3.11
    run: uv python install 3.11

  - name: ⏬️ Install Dependencies
    run: |
      sudo apt update && sudo apt install -y libegl1

  - name: ⬇️ Install Application
    env:
      UV_INDEX: "https://download.pytorch.org/whl/cpu"
      UV_INDEX_STRATEGY: "unsafe-best-match"
      CUDA_VISIBLE_DEVICES: ""
    run: uv sync --all-extras

  - name: 🌡️ Validate Application
    run: uv run pre-commit run --hook-stage manual --all

File: .github/workflows/pypi.yml

name: pypi

on:
push:
tags:
- ""
branches:
- 'master'
- 'release/1.x'
paths:
- src/khoj/
*
- src/interface/web/**
- pyproject.toml
- .github/workflows/pypi.yml
pull_request:
branches:
- 'master'
- 'release/1.x'
paths:
- src/khoj/**
- src/interface/web/**
- pyproject.toml
- .github/workflows/pypi.yml
workflow_dispatch:

jobs:
publish:
name: Publish Python Package to PyPI
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

text
- name: Install uv
    uses: astral-sh/setup-uv@v4
    with:
      version: "latest"

  - name: Set up Python 3.11
    run: uv python install 3.11.12

  - name: ⬇️ Install Server
    run: uv sync --all-extras

  - name: Install bun
    uses: oven-sh/setup-bun@v2
    with:
      bun-version: latest

  - name: ⬇️ Install Web Client
    run: |
      bun install
      bun pypiciexport
    working-directory: src/interface/web

  - name: ⚙️ Build Python Package
    run: |
      # Setup Environment for Reproducible Builds
      export PYTHONHASHSEED=42
      export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
      rm -rf dist

      # Build PyPI Package
      uv build

  - name: 🌡️ Validate Python Package
    run: |
      # Validate PyPi Package
      uv tool run check-wheel-contents dist/*.whl --ignore W002,W004
      uv tool run twine check dist/*

  - name: ⏫ Upload Python Package Artifacts
    uses: actions/upload-artifact@v4
    with:
      name: khoj
      path: dist/khoj-*.whl

  - name: 📦 Publish Python Package to PyPI
    if: startsWith(github.ref, 'refs/tags') || github.ref == 'refs/heads/master' || github.ref == 'refs/heads/release/1.x'
    uses: pypa/gh-action-pypi-publish@release/v1.12
    with:
      skip-existing: true
      print-hash: true

File: .github/workflows/release.yml

name: release

on:
push:
tags:
- "*"
workflow_dispatch:
inputs:
version:
required: true
type: string

jobs:
publish_obsidian_plugin:
name: 💎 Publish Obsidian Plugin
runs-on: ubuntu-latest
permissions:
contents: write
defaults:
run:
shell: bash
working-directory: src/interface/obsidian
steps:
- uses: actions/checkout@v3

text
- name: Install Node
    uses: actions/setup-node@v3
    with:
      node-version: "lts/*"

  - name: ⚙️ Build Obsidian Plugin
    run: |
      yarn
      yarn run build --if-present

  - name: ⏫ Upload Obsidian Plugin main.js
    uses: actions/upload-artifact@v4
    with:
      if-no-files-found: error
      name: main.js
      path: src/interface/obsidian/main.js

  - name: ⏫ Upload Obsidian Plugin manifest.json
    uses: actions/upload-artifact@v4
    with:
      if-no-files-found: error
      name: manifest.json
      path: src/interface/obsidian/manifest.json

  - name: ⏫ Upload Obsidian Plugin styles.css
    uses: actions/upload-artifact@v4
    with:
      if-no-files-found: error
      name: styles.css
      path: src/interface/obsidian/styles.css

  - name: 🌈 Create Release
    uses: softprops/action-gh-release@v1
    if: startsWith(github.ref, 'refs/tags/')
    with:
      generate_release_notes: true
      files: |
        src/interface/obsidian/main.js
        src/interface/obsidian/manifest.json
        src/interface/obsidian/styles.css

File: .github/workflows/run_evals.yml

name: eval

on:

Run on every release

push:
tags:
- "*"

Allow manual triggers from GitHub UI

workflow_dispatch:
inputs:
khoj_mode:
required: true
default: 'default'
type: choice
options:
- general
- default
- research
dataset:
required: true
default: 'frames'
type: choice
options:
- frames
- simpleqa
- gpqa
- math500
sample_size:
required: false
default: 200
type: number
sandbox:
required: false
default: 'terrarium'
type: choice
options:
- terrarium
- e2b
chat_model:
required: false
default: 'gemini-2.5-flash'
type: string
max_research_iterations:
required: false
default: 5
type: number
openai_api_key:
required: false
default: ''
type: string
openai_base_url:
required: false
default: 'https://api.openai.com/v1'
type: string
randomize:
required: false
default: 'true'
type: choice
options:
- 'false'
- 'true'
dataset_seed:
required: false
default: ''
type: string

jobs:
eval:
runs-on: ubuntu-latest
strategy:
matrix:
# Use input from manual trigger if available, else run all combinations
khoj_mode: ${{ github.event_name == 'workflow_dispatch' && fromJSON(format('["{0}"]', inputs.khoj_mode)) || fromJSON('["general", "default", "research"]') }}
dataset: ${{ github.event_name == 'workflow_dispatch' && fromJSON(format('["{0}"]', inputs.dataset)) || fromJSON('["frames", "gpqa"]') }}

text
services:
  postgres:
    image: pgvector/pgvector:pg18
    env:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
      POSTGRES_DB: postgres
    ports:
      - 5432:5432
    options: >-
      --health-cmd pg_isready
      --health-interval 10s
      --health-timeout 5s
      --health-retries 5

steps:
  - uses: actions/checkout@v3
    with:
      fetch-depth: 0

  - name: Install uv
    uses: astral-sh/setup-uv@v4
    with:
      version: "latest"

  - name: Set up Python
    run: uv python install 3.10

  - name: Get App Version
    id: hatch
    run: |
      # Mask relevant workflow inputs as secret early
      OPENAI_API_KEY=$(jq -r '.inputs.openai_api_key' $GITHUB_EVENT_PATH)
      echo ::add-mask::$OPENAI_API_KEY
      echo OPENAI_API_KEY="$OPENAI_API_KEY" >> $GITHUB_ENV

      # Get app version from hatch
      echo "version=$(pipx run hatch version)" >> $GITHUB_OUTPUT

  - name: ⏬️ Install Dependencies
    env:
      DEBIAN_FRONTEND: noninteractive
    run: |
      # install dependencies
      sudo apt update && sudo apt install -y git libegl1 sqlite3 libsqlite3-dev libsqlite3-0 ffmpeg libsm6 libxext6
      # install terrarium for code sandbox
      git clone https://github.com/khoj-ai/terrarium.git && cd terrarium && npm install --legacy-peer-deps && mkdir pyodide_cache

  - name: ⬇️ Install Application
    env:
      UV_INDEX: "https://download.pytorch.org/whl/cpu"
      UV_INDEX_STRATEGY: "unsafe-best-match"
      CUDA_VISIBLE_DEVICES: ""
    run: |
      sed -i 's/dynamic = \["version"\]/version = "${{ steps.hatch.outputs.version }}"/' pyproject.toml
      uv sync --all-extras

  - name: 📝 Run Eval
    env:
      KHOJ_MODE: ${{ matrix.khoj_mode }}
      SAMPLE_SIZE: ${{ github.event_name == 'workflow_dispatch' && inputs.sample_size || 200 }}
      BATCH_SIZE: "20"
      RANDOMIZE: ${{ github.event_name == 'workflow_dispatch' && inputs.randomize || 'true' }}
      DATASET_SEED: ${{ github.event_name == 'workflow_dispatch' && inputs.dataset_seed || github.run_id }}
      KHOJ_LLM_SEED: "42"
      KHOJ_URL: "http://localhost:42110"
      KHOJ_DEFAULT_CHAT_MODEL: ${{ github.event_name == 'workflow_dispatch' && inputs.chat_model || 'gemini-2.5-flash' }}
      KHOJ_RESEARCH_ITERATIONS: ${{ github.event_name == 'workflow_dispatch' && inputs.max_research_iterations || 10 }}
      KHOJ_AUTO_READ_WEBPAGE: ${{ github.event_name == 'workflow_dispatch' && inputs.auto_read_webpage || 'false' }}
      GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
      OPENAI_BASE_URL: ${{ github.event_name == 'workflow_dispatch' && inputs.openai_base_url || 'https://api.openai.com/v1' }}
      SERPER_DEV_API_KEY: ${{ matrix.dataset != 'math500' && secrets.SERPER_DEV_API_KEY || '' }}
      OLOSTEP_API_KEY: ${{ matrix.dataset != 'math500' && secrets.OLOSTEP_API_KEY || ''}}
      FIRECRAWL_API_KEY: ${{ matrix.dataset != 'math500' && secrets.FIRECRAWL_API_KEY || '' }}
      HF_TOKEN: ${{ secrets.HF_TOKEN }}
      E2B_API_KEY: ${{ inputs.sandbox == 'e2b' && secrets.E2B_API_KEY || '' }}
      E2B_TEMPLATE: ${{ vars.E2B_TEMPLATE }}
      KHOJ_ADMIN_EMAIL: khoj
      KHOJ_ADMIN_PASSWORD: khoj
      POSTGRES_HOST: localhost
      POSTGRES_PORT: 5432
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
      USE_EMBEDDED_DB: "true"
      KHOJ_TELEMETRY_DISABLE: "True"  # To disable telemetry for tests
    run: |
      set -euo pipefail

      # Start Khoj server in background
      # Capture stdout/stderr to a log for debugging if startup fails
      uv run khoj --anonymous-mode --non-interactive -vv > khoj_server.log 2>&1 &
      KHOJ_PID=$!
      echo "Started Khoj (PID=$KHOJ_PID)"

      # Start code sandbox
      npm install pm2
      NODE_ENV=production npm run ci --prefix terrarium

      # Wait for server to be ready
      timeout=120
      while ! curl -s http://localhost:42110/api/health > /dev/null; do
        # If process died, surface logs and fail fast
        if ! kill -0 "$KHOJ_PID" 2>/dev/null; then
          echo "Khoj process exited before becoming healthy. Logs:" >&2
          sed -n '1,200p' khoj_server.log >&2 || true
          exit 1
        fi
        if [ $timeout -le 0 ]; then
          echo "Timed out waiting for Khoj server. Partial logs:" >&2
          sed -n '1,200p' khoj_server.log >&2 || true
          exit 1
        fi
        echo "Waiting for Khoj server... ($timeout s left)"
        sleep 2
        timeout=$((timeout-2))
      done
      echo "Khoj server is healthy"

      # Run evals
      uv run python tests/evals/eval.py -d ${{ matrix.dataset }}

  - name: Upload Results
    if: always()  # Upload results even if tests fail
    uses: actions/upload-artifact@v4
    with:
      name: eval-results-${{ steps.hatch.outputs.version }}-${{ matrix.khoj_mode }}-${{ matrix.dataset }}
      path: |
        *_evaluation_results_*.csv
        *_evaluation_summary_*.txt
        khoj_server.log

  - name: Display Results
    if: always()
    run: |
      # Read and display summary
      echo "## Evaluation Summary of Khoj on ${{ matrix.dataset }} in ${{ matrix.khoj_mode }} mode" >> $GITHUB_STEP_SUMMARY
      echo "**$(head -n 1 *_evaluation_summary_*.txt)**" >> $GITHUB_STEP_SUMMARY
      echo "- Khoj Version: ${{ steps.hatch.outputs.version }}" >> $GITHUB_STEP_SUMMARY
      echo "- Chat Model: ${{ inputs.chat_model || 'gemini-2.5-flash' }}" >> $GITHUB_STEP_SUMMARY
      echo "- Code Sandbox: ${{ inputs.sandbox || 'terrarium' }}" >> $GITHUB_STEP_SUMMARY
      echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
      tail -n +2 *_evaluation_summary_*.txt >> $GITHUB_STEP_SUMMARY
      echo "" >> $GITHUB_STEP_SUMMARY
      echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

      # Display in logs too
      echo "===== EVALUATION RESULTS ====="
      cat *_evaluation_summary_*.txt

File: .github/workflows/test.yml

name: test

on:
pull_request:
branches:
- master
- release/1.x
paths:
- src/khoj/**
- tests/**
- '!tests/evals/'
- config/

- pyproject.toml
- .pre-commit-config.yml
- .github/workflows/test.yml
push:
branches:
- master
- release/1.x
paths:
- src/khoj/**
- tests/**
- '!tests/evals/'
- config/

- pyproject.toml
- .pre-commit-config.yml
- .github/workflows/test.yml

jobs:
test:
name: Run Tests
runs-on: ubuntu-latest
container: ubuntu:26.04
strategy:
fail-fast: false
matrix:
python_version:
- '3.10'
- '3.11'
- '3.12'

text
services:
  postgres:
    image: pgvector/pgvector:pg18
    env:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
    ports:
      - 5432:5432
    options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

steps:
  - uses: actions/checkout@v3
    with:
      fetch-depth: 0

  - name: Install uv
    uses: astral-sh/setup-uv@v4
    with:
      version: "latest"

  - name: Set up Python ${{ matrix.python_version }}
    run: uv python install ${{ matrix.python_version }}

  - name: ⏬️ Install Dependencies
    env:
      DEBIAN_FRONTEND: noninteractive
    run: |
      apt update && apt install -y git libegl1 libgl1 sqlite3 libsqlite3-dev libsqlite3-0 ffmpeg libsm6 libxext6

  - name: ⬇️ Install Postgres
    env:
      DEBIAN_FRONTEND: noninteractive
    run : |
      apt install -y postgresql postgresql-client postgresql-server-dev-all

  - name: ⬇️ Install Application
    env:
      UV_INDEX: "https://download.pytorch.org/whl/cpu"
      UV_INDEX_STRATEGY: "unsafe-best-match"
      CUDA_VISIBLE_DEVICES: ""
    run: sed -i 's/dynamic = \["version"\]/version = "0.0.0"/' pyproject.toml && uv sync --all-extras

  - name: 🧪 Test Application
    env:
      POSTGRES_HOST: postgres
      POSTGRES_PORT: 5432
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
      GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
    run: uv run pytest
    timeout-minutes: 10

File: .github/workflows/test_khoj_el.yml

name: test khoj.el

on:
push:
branches:
- 'master'
- 'release/1.x'
paths:
- src/interface/emacs/.el
- src/interface/emacs/tests/
.el
- .github/workflows/test_khoj_el.yml
pull_request:
branches:
- 'master'
- 'release/1.x'
paths:
- src/interface/emacs/.el
- src/interface/emacs/tests/
.el
- .github/workflows/test_khoj_el.yml

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
emacs_version:
- 28.2
- 29.4
- 30.2
- snapshot
steps:
- uses: purcell/setup-emacs@master
with:
version: ${{ matrix.emacs_version }}
- uses: actions/checkout@v3
- name: 🧪 Test Khoj.el
run: |
# Run ERT tests on khoj.el
emacs -batch
--eval "(progn
(require 'package)
(push '("melpa" . "https://melpa.org/packages/\") package-archives)
(package-initialize)
(unless package-archive-contents (package-refresh-contents))
(unless (package-installed-p 'transient) (package-install 'transient))
(unless (package-installed-p 'dash) (package-install 'dash))
(unless (package-installed-p 'org) (package-install 'org))
)"
-l ert
-l ./src/interface/emacs/khoj.el
-l ./src/interface/emacs/tests/khoj-tests.el
-f ert-run-tests-batch-and-exit