Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
python-version: ["3.11", "3.12", "3.13"]
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
# Pinned to immutable commit SHAs (not @v4 / @v5) so a compromised tag
# cannot silently swap the underlying action code on this CI runner.
Expand Down
10 changes: 8 additions & 2 deletions launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
directly in-process.
"""

import webview

from app import create_app


def main():
try:
import webview
except ImportError:
raise SystemExit(
"pywebview is not installed. Install the [desktop] extra, e.g.\n"
' pip install -e ".[desktop]"'
) from None

app = create_app()
webview.create_window(
"Cursor Chat Browser",
Expand Down
92 changes: 92 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
[build-system]
requires = ["hatchling>=1.21"]
build-backend = "hatchling.build"

[project]
name = "cppa-cursor-browser"
version = "0.1.0"
description = "Flask web application for browsing and exporting Cursor AI chat histories"
readme = "README.md"
license = { file = "LICENSE" }
authors = [{ name = "C++ Alliance", email = "admin@cppalliance.org" }]
requires-python = ">=3.10"

# Runtime dependencies — bounded on both sides so CI resolves deterministically
# and breaking major releases are caught at install time rather than at runtime.
# Upper bounds are conservative: pin to current known-compatible major version.
# See also: requirements.txt (backward-compat alias; pyproject.toml is canonical).
dependencies = [
"flask>=3.0,<4",
"fpdf2>=2.7,<3",
]
Comment thread
coderabbitai[bot] marked this conversation as resolved.

[project.optional-dependencies]
# Desktop launcher (pywebview pulls in heavy system libs — GTK/Qt on Linux —
# so it is intentionally excluded from the web-server and CI installs).
desktop = ["pywebview>=5.0,<6"]

# Development tooling: testing + type checking.
dev = [
"pytest>=8,<9",
"mypy>=1.10,<2",
]

[project.scripts]
# Primary CLI: export Cursor chat histories to Markdown / zip.
# Usage: cursor-chat-export [--since all|last] [--out DIR] [--no-zip] [--help]
cursor-chat-export = "scripts.export:main"

# Desktop launcher (requires the [desktop] extra to be installed).
cursor-chat-browser = "launcher:main"
Comment thread
bradjin8 marked this conversation as resolved.

[project.urls]
Repository = "https://github.com/cppalliance/cppa-cursor-browser"
Issues = "https://github.com/cppalliance/cppa-cursor-browser/issues"

# ── Build configuration ────────────────────────────────────────────────────────
# Flat layout (no src/ directory): enumerate every importable package and the
# two top-level application modules so the installed wheel has the same import
# surface as the repo checkout.
[tool.hatch.build.targets.wheel]
include = [
"api/",
"models/",
"scripts/",
"services/",
"utils/",
"templates/",
"static/",
"app.py",
"launcher.py",
]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
bradjin8 marked this conversation as resolved.

# sdist includes tests + ancillary files; wheel is runtime-only.
[tool.hatch.build.targets.sdist]
include = [
"api/",
"models/",
"scripts/",
"services/",
"utils/",
"tests/",
"templates/",
"static/",
"app.py",
"launcher.py",
"requirements.txt",
"README.md",
"LICENSE",
"cursor-browser.spec",
]

# ── Mypy ──────────────────────────────────────────────────────────────────────
# Mirrors the flags used in .github/workflows/tests.yml so local `mypy .`
# and CI produce identical results.
[tool.mypy]
ignore_missing_imports = true
no_strict_optional = true
pretty = true
# Exclude virtual-env and build artefact directories so that `mypy .` from the
# repo root matches CI behaviour (CI runs in a clean runner without a local venv).
# Anchored regexes — unanchored `venv/` would match any path segment containing "venv/".
exclude = ["^venv/", "^\\.venv/", "^build/", "^dist/"]
12 changes: 9 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
flask>=3.0
fpdf2>=2.7
pywebview>=5.0
# Backward-compatibility shim — mirrors [project.dependencies] in pyproject.toml.
# Keep version specifiers in sync when runtime deps change.
#
# Prefer: pip install -e . (installs the package + runtime deps)
# pip install -e ".[dev]" (+ pytest and mypy)
# pip install -e ".[desktop]" (+ pywebview for the GUI launcher)
flask>=3.0,<4
fpdf2>=2.7,<3
# pywebview is desktop-only — install with: pip install -e ".[desktop]"
Loading