Skip to main content

Per-topic AI chat interface for work follow-up, where each topic maps to a GitHub issue.

Project description

Precursor

Opinionated approach to work follow-up, built as an AI assistant.

Precursor is a small AI assistant, built with an opinionated approach to tracking work-in-progress conversations alongside the issues they belong to. Every chat is scoped to a topic that can be linked to (or create) a GitHub issue; the assistant uses the issue body, comments, and labels as live context so newer updates outweigh older ones.

Highlights

  • Collapsible, searchable, tree-organized topic sidebar
  • Each topic optionally linked to a GitHub issue; issue labels tag the chat
  • Multi-turn chat with SSE streaming and markdown rendering
  • Powered by GitHub Models (OpenAI-compatible) with a mock provider for offline development
  • MCP both ways: Precursor exposes its conversations as an MCP server and attaches external MCP tool servers per topic
  • Agents mode (opt-in): hand long-running tasks to an autonomous Copilot SDK agent attached to a topic/chat, followed in a workflow-style tab. Off by default — needs the agents extra and a toggle in Settings → Agents (see Optional: Agents mode)
  • Single uvicorn process in production — FastAPI serves the API and mounts the built React SPA
  • Plugin-ready: backend entry points + a frontend extension registry, designed for things like a future drawio preview/generator

Stack

Layer Tech
Tooling uv for env, run, build & release
Backend Python 3.12+, FastAPI, SQLAlchemy 2 (async), Alembic, sse-starlette
LLM openai SDK pointed at https://models.github.ai/inference
MCP mcp Python SDK (client + server scaffolding)
Frontend Vite + React 19 + TypeScript, Tailwind CSS 3, Lucide React
DB SQLite for dev (aiosqlite), PostgreSQL for prod (asyncpg, extra)

Quick start

Precursor uses uv for everything Python — environment, running, building, and releasing. Install it once (instructions), then:

uv sync                       # backend: .venv + Python deps (uv manages the interpreter)
npm --prefix frontend install # frontend: Vite + React toolchain (needs Node.js)
cp .env.example .env

[!NOTE] The dev server (precursor --dev) and the SPA build (make build) need Node.js + npm; the production runtime does not. make sync runs both install steps (uv sync + npm install) in one go.

GitHub credentials (optional). Precursor resolves a GitHub token in this order: (1) a token saved in Settings → GitHub, then (2) your GitHub CLI session (gh auth token) if you're signed in via gh auth login. So if you already use gh, you don't need to set anything. A token needs the models:read fine-grained permission (or Copilot access) for real model responses. With no token at all, Precursor falls back to the MockProvider so the chat flow stays usable offline.

Optional: Agents mode

Agents mode is opt-in and off by default. It is not installed by the uv sync above — it lives behind its own agents extra:

uv sync --extra agents               # adds github-copilot-sdk on top of the dev deps
uv run --extra agents precursor --dev # …or run the dev stack with it in one step (= make dev)

[!IMPORTANT] The github-copilot-sdk wheel bundles the native Copilot CLI runtime binary (~90 MB download, ~145 MB on disk), which is why it is kept out of the default install. Installing the extra is the only step that pulls that payload — there is no separate, smaller "download the runtime later" path for the published 1.0.x wheels.

Installing the extra only makes the runtime available. Agents stay disabled until you turn them on in Settings → Agents, where the UI also reports whether the runtime resolved on your platform.

Run it (one command)

uv run precursor --dev        # uvicorn --reload + Vite HMR (Ctrl-C stops both)
# or:  make dev

On startup Precursor prints a banner with the URL to open. --port is always the URL you open in your browser — in --dev the UI runs there and Vite proxies /api to the backend (which sits on a hidden port, by default --port + 1):

uv run precursor --dev --port 9000   # open :9000 (UI); API on :9001 behind it
uv run precursor --port 8100 --open  # prod-style, opens the browser when ready

Running several instances at once? Just pick a different --port per instance — or don't: a busy port automatically bumps to the next free one (pass --strict-port to fail instead, or --port 0 to grab any free port). The banner always tells you where the UI landed.

uv run resolves the project's environment on the fly — no manual activation. Other entry points:

uv run precursor                     # single process: API + pre-built SPA on one port
uv run precursor --dev --no-frontend # backend only (uvicorn --reload)
npm --prefix frontend run dev        # Vite only

Frontend prod build (served by FastAPI)

make build                    # npm --prefix frontend run build → frontend/dist
uv run precursor              # serves API + SPA on :8000

The single-process run needs the SPA pre-built; uv run precursor then serves it from frontend/dist. The SPA is also bundled inside the wheel, so an installed build is self-contained:

uvx precursor-ai              # run the latest published wheel, zero setup
# or pin it:  uv tool install precursor-ai && precursor-ai

