llmlinq 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. llmlinq-0.1.0/.claude/skills/local-app-monitor/SKILL.md +17 -0
  2. llmlinq-0.1.0/.github/workflows/ci.yml +40 -0
  3. llmlinq-0.1.0/.github/workflows/release.yml +51 -0
  4. llmlinq-0.1.0/.gitignore +34 -0
  5. llmlinq-0.1.0/.python-version +1 -0
  6. llmlinq-0.1.0/CHANGELOG.md +27 -0
  7. llmlinq-0.1.0/LICENSE +21 -0
  8. llmlinq-0.1.0/Makefile +42 -0
  9. llmlinq-0.1.0/PKG-INFO +183 -0
  10. llmlinq-0.1.0/README.md +155 -0
  11. llmlinq-0.1.0/frontend/index.html +14 -0
  12. llmlinq-0.1.0/frontend/package-lock.json +1418 -0
  13. llmlinq-0.1.0/frontend/package.json +29 -0
  14. llmlinq-0.1.0/frontend/public/favicon.svg +35 -0
  15. llmlinq-0.1.0/frontend/src/App.tsx +113 -0
  16. llmlinq-0.1.0/frontend/src/api/client.ts +116 -0
  17. llmlinq-0.1.0/frontend/src/api/types.ts +34 -0
  18. llmlinq-0.1.0/frontend/src/components/AppIcon.tsx +45 -0
  19. llmlinq-0.1.0/frontend/src/components/CloudSyncPanel.tsx +204 -0
  20. llmlinq-0.1.0/frontend/src/components/EmptyState.tsx +31 -0
  21. llmlinq-0.1.0/frontend/src/components/LiveBadge.tsx +15 -0
  22. llmlinq-0.1.0/frontend/src/components/PromptCard.tsx +108 -0
  23. llmlinq-0.1.0/frontend/src/components/ProviderTabs.tsx +51 -0
  24. llmlinq-0.1.0/frontend/src/components/RevisePanel.tsx +232 -0
  25. llmlinq-0.1.0/frontend/src/components/SearchBar.tsx +29 -0
  26. llmlinq-0.1.0/frontend/src/components/Timeline.tsx +77 -0
  27. llmlinq-0.1.0/frontend/src/hooks/usePrompts.ts +32 -0
  28. llmlinq-0.1.0/frontend/src/main.tsx +19 -0
  29. llmlinq-0.1.0/frontend/src/styles/index.css +1 -0
  30. llmlinq-0.1.0/frontend/tsconfig.json +21 -0
  31. llmlinq-0.1.0/frontend/vite.config.ts +19 -0
  32. llmlinq-0.1.0/pyproject.toml +80 -0
  33. llmlinq-0.1.0/skill/monitoring.md +146 -0
  34. llmlinq-0.1.0/src/llmlinq/__init__.py +8 -0
  35. llmlinq-0.1.0/src/llmlinq/__main__.py +6 -0
  36. llmlinq-0.1.0/src/llmlinq/api/__init__.py +1 -0
  37. llmlinq-0.1.0/src/llmlinq/api/routes.py +159 -0
  38. llmlinq-0.1.0/src/llmlinq/cli.py +82 -0
  39. llmlinq-0.1.0/src/llmlinq/core/__init__.py +1 -0
  40. llmlinq-0.1.0/src/llmlinq/core/cloud.py +165 -0
  41. llmlinq-0.1.0/src/llmlinq/core/config.py +23 -0
  42. llmlinq-0.1.0/src/llmlinq/core/events.py +42 -0
  43. llmlinq-0.1.0/src/llmlinq/core/models.py +95 -0
  44. llmlinq-0.1.0/src/llmlinq/core/paths.py +21 -0
  45. llmlinq-0.1.0/src/llmlinq/core/reviser.py +48 -0
  46. llmlinq-0.1.0/src/llmlinq/core/revisions.py +66 -0
  47. llmlinq-0.1.0/src/llmlinq/core/store.py +114 -0
  48. llmlinq-0.1.0/src/llmlinq/core/watcher.py +67 -0
  49. llmlinq-0.1.0/src/llmlinq/providers/__init__.py +34 -0
  50. llmlinq-0.1.0/src/llmlinq/providers/base.py +74 -0
  51. llmlinq-0.1.0/src/llmlinq/providers/claude.py +143 -0
  52. llmlinq-0.1.0/src/llmlinq/providers/codex.py +128 -0
  53. llmlinq-0.1.0/src/llmlinq/providers/gemini.py +106 -0
  54. llmlinq-0.1.0/src/llmlinq/server.py +140 -0
  55. llmlinq-0.1.0/src/llmlinq/web/static/assets/index-CJvy84g1.js +10 -0
  56. llmlinq-0.1.0/src/llmlinq/web/static/assets/index-Dba8tGzm.css +2 -0
  57. llmlinq-0.1.0/src/llmlinq/web/static/favicon.svg +35 -0
  58. llmlinq-0.1.0/src/llmlinq/web/static/index.html +15 -0
  59. llmlinq-0.1.0/tests/__init__.py +0 -0
  60. llmlinq-0.1.0/tests/conftest.py +213 -0
  61. llmlinq-0.1.0/tests/test_api.py +183 -0
  62. llmlinq-0.1.0/tests/test_cli.py +20 -0
  63. llmlinq-0.1.0/tests/test_cloud.py +201 -0
  64. llmlinq-0.1.0/tests/test_providers.py +93 -0
  65. llmlinq-0.1.0/tests/test_revisions.py +41 -0
  66. llmlinq-0.1.0/tests/test_store.py +92 -0
  67. llmlinq-0.1.0/tests/test_watcher.py +41 -0
  68. llmlinq-0.1.0/uv.lock +690 -0
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: local-app-monitor
3
+ description: Monitor the locally running llmlinq app — probe the API endpoints, scan logs, detect errors/problems, and file deduplicated bug issues in infoinlet-com/llmlinq-app. Use when asked to monitor the local app, check app health, or via /local-app-monitor. One invocation is one pass; combine with /loop for continuous monitoring.
4
+ ---
5
+
6
+ Execute one monitoring pass by following the complete procedure in
7
+ `skill/monitoring.md` at the repository root (read that file first — it
8
+ defines the checks, severity rules, log sources, issue dedupe/cap policy,
9
+ and the required summary format).
10
+
11
+ Hard rules, even if the procedure file is unavailable:
12
+ - Read-only checks only; never call paid endpoints (`/api/v1/revise`) unless
13
+ the user explicitly asked for a deep pass.
14
+ - App not running = report in chat, never a GitHub issue.
15
+ - Before creating any issue, search open issues for a matching
16
+ `[monitor] …` title; cap new issues at 3 per pass.
17
+ - Always end with a pass/warn/fail summary table in chat.
@@ -0,0 +1,40 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ backend:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.11", "3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v5
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ enable-cache: true
20
+ - run: uv sync --frozen
21
+ - run: uv run ruff check src tests
22
+ - run: uv run ruff format --check src tests
23
+ - run: uv run mypy src
24
+ - run: uv run pytest
25
+
26
+ frontend:
27
+ runs-on: ubuntu-latest
28
+ defaults:
29
+ run:
30
+ working-directory: frontend
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+ - uses: actions/setup-node@v4
34
+ with:
35
+ node-version: 22
36
+ cache: npm
37
+ cache-dependency-path: frontend/package-lock.json
38
+ - run: npm ci
39
+ - run: npm run typecheck
40
+ - run: npm run build
@@ -0,0 +1,51 @@
1
+ name: Release
2
+
3
+ # Tag-driven release: pushing a tag like v0.1.0 builds the UI, packs it into
4
+ # the wheel, and publishes to PyPI via trusted publishing (no API tokens).
5
+ #
6
+ # One-time setup: add a trusted publisher for the `llmlinq` project at
7
+ # https://pypi.org/manage/account/publishing/ with:
8
+ # owner: infoinlet-com · repo: llmlinq-app
9
+ # workflow: release.yml · environment: pypi
10
+
11
+ on:
12
+ push:
13
+ tags: ["v*"]
14
+
15
+ jobs:
16
+ build:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - uses: actions/setup-node@v4
21
+ with:
22
+ node-version: 22
23
+ cache: npm
24
+ cache-dependency-path: frontend/package-lock.json
25
+ - name: Build the web UI into the package
26
+ working-directory: frontend
27
+ run: |
28
+ npm ci
29
+ npm run build
30
+ - uses: astral-sh/setup-uv@v5
31
+ - name: Build sdist and wheel (UI bundled)
32
+ run: uv build
33
+ - name: Verify the wheel contains the UI
34
+ run: unzip -l dist/*.whl | grep -q "llmlinq/web/static/index.html"
35
+ - uses: actions/upload-artifact@v4
36
+ with:
37
+ name: dist
38
+ path: dist/
39
+
40
+ publish:
41
+ needs: build
42
+ runs-on: ubuntu-latest
43
+ environment: pypi
44
+ permissions:
45
+ id-token: write # trusted publishing
46
+ steps:
47
+ - uses: actions/download-artifact@v4
48
+ with:
49
+ name: dist
50
+ path: dist/
51
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,34 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .venv/
5
+ dist/
6
+ build/
7
+ *.egg-info/
8
+ .pytest_cache/
9
+ .mypy_cache/
10
+ .ruff_cache/
11
+ .coverage
12
+ htmlcov/
13
+
14
+ # Node
15
+ frontend/node_modules/
16
+ npm-debug.log*
17
+ *.tsbuildinfo
18
+
19
+ # Built frontend (generated by `make build-ui`, shipped inside the wheel)
20
+ src/aipromptdock/web/static/
21
+
22
+ # OS / editor
23
+ .DS_Store
24
+ .idea/
25
+ .vscode/
26
+
27
+ # Local AI-assistant artifacts and working notes (but ship shared skills)
28
+ .claude/*
29
+ !.claude/skills/
30
+ .context/
31
+
32
+ # Env
33
+ .env
34
+ .env.*
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-06-06
11
+
12
+ First release under the **LLMLinq** name. LLMLinq links prompts, contexts,
13
+ tools, validators, and LLMs — starting with everything previously published
14
+ as `aipromptdock` (0.1.0–0.2.4):
15
+
16
+ - Local timeline for Claude Code, Codex CLI, and Gemini CLI prompts —
17
+ day-grouped, searchable, live-updating at `http://127.0.0.1:8745`.
18
+ - AI prompt revision via the hosted LLMLinq API (`api.llmlinq.com`).
19
+ - Cloud sync: sign in and push your prompts (with revisions) to your account,
20
+ viewable on any device at `llmlinq.com`.
21
+ - Privacy: read-only access to CLI history, localhost-only, no telemetry.
22
+
23
+ ### Changed (vs aipromptdock 0.2.4)
24
+
25
+ - Renamed everywhere: install `llmlinq`, run `llmlinq`, data in `~/.llmlinq`
26
+ (migrated automatically from `~/.aipromptdock` on first run), env vars
27
+ `LLMLINQ_*` (old `AIPROMPTDOCK_*` honored as fallback for one cycle).
llmlinq-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 odyssey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
llmlinq-0.1.0/Makefile ADDED
@@ -0,0 +1,42 @@
1
+ .DEFAULT_GOAL := help
2
+ MAKEFLAGS += --no-print-directory
3
+
4
+ help: ## List available targets
5
+ @grep -E '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-12s\033[0m %s\n", $$1, $$2}'
6
+
7
+ install: ## Install backend (uv) + frontend (npm) dependencies
8
+ uv sync
9
+ cd frontend && npm install
10
+
11
+ dev: ## Run backend (:8745) + frontend (:5173) with hot reload
12
+ $(MAKE) -j2 dev-api dev-ui
13
+
14
+ dev-api: ## Run the FastAPI backend only (hot reload)
15
+ uv run uvicorn --factory llmlinq.server:create_app --reload --port 8745
16
+
17
+ dev-ui: ## Run the Vite dev server only
18
+ cd frontend && npm run dev
19
+
20
+ build-ui: ## Build the SPA into src/llmlinq/web/static/
21
+ cd frontend && npm run build
22
+
23
+ build: build-ui ## Build the distributable wheel (UI bundled inside)
24
+ uv build
25
+
26
+ test: ## Run the Python test suite
27
+ uv run pytest
28
+
29
+ lint: ## ruff + mypy + tsc
30
+ uv run ruff check src tests
31
+ uv run ruff format --check src tests
32
+ uv run mypy src
33
+ cd frontend && npm run typecheck
34
+
35
+ fmt: ## Auto-format Python code
36
+ uv run ruff check --fix src tests
37
+ uv run ruff format src tests
38
+
39
+ clean: ## Remove build artifacts and caches
40
+ rm -rf dist src/llmlinq/web/static .pytest_cache .mypy_cache .ruff_cache
41
+
42
+ .PHONY: help install dev dev-api dev-ui build-ui build test lint fmt clean
llmlinq-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,183 @@
1
+ Metadata-Version: 2.4
2
+ Name: llmlinq
3
+ Version: 0.1.0
4
+ Summary: A local-first timeline for every prompt you've sent to Claude Code, Codex CLI, and Gemini CLI.
5
+ Author-email: odyssey <odyssey.unheard@gmail.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: claude,cli,codex,gemini,history,localhost,prompt,timeline
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Web Environment
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development
18
+ Classifier: Topic :: Utilities
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: fastapi>=0.115
21
+ Requires-Dist: httpx2>=0.1
22
+ Requires-Dist: rich>=13
23
+ Requires-Dist: sse-starlette>=2.2
24
+ Requires-Dist: typer>=0.15
25
+ Requires-Dist: uvicorn>=0.32
26
+ Requires-Dist: watchdog>=6.0
27
+ Description-Content-Type: text/markdown
28
+
29
+ # <img src="frontend/public/favicon.svg" width="26" alt="LLMLinq icon"> LLMLinq
30
+
31
+ > A local-first timeline for every prompt you've ever sent to **Claude Code**,
32
+ > **Codex CLI**, and **Gemini CLI**.
33
+
34
+ LLMLinq reads the prompt history that the three major AI coding CLIs
35
+ already keep on your machine and presents it as a beautiful, searchable,
36
+ live-updating timeline at `http://127.0.0.1:8745`.
37
+
38
+ - 🗂 **Three tabs** — Claude · Codex · Gemini, with live prompt counts
39
+ - 🕰 **Timeline view** — day-grouped, newest first, with project context
40
+ - 🔍 **Search** — find any prompt you ever typed
41
+ - ⚡ **Live** — prompts appear in the timeline seconds after you type them
42
+ - 🔒 **Private by design** — read-only, binds to localhost, zero network egress, zero telemetry
43
+
44
+
45
+ ## Install
46
+
47
+ ```bash
48
+ uv tool install llmlinq # or: pipx install llmlinq / pip install llmlinq
49
+ llmlinq # scan → serve → open http://127.0.0.1:8745
50
+ ```
51
+
52
+ Or try it without installing anything:
53
+
54
+ ```bash
55
+ uvx llmlinq
56
+ ```
57
+
58
+ Only Python ≥ 3.11 is required — the web UI ships prebuilt inside the package.
59
+ The wheel can also be downloaded directly from the
60
+ [PyPI files page](https://pypi.org/project/llmlinq/#files).
61
+
62
+ > ⚠️ Running from a git clone (`uv run llmlinq`) shows a "UI not built"
63
+ > page — the UI is bundled into released packages, not the repository.
64
+ > Install from PyPI as above, or build the UI first (see Development).
65
+
66
+ Useful commands:
67
+
68
+ ```bash
69
+ llmlinq --port 9000 --no-browser # custom port, stay in the terminal
70
+ llmlinq paths # doctor: what was detected, where, how many prompts
71
+ ```
72
+
73
+ ## How it works
74
+
75
+ | Provider | Reads (read-only) |
76
+ |---|---|
77
+ | Claude Code | `~/.claude/history.jsonl` (or session transcripts as fallback) |
78
+ | Codex CLI | `~/.codex/history.jsonl` + per-session metadata for project names |
79
+ | Gemini CLI | `~/.gemini/tmp/<sha256(project)>/logs.json` |
80
+
81
+ Gemini never stores project paths — only a SHA-256 hash of them — so AI Prompt
82
+ Dock recovers project names by hashing paths it learned from Claude and Codex
83
+ data and matching them against Gemini's directory names.
84
+
85
+ A filesystem watcher picks up new prompts as you type them into any of the
86
+ three CLIs and pushes them to the timeline over Server-Sent Events.
87
+
88
+ Custom data locations are honored via `CLAUDE_CONFIG_DIR` and `CODEX_HOME`.
89
+
90
+ ## Project structure
91
+
92
+ ```
93
+ llmlinq-app/
94
+ ├── pyproject.toml # Package metadata, dependencies, tool config (ruff/mypy/pytest)
95
+ ├── uv.lock # Locked dependency versions (reproducible installs)
96
+ ├── Makefile # One-word workflows: make dev / test / lint / build
97
+ ├── .github/workflows/ci.yml # CI: lint + typecheck + tests (Python 3.11–3.13) + UI build
98
+ ├── src/
99
+ │ └── llmlinq/ # ── The Python package ──
100
+ │ ├── cli.py # Typer CLI entry point (`llmlinq` command)
101
+ │ ├── server.py # FastAPI app factory + production server runner
102
+ │ ├── api/ # HTTP API routes (Phase 2)
103
+ │ ├── core/ # Models, prompt store, file watcher (Phase 1)
104
+ │ ├── providers/ # Claude / Codex / Gemini history adapters (Phase 1)
105
+ │ └── web/static/ # Built SPA — generated by `make build-ui`, gitignored,
106
+ │ # shipped inside the wheel
107
+ ├── frontend/ # ── The React app ──
108
+ │ ├── vite.config.ts # Builds into src/llmlinq/web/static/; dev proxy → :8745
109
+ │ └── src/
110
+ │ ├── App.tsx # Root component
111
+ │ └── styles/index.css # Tailwind CSS v4 entry (sky theme)
112
+ └── tests/ # pytest suite (synthetic CLI-data fixtures in Phase 1)
113
+ ```
114
+
115
+ The one unusual thing worth knowing: **the frontend builds into the Python
116
+ package**. `vite build` outputs to `src/llmlinq/web/static/`, and the
117
+ wheel includes that directory (see `[tool.hatch.build]` in `pyproject.toml`).
118
+ That is why end users need only Python — never Node.
119
+
120
+ ## Local development
121
+
122
+ Prerequisites: [uv](https://docs.astral.sh/uv/) and Node.js ≥ 22.
123
+
124
+ ```bash
125
+ git clone <repo-url> && cd llmlinq-app
126
+ make install # uv sync (creates ./.venv + installs Python deps) + npm install
127
+ make dev # backend on :8745 + frontend on :5173, hot reload on both
128
+ ```
129
+
130
+ Open **http://localhost:5173** during development — the Vite dev server
131
+ proxies `/api` and `/healthz` to the FastAPI backend on `:8745`.
132
+
133
+ All Python tooling runs inside the project virtualenv at `./.venv`
134
+ (created by `uv sync`). Use `uv run <cmd>` — or activate it with
135
+ `source .venv/bin/activate` if you prefer.
136
+
137
+ Run the halves separately when needed:
138
+
139
+ ```bash
140
+ make dev-api # FastAPI only → uv run uvicorn --factory llmlinq.server:create_app --reload --port 8745
141
+ make dev-ui # Vite only → cd frontend && npm run dev
142
+ ```
143
+
144
+ To test the production setup (FastAPI serving the built SPA, as end users get it):
145
+
146
+ ```bash
147
+ make build-ui # build the SPA into the package
148
+ uv run llmlinq # serve everything from :8745
149
+ ```
150
+
151
+ Other useful targets:
152
+
153
+ ```bash
154
+ make test # pytest
155
+ make build # build the SPA, then the wheel (dist/llmlinq-*.whl, UI bundled)
156
+ make clean # remove build artifacts and caches
157
+ make help # list all targets
158
+ ```
159
+
160
+ ## Linting & formatting
161
+
162
+ ```bash
163
+ make lint # check everything (what CI runs)
164
+ make fmt # auto-fix + format Python code
165
+ ```
166
+
167
+ `make lint` runs, in order:
168
+
169
+ | Tool | Command | Checks |
170
+ |---|---|---|
171
+ | Ruff (lint) | `uv run ruff check src tests` | Python lint rules (`E,F,W,I,UP,B,SIM,C4,RUF`) |
172
+ | Ruff (format) | `uv run ruff format --check src tests` | Python formatting |
173
+ | mypy | `uv run mypy src` | Static types, `strict = true` |
174
+ | TypeScript | `cd frontend && npm run typecheck` | Frontend types (`tsc`, strict) |
175
+
176
+ Configuration lives in `pyproject.toml` (`[tool.ruff]`, `[tool.mypy]`) and
177
+ `frontend/tsconfig.json`. CI (`.github/workflows/ci.yml`) runs the same
178
+ checks plus the test suite on Python 3.11, 3.12, and 3.13 — run
179
+ `make lint test` before pushing and you should match CI exactly.
180
+
181
+ ## License
182
+
183
+ [MIT](LICENSE)
@@ -0,0 +1,155 @@
1
+ # <img src="frontend/public/favicon.svg" width="26" alt="LLMLinq icon"> LLMLinq
2
+
3
+ > A local-first timeline for every prompt you've ever sent to **Claude Code**,
4
+ > **Codex CLI**, and **Gemini CLI**.
5
+
6
+ LLMLinq reads the prompt history that the three major AI coding CLIs
7
+ already keep on your machine and presents it as a beautiful, searchable,
8
+ live-updating timeline at `http://127.0.0.1:8745`.
9
+
10
+ - 🗂 **Three tabs** — Claude · Codex · Gemini, with live prompt counts
11
+ - 🕰 **Timeline view** — day-grouped, newest first, with project context
12
+ - 🔍 **Search** — find any prompt you ever typed
13
+ - ⚡ **Live** — prompts appear in the timeline seconds after you type them
14
+ - 🔒 **Private by design** — read-only, binds to localhost, zero network egress, zero telemetry
15
+
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ uv tool install llmlinq # or: pipx install llmlinq / pip install llmlinq
21
+ llmlinq # scan → serve → open http://127.0.0.1:8745
22
+ ```
23
+
24
+ Or try it without installing anything:
25
+
26
+ ```bash
27
+ uvx llmlinq
28
+ ```
29
+
30
+ Only Python ≥ 3.11 is required — the web UI ships prebuilt inside the package.
31
+ The wheel can also be downloaded directly from the
32
+ [PyPI files page](https://pypi.org/project/llmlinq/#files).
33
+
34
+ > ⚠️ Running from a git clone (`uv run llmlinq`) shows a "UI not built"
35
+ > page — the UI is bundled into released packages, not the repository.
36
+ > Install from PyPI as above, or build the UI first (see Development).
37
+
38
+ Useful commands:
39
+
40
+ ```bash
41
+ llmlinq --port 9000 --no-browser # custom port, stay in the terminal
42
+ llmlinq paths # doctor: what was detected, where, how many prompts
43
+ ```
44
+
45
+ ## How it works
46
+
47
+ | Provider | Reads (read-only) |
48
+ |---|---|
49
+ | Claude Code | `~/.claude/history.jsonl` (or session transcripts as fallback) |
50
+ | Codex CLI | `~/.codex/history.jsonl` + per-session metadata for project names |
51
+ | Gemini CLI | `~/.gemini/tmp/<sha256(project)>/logs.json` |
52
+
53
+ Gemini never stores project paths — only a SHA-256 hash of them — so AI Prompt
54
+ Dock recovers project names by hashing paths it learned from Claude and Codex
55
+ data and matching them against Gemini's directory names.
56
+
57
+ A filesystem watcher picks up new prompts as you type them into any of the
58
+ three CLIs and pushes them to the timeline over Server-Sent Events.
59
+
60
+ Custom data locations are honored via `CLAUDE_CONFIG_DIR` and `CODEX_HOME`.
61
+
62
+ ## Project structure
63
+
64
+ ```
65
+ llmlinq-app/
66
+ ├── pyproject.toml # Package metadata, dependencies, tool config (ruff/mypy/pytest)
67
+ ├── uv.lock # Locked dependency versions (reproducible installs)
68
+ ├── Makefile # One-word workflows: make dev / test / lint / build
69
+ ├── .github/workflows/ci.yml # CI: lint + typecheck + tests (Python 3.11–3.13) + UI build
70
+ ├── src/
71
+ │ └── llmlinq/ # ── The Python package ──
72
+ │ ├── cli.py # Typer CLI entry point (`llmlinq` command)
73
+ │ ├── server.py # FastAPI app factory + production server runner
74
+ │ ├── api/ # HTTP API routes (Phase 2)
75
+ │ ├── core/ # Models, prompt store, file watcher (Phase 1)
76
+ │ ├── providers/ # Claude / Codex / Gemini history adapters (Phase 1)
77
+ │ └── web/static/ # Built SPA — generated by `make build-ui`, gitignored,
78
+ │ # shipped inside the wheel
79
+ ├── frontend/ # ── The React app ──
80
+ │ ├── vite.config.ts # Builds into src/llmlinq/web/static/; dev proxy → :8745
81
+ │ └── src/
82
+ │ ├── App.tsx # Root component
83
+ │ └── styles/index.css # Tailwind CSS v4 entry (sky theme)
84
+ └── tests/ # pytest suite (synthetic CLI-data fixtures in Phase 1)
85
+ ```
86
+
87
+ The one unusual thing worth knowing: **the frontend builds into the Python
88
+ package**. `vite build` outputs to `src/llmlinq/web/static/`, and the
89
+ wheel includes that directory (see `[tool.hatch.build]` in `pyproject.toml`).
90
+ That is why end users need only Python — never Node.
91
+
92
+ ## Local development
93
+
94
+ Prerequisites: [uv](https://docs.astral.sh/uv/) and Node.js ≥ 22.
95
+
96
+ ```bash
97
+ git clone <repo-url> && cd llmlinq-app
98
+ make install # uv sync (creates ./.venv + installs Python deps) + npm install
99
+ make dev # backend on :8745 + frontend on :5173, hot reload on both
100
+ ```
101
+
102
+ Open **http://localhost:5173** during development — the Vite dev server
103
+ proxies `/api` and `/healthz` to the FastAPI backend on `:8745`.
104
+
105
+ All Python tooling runs inside the project virtualenv at `./.venv`
106
+ (created by `uv sync`). Use `uv run <cmd>` — or activate it with
107
+ `source .venv/bin/activate` if you prefer.
108
+
109
+ Run the halves separately when needed:
110
+
111
+ ```bash
112
+ make dev-api # FastAPI only → uv run uvicorn --factory llmlinq.server:create_app --reload --port 8745
113
+ make dev-ui # Vite only → cd frontend && npm run dev
114
+ ```
115
+
116
+ To test the production setup (FastAPI serving the built SPA, as end users get it):
117
+
118
+ ```bash
119
+ make build-ui # build the SPA into the package
120
+ uv run llmlinq # serve everything from :8745
121
+ ```
122
+
123
+ Other useful targets:
124
+
125
+ ```bash
126
+ make test # pytest
127
+ make build # build the SPA, then the wheel (dist/llmlinq-*.whl, UI bundled)
128
+ make clean # remove build artifacts and caches
129
+ make help # list all targets
130
+ ```
131
+
132
+ ## Linting & formatting
133
+
134
+ ```bash
135
+ make lint # check everything (what CI runs)
136
+ make fmt # auto-fix + format Python code
137
+ ```
138
+
139
+ `make lint` runs, in order:
140
+
141
+ | Tool | Command | Checks |
142
+ |---|---|---|
143
+ | Ruff (lint) | `uv run ruff check src tests` | Python lint rules (`E,F,W,I,UP,B,SIM,C4,RUF`) |
144
+ | Ruff (format) | `uv run ruff format --check src tests` | Python formatting |
145
+ | mypy | `uv run mypy src` | Static types, `strict = true` |
146
+ | TypeScript | `cd frontend && npm run typecheck` | Frontend types (`tsc`, strict) |
147
+
148
+ Configuration lives in `pyproject.toml` (`[tool.ruff]`, `[tool.mypy]`) and
149
+ `frontend/tsconfig.json`. CI (`.github/workflows/ci.yml`) runs the same
150
+ checks plus the test suite on Python 3.11, 3.12, and 3.13 — run
151
+ `make lint test` before pushing and you should match CI exactly.
152
+
153
+ ## License
154
+
155
+ [MIT](LICENSE)
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta name="description" content="A local timeline for your Claude Code, Codex CLI, and Gemini CLI prompts." />
8
+ <title>LLMLinq</title>
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ <script type="module" src="/src/main.tsx"></script>
13
+ </body>
14
+ </html>