timothy

agent
Security Audit
Fail
Health Warn
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 6 GitHub stars
Code Fail
  • network request — Outbound network request in deploy/release/install.sh
  • rm -rf — Recursive force deletion command in scripts/canary-coding.sh
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Self-hosted personal AI assistant: chat, cost tracking, tasks, and agents, running on your own hardware, on your own LLM providers.

README.md

Timothy

CI
Release
Go
React
TypeScript
PostgreSQL
License: MIT

Timothy

Self-hosted personal AI assistant: chat, cost tracking, tasks, and agents, running on your own hardware, talking to whichever LLM providers you configure.

Status: early, under active development.

Alpha releases with prebuilt images are available on the Releases page; expect rough edges and breaking changes between releases.

What works today

  • Multi-provider chat: Anthropic, Amazon Bedrock, and any OpenAI-compatible API behind one gateway; providers, models, and per-task routing are database configuration, editable at runtime from the settings panel with hot reload.
  • Sessions that survive: every conversation is an append-only event log; kill a container mid-stream and the session resumes and replays exactly.
  • Tools, permissions, skills: the agent loop executes tools behind a constraint/permission chain (destructive actions require explicit approval in the UI); skill packs load lazily by task.
  • Missions: long-running agent tasks with a pure state machine, harness-owned verification (artifacts must exist before any model claim counts), per-mission sandboxes, budgets, and LLM review; recurring missions fire from cron schedules.
  • Long-term memory: staged fact extraction with a confirmation queue, hybrid pgvector retrieval (vector + text + entity, RRF-fused) under a strict token budget.
  • Cost accounting: every request lands in a ledger with honest pricing (unknown price is recorded as null, never guessed); usage dashboard, spend budgets with alerts, Prometheus metrics on every service.
  • Privacy floor: tools whose output carries sensitive data (raw email) pin the rest of their turn, and every downstream side-call (memory extraction, compaction), to a dedicated route you can chain to a local model.

Architecture

Go microservices behind a single public API, one PostgreSQL database, React web UI. All run via Docker Compose.

Service Role
brain Public API: chat orchestration, agent loop, missions, event-sourced sessions, SSE streaming
gateway Internal LLM gateway: multi-provider routing, cost ledger
memoryd Internal memory service: pgvector-backed recall
sandboxd Internal service holding the Docker socket: per-mission sandbox containers
web React + Tailwind interface: chat, missions, usage, settings
searxng Internal metasearch backend for the web_search tool
markitdown Internal Python sidecar: file→markdown conversion
whisper Internal Python sidecar: local speech-to-text for the web mic button

Plus Postgres (18 + pgvector), internal only, no host port. Migrations are embedded in each Go binary and applied automatically at startup; there's no separate migrate command. Every Go service exposes GET /health and GET /metrics.

Sessions are an append-only event log: every turn, tool run, and compaction is an immutable event, so conversations survive crashes mid-stream and replay exactly as they happened.

Published ports (everything else is compose-internal):

Port What
3300 Web UI
8300 Brain (public API)
3301 Vite dev server (make dev)

Quick start (prebuilt images)

The fastest way to run Timothy: no Go/Node toolchain, no build step, just Docker and the released images.

  1. Make an empty directory and download the installer from the latest release. While Timothy is alpha, every release is marked prerelease, so GitHub's /releases/latest redirect doesn't resolve; look up the newest tag instead:

    mkdir timothy && cd timothy
    TAG=$(curl -fsSL https://api.github.com/repos/timothy-agent/timothy/releases \
      | grep -E '"tag_name"|"published_at"' | paste - - \
      | sed -E 's/.*"tag_name": "([^"]+)".*"published_at": "([^"]+)".*/\2 \1/' \
      | sort -r | head -1 | awk '{print $2}')
    curl -fsSLo install.sh "https://github.com/timothy-agent/timothy/releases/download/$TAG/install.sh"
    
  2. Read install.sh before running it. Then run it:

    sh install.sh
    

    It downloads docker-compose.yml and env.example, generates a .env with fresh secrets (POSTGRES_PASSWORD, TIMOTHY_MASTER_KEY, TIMOTHY_API_TOKEN), pulls the images, starts the stack, and prints a magic sign-in link once the web UI is up.

  3. Open the printed link: the web UI signs in automatically from the token in the URL.

To upgrade later: bump TIMOTHY_VERSION in .env and run docker compose pull && docker compose up -d, or just re-run install.sh (it leaves an existing .env untouched and only refreshes docker-compose.yml and the searxng config).

The rest of this README covers building and running from source instead.

Build from source

