leetvault 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 (41) hide show
  1. leetvault-0.1.0/.github/workflows/ci.yml +41 -0
  2. leetvault-0.1.0/.github/workflows/publish.yml +58 -0
  3. leetvault-0.1.0/.gitignore +17 -0
  4. leetvault-0.1.0/CHANGELOG.md +23 -0
  5. leetvault-0.1.0/CLAUDE.md +62 -0
  6. leetvault-0.1.0/CONTRIBUTING.md +45 -0
  7. leetvault-0.1.0/LICENSE +21 -0
  8. leetvault-0.1.0/PKG-INFO +120 -0
  9. leetvault-0.1.0/PLAN.md +307 -0
  10. leetvault-0.1.0/README.md +81 -0
  11. leetvault-0.1.0/docs/ARCHITECTURE.md +83 -0
  12. leetvault-0.1.0/docs/DEVELOPER.md +83 -0
  13. leetvault-0.1.0/docs/FAQ.md +50 -0
  14. leetvault-0.1.0/docs/TROUBLESHOOTING.md +71 -0
  15. leetvault-0.1.0/leetvault_kickoff.md +19 -0
  16. leetvault-0.1.0/pyproject.toml +78 -0
  17. leetvault-0.1.0/src/leetvault/__init__.py +3 -0
  18. leetvault-0.1.0/src/leetvault/auth.py +174 -0
  19. leetvault-0.1.0/src/leetvault/cli.py +99 -0
  20. leetvault-0.1.0/src/leetvault/client.py +352 -0
  21. leetvault-0.1.0/src/leetvault/config.py +122 -0
  22. leetvault-0.1.0/src/leetvault/db.py +67 -0
  23. leetvault-0.1.0/src/leetvault/git_writer.py +206 -0
  24. leetvault-0.1.0/src/leetvault/models.py +93 -0
  25. leetvault-0.1.0/src/leetvault/py.typed +0 -0
  26. leetvault-0.1.0/src/leetvault/readme.py +205 -0
  27. leetvault-0.1.0/src/leetvault/sync.py +390 -0
  28. leetvault-0.1.0/src/leetvault/templates/README.md.j2 +48 -0
  29. leetvault-0.1.0/src/leetvault/watch.py +104 -0
  30. leetvault-0.1.0/tests/__init__.py +0 -0
  31. leetvault-0.1.0/tests/conftest.py +44 -0
  32. leetvault-0.1.0/tests/test_auth.py +186 -0
  33. leetvault-0.1.0/tests/test_cli.py +23 -0
  34. leetvault-0.1.0/tests/test_client.py +206 -0
  35. leetvault-0.1.0/tests/test_config.py +51 -0
  36. leetvault-0.1.0/tests/test_db.py +43 -0
  37. leetvault-0.1.0/tests/test_git_writer.py +184 -0
  38. leetvault-0.1.0/tests/test_models.py +53 -0
  39. leetvault-0.1.0/tests/test_readme.py +147 -0
  40. leetvault-0.1.0/tests/test_sync.py +398 -0
  41. leetvault-0.1.0/tests/test_watch.py +107 -0