Automatic upgrades on startup

When you pull new code or upgrade Precursor, both the frontend and database are automatically upgraded when the app starts — no manual build or migration steps needed:

  • Frontend: Built automatically if frontend/dist is missing or stale
  • Database: Migrations applied during app startup via Alembic

Just start Precursor and it handles the rest:

git pull
uv run precursor              # frontend built + DB migrated automatically

Project layout

precursor/
├── precursor/backend/
│   ├── main.py             # FastAPI app + SPA mount + lifespan
│   ├── config.py           # pydantic-settings
│   ├── db.py               # async SQLAlchemy engine + session
│   ├── models/             # Topic, Message, AppSetting
│   ├── schemas/            # Pydantic request/response models
│   ├── routers/            # topics, chat (SSE), settings, github, mcp
│   ├── services/
│   │   ├── llm/            # provider protocol + GH Models + mock
│   │   ├── github_client.py
│   │   └── mcp/            # server + client manager
│   ├── plugins/            # entry-point loader + registry
│   └── alembic/            # migrations
├── frontend/
│   ├── src/components/     # Sidebar, ChatPanel, SettingsPanel, MessageBubble
│   ├── src/lib/            # api, sse, plugins, theme, types
│   └── vite.config.ts      # built to frontend/dist → bundled into the wheel
├── pyproject.toml          # uv project: deps, build (hatch-vcs CalVer), tooling
├── uv.lock                 # uv-managed lockfile (committed)
├── Makefile                # uv-based dev/build shortcuts
└── alembic.ini

Design principles

  • Streaming-first chat with tool-call visualization
  • Single process in production — no Node.js runtime required
  • Each topic is an independent conversation context, hydrated from its linked GitHub issue (newer comments preferred over older)
  • Extensible by design: see docs/plugins.md for the plugin contract — third parties can mount routers, contribute frontend panels, and register MCP tools without forking the core

Security & deployment model

[!IMPORTANT] Precursor is designed as a single-user, local-first app and ships with no authentication. Run it bound to 127.0.0.1 (the default) and do not expose it to a network or the public internet without putting your own authenticating reverse proxy in front of it.

Specific things to keep local:

  • The API and SPA have no auth — anyone who can reach the port has full access to your topics, settings, and stored tokens.
  • The optional command-runner MCP tool can execute shell/Python/Node. Keep the Docker "jail" enabled; disabling it grants full local-disk access.
  • The built-in MCP-over-HTTP transport is off by default and only binds to loopback — leave it that way unless you front it with auth.
  • Secrets (the GitHub token, LLM provider keys) live in the local DB (set via Settings) and are never echoed by the API. Don't commit .env.

See SECURITY.md for vulnerability reporting.

Versioning & releases

Precursor uses CalVer (YYYY.M.MICRO, e.g. 2026.6.0). The version is a single source of truth derived from git tags by hatch-vcs at build time — there is no literal to edit. The running version is exposed at GET /api/version and shown in the Settings panel.

Releases ship from a pushed v<version> tag via GitHub Actions. See RELEASING.md and CHANGELOG.md.

Documentation

📖 Website & full documentation — feature guides, installation, configuration, architecture, and contribution docs, published from website/ on every push.

In-repo references:

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

precursor_ai-2026.7.0.tar.gz (5.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

precursor_ai-2026.7.0-py3-none-any.whl (1.7 MB view details)

Uploaded Python 3

File details

Details for the file precursor_ai-2026.7.0.tar.gz.

File metadata

  • Download URL: precursor_ai-2026.7.0.tar.gz
  • Upload date:
  • Size: 5.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for precursor_ai-2026.7.0.tar.gz
Algorithm Hash digest
SHA256 857ad6e82d613a3638e281520a41b03a7f1b0f5f300f4469ef5a624b3de0fbf9
MD5 5e1e6b62b7c526ae88e433b2ead58383
BLAKE2b-256 8c6c0ba7f0026979f2f527a39c7f2c0bddca4b5b958b19aea64d13ac744c2748

See more details on using hashes here.

Provenance

The following attestation bundles were made for precursor_ai-2026.7.0.tar.gz:

Publisher: release.yml on lrivallain/precursor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file precursor_ai-2026.7.0-py3-none-any.whl.

File metadata

File hashes

Hashes for precursor_ai-2026.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2815210a4c642fd1afc5eee0083c8d238ccc43b95b857ec8a63534ed91549c8a
MD5 6f3f189fda0906238dfc86b791fae6c2
BLAKE2b-256 d4276174bd44d24d5e0d984f55eef918804c82e0eb5be0a3297faedd514ba48c

See more details on using hashes here.

Provenance

The following attestation bundles were made for precursor_ai-2026.7.0-py3-none-any.whl:

Publisher: release.yml on lrivallain/precursor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page