Prerequisites:

  • Docker (Desktop, or engine + compose plugin).
  • A hugeicons.com account with an active token. The web UI's icons are HugeIcons Pro (a paid icon set) and the token is required to build the web image; without it, make up fails on the web build step. Not needed for the prebuilt-image quick start above.
  1. Copy the env file and fill in the required values:

    cp deploy/env.example deploy/.env
    

    Open deploy/.env and set:

    • POSTGRES_PASSWORD: compose refuses to start without it.
    • TIMOTHY_MASTER_KEY: generate with openssl rand -base64 32. This is the root of trust for the encrypted secret store (provider API keys, OAuth tokens all live behind it). Compose hard-fails if it's blank. Back this up: losing it makes every stored secret unrecoverable.
    • TIMOTHY_API_TOKEN: generate with openssl rand -hex 32. Bearer token for the API; if it's blank, every request 401s.
    • HUGEICONS_TOKEN: your HugeIcons Pro token, needed to build the web image.
  2. (Optional) Missions sandbox. deploy/env.example prefills MISSION_SANDBOX_IMAGE=timothy-sandbox:latest, but that image doesn't exist until you build it:

    make sandbox-image
    

    Skip this and leave MISSION_SANDBOX_IMAGE empty in .env if you don't need missions isolated in their own container; mission shell commands then run in-process instead.

  3. (Linux only) Set DOCKER_SOCK_GID so sandboxd can use the Docker socket:

    stat -c '%g' /var/run/docker.sock
    

    Put that number in .env. On Docker Desktop the default of 0 works as-is. Note: mounting docker.sock gives sandboxd root-equivalent access to the host. It's isolated on its own compose network, read-only, and runs with all capabilities dropped, but the socket itself is the trust boundary, so only run this on a host you control.

  4. Start the stack:

    make up
    

    Web UI: http://localhost:3300. API: http://localhost:8300.

  5. First login. There's no login page: the web UI auto-opens a settings dialog asking for an API token the first time it can't find one. Paste the TIMOTHY_API_TOKEN value from deploy/.env. It's stored in your browser's localStorage.

  6. Add a provider. A fresh install has zero LLM providers and no routing configured, so Timothy can't answer anything until you do this. Go to Settings → Providers, pick a preset tile (OpenAI, Anthropic, Bedrock, GLM, Grok, Ollama, or a custom OpenAI-compatible endpoint), fill in the form, and run the connection test before adding it. The API key you enter is encrypted into the secret store (default backend db, encrypted with TIMOTHY_MASTER_KEY); the database only ever holds a reference to it, never the raw value, and it never appears in .env, logs, or API responses. Creating your first provider automatically bootstraps the 4 routes Timothy needs to work (default, summarize, embedding, vision); routes are otherwise fully user-managed (create, edit chain/strategy, delete) from Settings → Routing.

Optional: local models

Run Ollama natively on the host, not in a container: a containerized Ollama only gets CPU, while a host install can use Metal or CUDA. Then add a provider with the Ollama preset; it prefills the base URL http://host.docker.internal:11434/v1. On Linux, host.docker.internal may need a host-gateway entry in your Docker config to resolve.

Optional: Google connectors (Gmail, Calendar)

  1. Create an OAuth client in Google Cloud Console, type Web application.
  2. Set TIMOTHY_PUBLIC_URL in .env to the URL your browser uses to reach Timothy (e.g. http://localhost:3300). This must match what you register with Google, or the OAuth callback fails.
  3. Add <TIMOTHY_PUBLIC_URL>/v1/connectors/oauth/callback to the OAuth client's authorized redirect URIs.
  4. In the UI: Settings → Connectors, pick the Gmail or Calendar tile, paste the client ID and client secret, and complete the consent flow. Scopes requested: gmail.modify, calendar.

While the Google OAuth app is in "Testing" mode (the default for a new Cloud project), refresh tokens expire roughly every 7 days; when a connector stops working, reconnect it from Settings, or publish the OAuth app to avoid the expiry.

Optional: GitHub connector

Configured as an MCP preset in Settings → Connectors: paste a GitHub personal access token into the Bearer token field.

Optional: Amazon Bedrock

Create an IAM user scoped to bedrock:InvokeModel* only, generate an access key, and enter the access key ID and secret access key into their own fields on the Bedrock provider in Settings → Providers. Pick a region from the dropdown; no ~/.aws, no SSO, nothing to run on the host.

Operating the stack

make up      # start (builds images as needed)
make down    # stop
make logs    # follow logs for all services

Rebuild and restart a single service after a code change:

make brain      # or gateway, memoryd, web, markitdown, whisper, sandboxd

Backups

Postgres has no host port, so back it up through the container:

docker compose -f deploy/docker-compose.yml exec postgres pg_dump -U timothy timothy > backup.sql

A full backup is the pgdata volume plus deploy/.env: without TIMOTHY_MASTER_KEY, the encrypted secrets in that dump are unrecoverable.

Upgrading

git pull
make up

Migrations are additive-only, never edited once applied, and run automatically at service startup; no separate migrate step.

Local development

The Go toolchain runs fully containerized; no host Go install required.

make build   # compile everything
make test    # unit tests
make vet     # go vet
make lint    # golangci-lint

Frontend development with hot reload:

make dev   # Vite dev server on :3301, proxies /v1 to brain

make test-integration and make canary need the compose stack up (make up first).

Design decisions are documented as D-0XX markers in code comments next to the code they explain.

License

MIT

Reviews (0)

No results found