@@ -0,0 +1,41 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ test:
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, windows-latest, macos-latest]
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+ runs-on: ${{ matrix.os }}
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+ - name: Install
23
+ run: pip install -e ".[dev]"
24
+ - name: Test
25
+ run: pytest
26
+
27
+ lint:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+ - uses: actions/setup-python@v5
32
+ with:
33
+ python-version: "3.12"
34
+ - name: Install
35
+ run: pip install -e ".[dev]"
36
+ - name: Ruff check
37
+ run: ruff check .
38
+ - name: Ruff format check
39
+ run: ruff format --check .
40
+ - name: Mypy strict
41
+ run: mypy --strict
@@ -0,0 +1,58 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.12"
16
+ - name: Install build
17
+ run: pip install build
18
+ - name: Build sdist + wheel
19
+ run: python -m build
20
+ - uses: actions/upload-artifact@v4
21
+ with:
22
+ name: dist
23
+ path: dist/
24
+
25
+ # Dry-run: every tag push publishes to TestPyPI first. Real PyPI only follows if this
26
+ # succeeds, so a broken release never reaches real users.
27
+ publish-testpypi:
28
+ needs: build
29
+ runs-on: ubuntu-latest
30
+ environment:
31
+ name: testpypi
32
+ url: https://test.pypi.org/p/leetvault
33
+ permissions:
34
+ id-token: write
35
+ steps:
36
+ - uses: actions/download-artifact@v4
37
+ with:
38
+ name: dist
39
+ path: dist/
40
+ - uses: pypa/gh-action-pypi-publish@release/v1
41
+ with:
42
+ repository-url: https://test.pypi.org/legacy/
43
+ skip-existing: true
44
+
45
+ publish-pypi:
46
+ needs: publish-testpypi
47
+ runs-on: ubuntu-latest
48
+ environment:
49
+ name: pypi
50
+ url: https://pypi.org/p/leetvault
51
+ permissions:
52
+ id-token: write
53
+ steps:
54
+ - uses: actions/download-artifact@v4
55
+ with:
56
+ name: dist
57
+ path: dist/
58
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,17 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .eggs/
5
+ build/
6
+ dist/
7
+ .venv/
8
+ venv/
9
+ .pytest_cache/
10
+ .mypy_cache/
11
+ .ruff_cache/
12
+ .coverage
13
+ htmlcov/
14
+ *.db
15
+ *.sqlite3
16
+ .env
17
+ .claude/
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. Format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [0.1.0] - 2026-07-11
9
+
10
+ Initial release.
11
+
12
+ - `login`/`logout`/`status`: keyring-backed LeetCode session storage, live session validation,
13
+ JWT expiry decoding, optional GitHub PAT storage.
14
+ - `import`/`sync`: resumable full-history import and incremental sync of accepted submissions,
15
+ same-day dedup (`--keep-all` to disable), REST + GraphQL enrichment.
16
+ - Git layer: batched commit + transient-PAT push per run, never persisted to `.git/config`.
17
+ - Auto-generated README dashboard: progress, difficulty/language/topic breakdowns, streaks,
18
+ recent solves, full searchable solutions table.
19
+ - `watch`: polling loop with graceful shutdown and session-expiry warnings.
20
+ - `config`: get/set persistent settings.
21
+
22
+ [Unreleased]: https://github.com/priyadip/LeetVault/compare/v0.1.0...HEAD
23
+ [0.1.0]: https://github.com/priyadip/LeetVault/releases/tag/v0.1.0
@@ -0,0 +1,62 @@
1
+ # CLAUDE.md — leetvault
2
+
3
+ Project memory for Claude Code (auto-loaded each session). This file is authoritative. Keep the **Phase checklist** at the bottom updated as work completes.
4
+
5
+ ## What this is
6
+ `leetvault` — a cross-platform (Windows/Linux/macOS) Python CLI that mirrors *my* LeetCode account (accepted submissions + source code + metadata) into a normalized SQLite DB and a GitHub repo with an auto-generated README dashboard. Sync is **account-based** via my authenticated session — never browser-dependent. My LeetCode account is the single source of truth. Free/OSS only; the only external services are LeetCode and GitHub.
7
+
8
+ ## v1 scope
9
+ Commands: `login`, `import` (full history), `sync` (incremental), `watch` (polling), `status`, `logout`, `config`. Plus SQLite persistence, GitHub commit/push, auto-generated README, PyPI packaging + CI.
10
+ **NOT in v1** (leave `# FUTURE:` notes only, build nothing): browser extension, AI/weak-topic dashboard, standalone binaries, deep contest analytics.
11
+
12
+ ## Ground-truth API facts — do NOT re-derive; verify exact field shapes live in Phase 2
13
+ LeetCode has no official API — every endpoint is reverse-engineered. Isolate all LeetCode access behind one client module.
14
+
15
+ **Auth**
16
+ - Cookies `LEETCODE_SESSION` (a JWT) + `csrftoken`; I paste them at `login`. No password flow.
17
+ - Every authed request sends: both cookies + header `x-csrftoken: <csrftoken>` + `Referer: https://leetcode.com`.
18
+ - Decode the JWT `exp` for `status` + expiry warnings; don't hardcode a lifetime (varies ~1 wk to several wks).
19
+ - Store secrets (both cookies + GitHub PAT) via **`keyring`**, service name `leetvault`. Never in `.env`, `.git/config`, logs, or commits.
20
+
21
+ **Fetching**
22
+ - Full history → REST `https://leetcode.com/api/submissions/?offset=0&limit=20` (20/page; includes `code`, `id`, `question_id`, `title`, `title_slug`, `status_display`, `lang`, `runtime`, `memory`, `timestamp`, `url`; top-level `has_next`/`last_key`). Prefer for bulk — code + metadata in one pass.
23
+ - Enrichment/fallback → GraphQL `https://leetcode.com/graphql`: `submissionList(offset,limit,questionSlug)` + `submissionDetails(submissionId)` (code, runtimePercentile, memoryPercentile). One extra call per submission — use only when REST `code` is missing or percentiles are needed.
24
+ - Incremental/watch → `recentAcSubmissions` / `recentSubmissionList` (capped at 20; detection only, useless for history).
25
+
26
+ **Rate limits (empirical, not published — design defensively)**
27
+ - ~480 sequential requests → HTTP 403. Stay under 20 req / 10 s.
28
+ - Bulk import: 300–500 ms between pages; exponential backoff 1→3→9→27 s on 403/429; honor `Retry-After`.
29
+ - **Import MUST be resumable** — persist last offset / submission id after every page.
30
+ - GitHub write API has a **separate** quota — batch/space commits; never one push per submission.
31
+ - `--site com|cn` (default `com`); for `cn` swap base URL + stricter limiter (~1 req/10 s).
32
+
33
+ **Honest limits (state in docs, never fake)**
34
+ - `watch` = polling (60–120 s), not real-time (no LeetCode webhook/streaming exists).
35
+ - Cloudflare may challenge HTTP clients — fail gracefully; `# FUTURE:` optional Playwright real-browser fetcher.
36
+ - Stored-cookie automation may breach LeetCode ToS — neutral README disclaimer.
37
+
38
+ ## Stack (exact)
39
+ Typer (+`rich`) · `httpx` + **`httpx-retries`** (NOT `httpx-retry`) + custom rate limiter · SQLAlchemy 2.0 declarative (`DeclarativeBase`/`Mapped`/`mapped_column`/`select`) on SQLite · Jinja2 (`PackageLoader`) · GitPython (PAT injected transiently at push time, never in remote URL / `.git/config`; fine-grained PAT scoped to one repo, Contents: write) · `keyring` · `pytest`+cov / `ruff` / `mypy --strict` · **hatchling** + `src/` layout + entry point `leetvault = "leetvault.cli:app"` · **PyPI Trusted Publishing (OIDC)**. All config in `pyproject.toml`.
40
+
41
+ ## Data model (SQLite)
42
+ `problems`(question_id PK, frontend_id, title, title_slug, difficulty, paid_only, url) · `submissions`(submission_id PK, question_id FK, lang, status, runtime, memory, runtime_percentile, memory_percentile, timestamp, code_hash, is_accepted) · `submission_code`(submission_id PK/FK, code) · `topics` + `problem_topics` (M2M) · `sync_state`(id, site, last_offset, last_submission_id, last_synced_timestamp, last_full_import_completed_at).
43
+ History: store every accepted submission. Disk layout per problem: `Problems/<slug>/{latest.<ext>, history/submission_<id>.<ext>, notes.md, metadata.json}`. Default dedup = same problem within same day (86400 s); `--keep-all` opts out.
44
+
45
+ ## Working protocol
46
+ - **Run continuously.** Execute Phases 0 → 7 end-to-end without pausing for my approval between phases. Never ask "should I proceed / continue / go ahead?" — just proceed. Don't stop per-file.
47
+ - Per phase, loop: state what/why in 1–2 lines → build (full type hints, DI, SOLID, clean architecture) → tests green → `ruff check` + `ruff format --check` + `mypy --strict` clean → Conventional Commit → one-line progress note → immediately start the next phase.
48
+ - **Only stop to ask me when you need something ONLY I can provide.** In v1 that is exactly two moments: (1) **Phase 2** — my `LEETCODE_SESSION` + `csrftoken` (I paste them into the `login` flow); (2) **Phase 4** — a fine-grained GitHub PAT + target repo URL (for push). Ask once at each, then continue autonomously. Also stop before any irreversible action *outside this repo* (force-push, history rewrite, deleting files you didn't create).
49
+ - **Decide, don't ask, for everything else.** For small choices (naming, layout, library minutiae, config defaults) pick the sensible option, record it in `PLAN.md`, and keep moving. Surface a decision only if it's a true one-way door.
50
+ - **Verify, don't assume:** confirm real REST + `submissionDetails` fields live in Phase 2 before locking schema; adapt to reality; note any divergence in `PLAN.md`.
51
+ - **Never fake functionality** — no stubbed "pretend it worked," no fabricated data, no swallowed errors. If genuinely blocked, say so and propose a real fallback rather than faking or silently skipping.
52
+ - Commit after every phase so all work is recoverable via git. Never print or commit secrets. Keep `PLAN.md` + `docs/ARCHITECTURE.md` current as you go.
53
+
54
+ ## Phase checklist (update as completed)
55
+ - [x] **0 Scaffold** — `src/` layout, `pyproject.toml` (hatchling + deps + entry + ruff/mypy/pytest), command stubs, CI skeleton, `PLAN.md`, `docs/`. ✔ `pip install -e .` + `leetvault --help` lists all commands.
56
+ - [x] **1 Data layer** — models, engine/session factory, `create_all`, `SyncState` helpers, unit tests + temp-DB round-trip.
57
+ - [x] **2 Auth + client** — keyring store, httpx client (headers/timeouts/retries/limiter), JWT `exp`, session validation; `login`/`logout`/`status`. Verify live API. ✔ real-account `status` reports validity/expiry.
58
+ - [x] **3 Sync engine** — `import` (resumable, throttled, backoff) + `sync` (incremental, stop at last-known id); dedup; DB + `submission_code` + disk files; progress bars; mocked tests + opt-in live smoke. ✔ full import correct + re-run does no redundant work.
59
+ - [x] **4 Git** — layout writer, commit-template rendering, transient-PAT batched push. ✔ real push with correct messages, no dupes on re-run.
60
+ - [x] **5 README** — Jinja2 templates + stats aggregation (progress, difficulty, topics, langs, streaks, recent, searchable table w/ links, % bars), regenerate-after-sync, aggregation-math tests.
61
+ - [x] **6 Watch** — polling loop (`--interval`, 60–120 s), reconcile `SyncState`, run sync→write→README→commit→push on new AC, graceful shutdown, expiry warning. ✔ picks up a fresh solve within one interval.
62
+ - [x] **7 Packaging/CI/docs** — finalize `pyproject.toml`; Actions (pytest matrix ubuntu/windows/macos × py3.11–3.13, `fail-fast:false`; ruff + `mypy --strict` on ubuntu; tag-triggered Trusted Publishing `id-token: write`, TestPyPI dry-run first); README + Install + Architecture + Developer + Contribution + FAQ + Troubleshooting. Workflows built and locally verified (wheel build + install, YAML validity, pytest/ruff/mypy all clean); **not yet run on GitHub's own runners** — this local repo has no GitHub remote configured for leetvault's own source (only for the separate solutions-mirror repo used in the Phase 4 live test), and PyPI Trusted Publisher setup is an account-level action only the repo owner can do. See PLAN.md Phase 7 for the exact gap and what's needed to close it.
@@ -0,0 +1,45 @@
1
+ # Contributing
2
+
3
+ Thanks for considering a contribution to leetvault.
4
+
5
+ ## Before you start
6
+
7
+ - For anything beyond a small fix, open an issue first to discuss the approach - especially
8
+ for anything touching `client.py` (LeetCode's API is entirely reverse-engineered; changes
9
+ there need live verification, see [docs/DEVELOPER.md](docs/DEVELOPER.md)).
10
+ - This project is free/open-source and intentionally scoped to LeetCode + GitHub as its only
11
+ external services. PRs adding new third-party services are unlikely to be accepted.
12
+
13
+ ## Workflow
14
+
15
+ 1. Fork and branch from `main`.
16
+ 2. Install dev dependencies: `pip install -e ".[dev]"`.
17
+ 3. Make your change. Match the existing style: full type hints, no comments unless they
18
+ explain a non-obvious *why*, no speculative abstraction.
19
+ 4. Before opening a PR, all of these must be clean:
20
+ ```bash
21
+ pytest
22
+ ruff check .
23
+ ruff format --check .
24
+ mypy --strict
25
+ ```
26
+ 5. Write a [Conventional Commit](https://www.conventionalcommits.org/) message
27
+ (`feat: ...`, `fix: ...`, `docs: ...`, etc.).
28
+ 6. Open a PR against `main`. CI runs the full matrix (Ubuntu/Windows/macOS × Python 3.11-3.13)
29
+ plus lint/type-check on every PR.
30
+
31
+ ## Reporting bugs
32
+
33
+ Open a GitHub issue with:
34
+
35
+ - your OS and Python version
36
+ - the command you ran and its full output (`leetvault --help` output plus the failing command)
37
+ - **never include your `LEETCODE_SESSION`, `csrftoken`, or GitHub PAT** in an issue - those are
38
+ credentials, not debug info
39
+
40
+ ## Security
41
+
42
+ leetvault stores your LeetCode session cookies and GitHub PAT via the OS keyring, never in
43
+ plaintext files, `.env`, `.git/config`, logs, or commits. If you find a way those could leak,
44
+ please report it privately rather than opening a public issue - see
45
+ [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) for how credentials are handled.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 leetvault contributors
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.
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: leetvault
3
+ Version: 0.1.0
4
+ Summary: Mirror your LeetCode account (accepted submissions + source + metadata) into a normalized SQLite DB and a GitHub repo with an auto-generated README dashboard.
5
+ Project-URL: Homepage, https://github.com/priyadip/LeetVault
6
+ Project-URL: Repository, https://github.com/priyadip/LeetVault
7
+ Project-URL: Issues, https://github.com/priyadip/LeetVault/issues
8
+ Project-URL: Changelog, https://github.com/priyadip/LeetVault/blob/main/CHANGELOG.md
9
+ Author: leetvault
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: backup,cli,github,leetcode,sqlite,sync
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Version Control :: Git
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: gitpython>=3.1
23
+ Requires-Dist: httpx-retries>=0.2
24
+ Requires-Dist: httpx>=0.27
25
+ Requires-Dist: jinja2>=3.1
26
+ Requires-Dist: keyring>=25.0
27
+ Requires-Dist: pyjwt>=2.8
28
+ Requires-Dist: rich>=13.7
29
+ Requires-Dist: sqlalchemy>=2.0
30
+ Requires-Dist: typer>=0.12
31
+ Provides-Extra: dev
32
+ Requires-Dist: mypy>=1.11; extra == 'dev'
33
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
34
+ Requires-Dist: pytest-mock>=3.14; extra == 'dev'
35
+ Requires-Dist: pytest>=8.0; extra == 'dev'
36
+ Requires-Dist: respx>=0.21; extra == 'dev'
37
+ Requires-Dist: ruff>=0.6; extra == 'dev'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # leetvault
41
+
42
+ Mirror your LeetCode account (accepted submissions + source code + metadata) into a normalized
43
+ SQLite database and a GitHub repository with an auto-generated README dashboard.
44
+
45
+ Sync is **account-based**, driven by your authenticated LeetCode session — not a browser
46
+ extension. Your LeetCode account is the single source of truth. Free and open source; the only
47
+ external services involved are LeetCode and GitHub.
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ pip install leetvault
53
+ ```
54
+
55
+ Requires Python 3.11+. See [docs/DEVELOPER.md](docs/DEVELOPER.md) for an editable/dev install.
56
+
57
+ ## Quickstart
58
+
59
+ ```bash
60
+ leetvault login # paste LEETCODE_SESSION + csrftoken
61
+ leetvault config repo_url https://github.com/you/repo.git # optional: enable GitHub push
62
+ leetvault import # one-time full history
63
+ leetvault sync # incremental, run anytime
64
+ leetvault watch # or: poll automatically
65
+ ```
66
+
67
+ ## Commands
68
+
69
+ - `leetvault login` — store your `LEETCODE_SESSION` + `csrftoken` (and optionally a GitHub PAT)
70
+ in the OS keyring.
71
+ - `leetvault import` — full history import of every accepted submission (resumable, one-time
72
+ per site).
73
+ - `leetvault sync` — incremental sync of new accepted submissions since the last run.
74
+ - `leetvault watch` — poll LeetCode and sync automatically (`--interval`, default 90s).
75
+ - `leetvault status` — show session validity/expiry and sync state.
76
+ - `leetvault logout` — remove stored credentials.
77
+ - `leetvault config` — get/set persistent configuration (repo URL, DB path, dedup window, ...).
78
+
79
+ ## What gets stored
80
+
81
+ A normalized SQLite database (problems, submissions, source code, topics, sync state) plus a
82
+ disk layout per problem:
83
+
84
+ ```
85
+ Problems/<slug>/
86
+ latest.<ext> the most recent accepted submission
87
+ history/submission_<id>.<ext> every kept accepted submission
88
+ metadata.json difficulty, topics, runtime/memory percentiles, ...
89
+ notes.md yours - never overwritten once created
90
+ README.md auto-generated dashboard: progress, streaks, full solutions table
91
+ ```
92
+
93
+ By default, same-day accepted submissions for the same problem are deduplicated (only the
94
+ newest is kept); pass `--keep-all` to `import`/`sync` to disable that.
95
+
96
+ ## Honest limits
97
+
98
+ - `watch` is polling (default 90s, configurable), not a real-time push — LeetCode has no public
99
+ webhook/streaming API.
100
+ - LeetCode may Cloudflare-challenge automated HTTP clients; leetvault fails gracefully rather
101
+ than faking success.
102
+ - Storing session cookies for automated access may be against LeetCode's Terms of Service. Use
103
+ at your own risk, against your own account only.
104
+ - LeetCode has no official API — every endpoint leetvault uses is reverse-engineered and could
105
+ change without notice.
106
+
107
+ ## Docs
108
+
109
+ - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — data flow, module responsibilities, and every
110
+ place live API behavior diverged from initial assumptions.
111
+ - [docs/DEVELOPER.md](docs/DEVELOPER.md) — dev setup, project layout, running checks.
112
+ - [docs/FAQ.md](docs/FAQ.md)
113
+ - [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md)
114
+ - [CONTRIBUTING.md](CONTRIBUTING.md)
115
+ - [CHANGELOG.md](CHANGELOG.md)
116
+ - [PLAN.md](PLAN.md) — the running decision log from this project's initial build.
117
+
118
+ ## License
119
+
120
+ MIT — see [LICENSE](LICENSE).