better-dontforget 1.0.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.
- better_dontforget-1.0.0/.github/workflows/ci.yml +29 -0
- better_dontforget-1.0.0/.github/workflows/publish.yml +83 -0
- better_dontforget-1.0.0/.gitignore +20 -0
- better_dontforget-1.0.0/.python-version +1 -0
- better_dontforget-1.0.0/AGENTS.md +92 -0
- better_dontforget-1.0.0/Justfile +43 -0
- better_dontforget-1.0.0/PKG-INFO +103 -0
- better_dontforget-1.0.0/PRD.md +234 -0
- better_dontforget-1.0.0/README.md +90 -0
- better_dontforget-1.0.0/ROADMAP.md +84 -0
- better_dontforget-1.0.0/better_dontforget/__init__.py +3 -0
- better_dontforget-1.0.0/better_dontforget/__main__.py +8 -0
- better_dontforget-1.0.0/better_dontforget/cli.py +392 -0
- better_dontforget-1.0.0/better_dontforget/cli_helpers.py +17 -0
- better_dontforget-1.0.0/better_dontforget/core/__init__.py +7 -0
- better_dontforget-1.0.0/better_dontforget/core/ai.py +78 -0
- better_dontforget-1.0.0/better_dontforget/core/app.py +90 -0
- better_dontforget-1.0.0/better_dontforget/core/config.py +132 -0
- better_dontforget-1.0.0/better_dontforget/core/crypto.py +56 -0
- better_dontforget-1.0.0/better_dontforget/core/db.py +284 -0
- better_dontforget-1.0.0/better_dontforget/core/models.py +33 -0
- better_dontforget-1.0.0/better_dontforget/core/notifications.py +56 -0
- better_dontforget-1.0.0/better_dontforget/core/paths.py +43 -0
- better_dontforget-1.0.0/better_dontforget/core/providers.py +235 -0
- better_dontforget-1.0.0/better_dontforget/core/reminder_parser.py +194 -0
- better_dontforget-1.0.0/better_dontforget/core/reminders.py +46 -0
- better_dontforget-1.0.0/better_dontforget/tui/app.py +327 -0
- better_dontforget-1.0.0/docs/config.md +135 -0
- better_dontforget-1.0.0/docs/docs.md +237 -0
- better_dontforget-1.0.0/legacy/main.py +269 -0
- better_dontforget-1.0.0/legacy/mem-cli +96 -0
- better_dontforget-1.0.0/packaging/better-dontforget-notify.service +12 -0
- better_dontforget-1.0.0/packaging/better-dontforget-notify.timer +10 -0
- better_dontforget-1.0.0/pyproject.toml +51 -0
- better_dontforget-1.0.0/tests/conftest.py +123 -0
- better_dontforget-1.0.0/tests/test_ai.py +80 -0
- better_dontforget-1.0.0/tests/test_cli.py +78 -0
- better_dontforget-1.0.0/tests/test_config.py +62 -0
- better_dontforget-1.0.0/tests/test_crypto.py +27 -0
- better_dontforget-1.0.0/tests/test_db.py +88 -0
- better_dontforget-1.0.0/tests/test_models.py +56 -0
- better_dontforget-1.0.0/tests/test_providers.py +68 -0
- better_dontforget-1.0.0/tests/test_reminder_parser.py +74 -0
- better_dontforget-1.0.0/tests/test_reminders.py +63 -0
- better_dontforget-1.0.0/uv.lock +1161 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
check:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v5
|
|
16
|
+
with:
|
|
17
|
+
enable-cache: true
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
run: uv python install
|
|
21
|
+
|
|
22
|
+
- name: Install just
|
|
23
|
+
uses: extractions/setup-just@v2
|
|
24
|
+
|
|
25
|
+
- name: Sync dependencies
|
|
26
|
+
run: uv sync
|
|
27
|
+
|
|
28
|
+
- name: Run quality gate (just check)
|
|
29
|
+
run: just check
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Publish to PyPI. Supports a TestPyPI dry run via manual dispatch.
|
|
2
|
+
# Uses PyPI Trusted Publishing (OIDC) — no token secret required.
|
|
3
|
+
# One-time setup in PyPI: Account settings -> Publishing -> add pending publisher
|
|
4
|
+
# (project: better-dontforget, owner: vaproh, repo: dontforget,
|
|
5
|
+
# workflow: publish.yml, environment: pypi).
|
|
6
|
+
# For TestPyPI: register an equivalent publisher on test.pypi.org with environment "testpypi".
|
|
7
|
+
|
|
8
|
+
name: Publish to PyPI
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
release:
|
|
12
|
+
types: [published]
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
inputs:
|
|
15
|
+
target:
|
|
16
|
+
description: "Publish target"
|
|
17
|
+
required: true
|
|
18
|
+
default: "pypi"
|
|
19
|
+
type: choice
|
|
20
|
+
options:
|
|
21
|
+
- pypi
|
|
22
|
+
- testpypi
|
|
23
|
+
|
|
24
|
+
permissions:
|
|
25
|
+
# Required for PyPI trusted publishing (OIDC).
|
|
26
|
+
id-token: write
|
|
27
|
+
contents: read
|
|
28
|
+
|
|
29
|
+
jobs:
|
|
30
|
+
build:
|
|
31
|
+
name: Build distributions
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Install uv
|
|
37
|
+
uses: astral-sh/setup-uv@v5
|
|
38
|
+
with:
|
|
39
|
+
enable-cache: true
|
|
40
|
+
|
|
41
|
+
- name: Set up Python
|
|
42
|
+
run: uv python install
|
|
43
|
+
|
|
44
|
+
- name: Build distributions
|
|
45
|
+
run: uv build
|
|
46
|
+
|
|
47
|
+
- name: Upload distributions
|
|
48
|
+
uses: actions/upload-artifact@v4
|
|
49
|
+
with:
|
|
50
|
+
name: dist
|
|
51
|
+
path: dist/*
|
|
52
|
+
|
|
53
|
+
publish-pypi:
|
|
54
|
+
name: Publish to PyPI
|
|
55
|
+
if: github.event_name == 'release' || inputs.target == 'pypi'
|
|
56
|
+
needs: build
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
environment: pypi
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/download-artifact@v4
|
|
61
|
+
with:
|
|
62
|
+
name: dist
|
|
63
|
+
path: dist
|
|
64
|
+
|
|
65
|
+
- name: Publish to PyPI (trusted publishing)
|
|
66
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
67
|
+
|
|
68
|
+
publish-testpypi:
|
|
69
|
+
name: Publish to TestPyPI (dry run)
|
|
70
|
+
if: github.event_name == 'workflow_dispatch' && inputs.target == 'testpypi'
|
|
71
|
+
needs: build
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
environment: testpypi
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/download-artifact@v4
|
|
76
|
+
with:
|
|
77
|
+
name: dist
|
|
78
|
+
path: dist
|
|
79
|
+
|
|
80
|
+
- name: Publish to TestPyPI (trusted publishing)
|
|
81
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
82
|
+
with:
|
|
83
|
+
repository-url: https://test.pypi.org/legacy/
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
.idea/
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv
|
|
12
|
+
.env
|
|
13
|
+
app.log
|
|
14
|
+
agents.db
|
|
15
|
+
aisys_cli.egg-info
|
|
16
|
+
service_account.json
|
|
17
|
+
key.json
|
|
18
|
+
dontforget.db
|
|
19
|
+
memory.db
|
|
20
|
+
*.db
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# AGENTS.md — Engineering Operating Manual
|
|
2
|
+
|
|
3
|
+
This file is the operating manual for autonomous coding agents working on
|
|
4
|
+
**Better Dontforget** (`better-dontforget`). Follow it precisely.
|
|
5
|
+
|
|
6
|
+
## Read first
|
|
7
|
+
|
|
8
|
+
Before editing anything, read in order:
|
|
9
|
+
|
|
10
|
+
1. `PRD.md` — product requirements and scope (source of truth for *what*).
|
|
11
|
+
2. `ROADMAP.md` — implementation progress and dependency order.
|
|
12
|
+
3. `docs/docs.md` and `docs/config.md` — documented user behavior.
|
|
13
|
+
4. The relevant source under `better_dontforget/` — inspect before changing.
|
|
14
|
+
|
|
15
|
+
## Golden rules
|
|
16
|
+
|
|
17
|
+
* Preserve upstream behavior unless intentionally changing it (document why).
|
|
18
|
+
* Prefer the smallest coherent change: **extend → refactor → replace (justified)**.
|
|
19
|
+
* Avoid speculative abstractions and unnecessary dependencies.
|
|
20
|
+
* Keep reminders **optional** and encryption **optional + explicit**.
|
|
21
|
+
* Respect XDG conventions; never dump files into `$HOME` directly.
|
|
22
|
+
* Never turn the project into a calendar, task manager, or full notes app.
|
|
23
|
+
* Never silently expand scope beyond `PRD.md`.
|
|
24
|
+
|
|
25
|
+
## Workflow
|
|
26
|
+
|
|
27
|
+
1. Inspect relevant code before editing.
|
|
28
|
+
2. Implement the smallest coherent solution for the milestone in `ROADMAP.md`.
|
|
29
|
+
3. Add/update tests for behavioral changes.
|
|
30
|
+
4. Update affected docs alongside behavior changes.
|
|
31
|
+
5. Run focused tests during development.
|
|
32
|
+
6. Before declaring done: run the canonical quality gate.
|
|
33
|
+
|
|
34
|
+
## Quality gate
|
|
35
|
+
|
|
36
|
+
The single canonical full-project verification command is:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
just check
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`just check` runs formatting verification, linting, static analysis, the test
|
|
43
|
+
suite, and build verification. Never claim completion while `just check` fails.
|
|
44
|
+
|
|
45
|
+
## Testing discipline
|
|
46
|
+
|
|
47
|
+
* Tests must not require real API keys, paid services, network, or a graphical
|
|
48
|
+
desktop notification server.
|
|
49
|
+
* Mock external AI providers (inject a fake `AIProvider`).
|
|
50
|
+
* Mock/abstract the notifier (`Notifier`) for notification tests.
|
|
51
|
+
* Use temp XDG dirs and temp DB files in tests.
|
|
52
|
+
* Do not overmock pure internal logic into meaningless tests.
|
|
53
|
+
* Cover: capture, provider selection, provider failure, malformed responses,
|
|
54
|
+
config persistence, XDG env + fallback, reminder persistence, due/overdue
|
|
55
|
+
detection, duplicate prevention, notification success/failure state,
|
|
56
|
+
encryption round-trip, wrong-passphrase, CLI behavior, migration.
|
|
57
|
+
|
|
58
|
+
## Reliability invariants (must hold)
|
|
59
|
+
|
|
60
|
+
1. A quick note is never silently lost.
|
|
61
|
+
2. AI failure does not destroy user input.
|
|
62
|
+
3. A normal note needs no reminder.
|
|
63
|
+
4. A normal note needs no encryption.
|
|
64
|
+
5. Encryption only when explicitly requested.
|
|
65
|
+
6. Reminder state persists across exits/restarts.
|
|
66
|
+
7. A reminder missed while the machine is off stays pending.
|
|
67
|
+
8. A notification counts as delivered only after delivery succeeds.
|
|
68
|
+
9. Delivered reminders are not re-notified without cause.
|
|
69
|
+
10. Config persists in an XDG-compliant location.
|
|
70
|
+
11. User data is not silently discarded during migration.
|
|
71
|
+
12. API keys never appear in ordinary displayed config output.
|
|
72
|
+
13. Tests never depend on external paid services.
|
|
73
|
+
14. The project stays a focused improvement of `dontforget`.
|
|
74
|
+
|
|
75
|
+
## Compatibility / secrets
|
|
76
|
+
|
|
77
|
+
* Preserve upstream `memory.db` via migration; never silently destroy data.
|
|
78
|
+
* Document intentional compatibility breaks in `ROADMAP.md` and PRD.
|
|
79
|
+
* Never print secrets; `config show` masks keys as `configured`.
|
|
80
|
+
* Never send encrypted note content to external AI.
|
|
81
|
+
|
|
82
|
+
## ROADMAP maintenance
|
|
83
|
+
|
|
84
|
+
Keep `ROADMAP.md` updated continuously. A task is complete only when
|
|
85
|
+
implementation exists, tests pass, docs are updated, and no known regression
|
|
86
|
+
remains in scope. Use status markers: `[ ]` not started, `[~]` in progress,
|
|
87
|
+
`[x]` complete, `[!]` blocked.
|
|
88
|
+
|
|
89
|
+
## Justfile workflow
|
|
90
|
+
|
|
91
|
+
Use `just` recipes: `just build`, `just run`, `just fmt`, `just lint`,
|
|
92
|
+
`just test`, `just check`. See `Justfile` for details.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Justfile — Better Dontforget development workflow
|
|
2
|
+
#
|
|
3
|
+
# Canonical quality gate: `just check`
|
|
4
|
+
|
|
5
|
+
# Show available recipes.
|
|
6
|
+
default:
|
|
7
|
+
@just --list
|
|
8
|
+
|
|
9
|
+
# Install dependencies (uv-managed virtual environment).
|
|
10
|
+
install:
|
|
11
|
+
uv sync
|
|
12
|
+
|
|
13
|
+
# Build a distributable wheel/sdist.
|
|
14
|
+
build:
|
|
15
|
+
uv build
|
|
16
|
+
|
|
17
|
+
# Run the application (opens TUI when no arguments are given).
|
|
18
|
+
run *ARGS:
|
|
19
|
+
uv run better-dontforget {{ARGS}}
|
|
20
|
+
|
|
21
|
+
# Format all Python sources.
|
|
22
|
+
fmt:
|
|
23
|
+
uv run ruff format .
|
|
24
|
+
|
|
25
|
+
# Lint (ruff check).
|
|
26
|
+
lint:
|
|
27
|
+
uv run ruff check .
|
|
28
|
+
|
|
29
|
+
# Type-check (mypy) on the package.
|
|
30
|
+
type:
|
|
31
|
+
uv run mypy better_dontforget
|
|
32
|
+
|
|
33
|
+
# Run the test suite.
|
|
34
|
+
test:
|
|
35
|
+
uv run pytest
|
|
36
|
+
|
|
37
|
+
# Canonical full-project verification.
|
|
38
|
+
check:
|
|
39
|
+
uv run ruff format --check .
|
|
40
|
+
uv run ruff check .
|
|
41
|
+
uv run mypy better_dontforget
|
|
42
|
+
uv run pytest
|
|
43
|
+
uv build
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: better-dontforget
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: AI-assisted terminal tool for quick personal memory dumps: better TUI, multiple AI providers, optional reminders with desktop notifications, optional per-note encryption, XDG storage, CLI/TUI config.
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: cryptography>=42.0.0
|
|
7
|
+
Requires-Dist: google-genai>=1.0.0
|
|
8
|
+
Requires-Dist: openai>=1.0.0
|
|
9
|
+
Requires-Dist: rich>=13.0.0
|
|
10
|
+
Requires-Dist: textual>=8.0.0
|
|
11
|
+
Requires-Dist: tomli-w>=1.0.0
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# 🧠 Better Dontforget
|
|
15
|
+
|
|
16
|
+
> 🍴 **A fork of [`bugswriter/dontforget`](https://github.com/bugswriter/dontforget).**
|
|
17
|
+
|
|
18
|
+
**Better Dontforget** is a focused improvement of the upstream `dontforget`
|
|
19
|
+
project: an AI-assisted terminal tool for quickly capturing and retrieving small
|
|
20
|
+
personal memory dumps, enhanced with a better TUI, configurable AI providers,
|
|
21
|
+
optional reminders with persistent desktop notifications, optional per-note
|
|
22
|
+
encryption, XDG-compliant storage, and CLI/TUI-based configuration.
|
|
23
|
+
|
|
24
|
+
> It is a quick personal memory-dump tool. Reminders and encryption are optional
|
|
25
|
+
> and per-note. It is **not** a calendar, task manager, or full notes application.
|
|
26
|
+
|
|
27
|
+
## 📦 Install
|
|
28
|
+
|
|
29
|
+
From [PyPI](https://pypi.org/project/better-dontforget/):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install better-dontforget
|
|
33
|
+
better-dontforget config set provider gemini
|
|
34
|
+
better-dontforget config set api_key "$GEMINI_API_KEY"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or, for development from source:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uv sync
|
|
41
|
+
better-dontforget "anything"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## ✨ Features
|
|
45
|
+
|
|
46
|
+
* **⚡ Zero-friction capture:** `better-dontforget "anything"`. Works offline; AI
|
|
47
|
+
tagging is best-effort and never loses your input.
|
|
48
|
+
* **🔍 Search & AI recall:** full-text search (`search`) and AI-assisted answers
|
|
49
|
+
(`remind`) over your memories (SQLite + FTS5).
|
|
50
|
+
* **🤖 Multiple AI providers:** Gemini (default) and OpenAI-compatible
|
|
51
|
+
(OpenAI, OpenRouter, self-hosted), behind a small provider abstraction.
|
|
52
|
+
* **🖥️ Improved TUI:** view/add/edit/delete/search, reminders, encryption, and
|
|
53
|
+
settings — all keyboard-driven.
|
|
54
|
+
* **⏰ Optional reminders:** attach a due time to a note via `--remind` or natural
|
|
55
|
+
language ("remind me tomorrow to …").
|
|
56
|
+
* **🔔 Desktop notifications:** due reminders notify via `notify-send` (libnotify),
|
|
57
|
+
with a one-shot `notify-pending` command and optional systemd user timer that
|
|
58
|
+
survives restarts.
|
|
59
|
+
* **🔐 Optional per-note encryption:** authenticated (Fernet + PBKDF2), passphrase
|
|
60
|
+
based, explicit per note; encrypted content is never sent to AI.
|
|
61
|
+
* **📁 XDG-compliant storage** and **CLI/TUI configuration** (no manual file editing).
|
|
62
|
+
|
|
63
|
+
## 🚀 Quick start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uv sync
|
|
67
|
+
better-dontforget config set provider gemini
|
|
68
|
+
better-dontforget config set api_key "$GEMINI_API_KEY"
|
|
69
|
+
|
|
70
|
+
better-dontforget "ratatui was that rust tui library"
|
|
71
|
+
better-dontforget "remind me tomorrow 9am to check that library"
|
|
72
|
+
better-dontforget search "rust tui"
|
|
73
|
+
better-dontforget tui
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The short alias **`bdf`** is also installed (`bdf "ratatui was that rust tui library"`, `bdf search "rust tui"`, …).
|
|
77
|
+
|
|
78
|
+
See [`docs/docs.md`](docs/docs.md) for full usage and
|
|
79
|
+
[`docs/config.md`](docs/config.md) for configuration.
|
|
80
|
+
|
|
81
|
+
## 🛠️ Development
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
just install # uv sync
|
|
85
|
+
just check # format + lint + type + tests + build (canonical gate)
|
|
86
|
+
just test
|
|
87
|
+
just lint
|
|
88
|
+
just fmt
|
|
89
|
+
just type
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 📄 License
|
|
93
|
+
|
|
94
|
+
GPL-3. Upstream `dontforget` by Suraj Kushwah; legacy server/client retained under
|
|
95
|
+
`legacy/` for attribution.
|
|
96
|
+
|
|
97
|
+
## 🙏 Credits
|
|
98
|
+
|
|
99
|
+
Better Dontforget is a fork of [`bugswriter/dontforget`](https://github.com/bugswriter/dontforget)
|
|
100
|
+
by **Suraj Kushwah**. The original SQLite + FTS5 storage engine and AI-assisted
|
|
101
|
+
capture/recall concept are carried over and extended; the legacy FastAPI
|
|
102
|
+
server and bash `curl` client are preserved under `legacy/` for reference.
|
|
103
|
+
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# PRD — Better Dontforget
|
|
2
|
+
|
|
3
|
+
## Project name
|
|
4
|
+
|
|
5
|
+
**Better Dontforget** (repository: `better-dontforget`)
|
|
6
|
+
|
|
7
|
+
## Project summary
|
|
8
|
+
|
|
9
|
+
Better Dontforget is a focused improvement of the upstream `bugswriter/dontforget`
|
|
10
|
+
(author Suraj Kushwah) project. It is an AI-assisted terminal tool for quickly
|
|
11
|
+
capturing and retrieving small personal memory dumps, enhanced with a better TUI,
|
|
12
|
+
configurable AI providers, optional reminders with persistent desktop
|
|
13
|
+
notifications, optional per-note encryption, XDG-compliant storage, and
|
|
14
|
+
CLI/TUI-based configuration.
|
|
15
|
+
|
|
16
|
+
## Relationship to upstream `dontforget`
|
|
17
|
+
|
|
18
|
+
The upstream project is a Python **FastAPI server** (`main.py`) plus a bash
|
|
19
|
+
**curl client** (`mem-cli`). It stores raw notes in SQLite with an FTS5 full-text
|
|
20
|
+
index, uses Google Gemini to auto-generate search tags on capture and to
|
|
21
|
+
synthesize answers on query, and requires a long-running server plus a secret key.
|
|
22
|
+
|
|
23
|
+
Better Dontforget **preserves**:
|
|
24
|
+
|
|
25
|
+
* the SQLite + FTS5 storage engine and its data (with backward-compatible migration);
|
|
26
|
+
* the quick-capture + AI-assisted-tagging workflow;
|
|
27
|
+
* the AI-assisted retrieval / synthesis workflow;
|
|
28
|
+
* the Gemini provider (kept as a first-class provider).
|
|
29
|
+
|
|
30
|
+
Better Dontforget **changes the runtime shape** with demonstrated justification:
|
|
31
|
+
the upstream client/server model forces a running server and makes capture
|
|
32
|
+
synchronously dependent on AI (a failed AI call loses the note). The requested
|
|
33
|
+
improvements — reliable notifications while the CLI/TUI is closed, an interactive
|
|
34
|
+
TUI, per-note encryption, XDG storage, and config without manual file editing —
|
|
35
|
+
are a poor fit for a required-running HTTP server driven by a bash `curl` script.
|
|
36
|
+
Better Dontforget is therefore a **self-contained CLI + TUI application** that
|
|
37
|
+
talks directly to local storage and to AI providers, while keeping the storage
|
|
38
|
+
format and useful AI behavior intact. The legacy server/client files are retained
|
|
39
|
+
under `legacy/` for reference and attribution; they are not part of the shipped
|
|
40
|
+
application.
|
|
41
|
+
|
|
42
|
+
## Product philosophy
|
|
43
|
+
|
|
44
|
+
> The primary product is a quick personal memory-dump tool. Reminders are an
|
|
45
|
+
> optional capability attached to a note, not the primary abstraction. Encryption
|
|
46
|
+
> is also optional and explicitly selected per note. Better Dontforget must not
|
|
47
|
+
> evolve into a calendar, task manager, project manager, full notes application,
|
|
48
|
+
> knowledge base, or second-brain system.
|
|
49
|
+
|
|
50
|
+
> The goal is to improve the existing upstream project with the smallest coherent
|
|
51
|
+
> changes. A ground-up rewrite is not desired unless repository inspection
|
|
52
|
+
> demonstrates that preserving the existing implementation would make the
|
|
53
|
+
> requirements substantially harder, less reliable, or less maintainable.
|
|
54
|
+
|
|
55
|
+
## Target use case
|
|
56
|
+
|
|
57
|
+
Fast, low-friction capture and later retrieval of small personal facts:
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
the rust tui library was called ratatui
|
|
61
|
+
wifi password is written behind the router
|
|
62
|
+
John recommended Severance
|
|
63
|
+
remind me tomorrow to check that library
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Existing upstream behavior being preserved
|
|
67
|
+
|
|
68
|
+
* SQLite + FTS5 storage and schema (`memories` + `memories_idx`).
|
|
69
|
+
* AI-assisted capture tags.
|
|
70
|
+
* AI-assisted query synthesis over retrieved memories.
|
|
71
|
+
* The `remember` / `remind` / `delete` conceptual operations.
|
|
72
|
+
|
|
73
|
+
## Improvements introduced by Better Dontforget
|
|
74
|
+
|
|
75
|
+
1. Improved TUI.
|
|
76
|
+
2. Multiple configurable AI/LLM providers (Gemini + OpenAI-compatible).
|
|
77
|
+
3. Optional reminders attached to quick notes.
|
|
78
|
+
4. Desktop notifications for due reminders.
|
|
79
|
+
5. Reliable background notification processing.
|
|
80
|
+
6. Persistent reminders that survive application exits and machine restarts.
|
|
81
|
+
7. Optional per-note encryption.
|
|
82
|
+
8. XDG-compliant application paths.
|
|
83
|
+
9. Configuration through CLI and TUI rather than manual file editing.
|
|
84
|
+
10. Better project documentation and agentic development infrastructure.
|
|
85
|
+
|
|
86
|
+
## v1 requirements
|
|
87
|
+
|
|
88
|
+
* Self-contained CLI + TUI (no required server).
|
|
89
|
+
* Quick capture works without AI; AI failure never loses user input.
|
|
90
|
+
* Multiple AI providers behind a small abstraction; OpenAI-compatible covers
|
|
91
|
+
OpenAI and OpenRouter via a configurable base URL.
|
|
92
|
+
* Optional reminders persisted per note; due/overdue detection.
|
|
93
|
+
* Desktop notifications via the platform mechanism (`notify-send`/libnotify).
|
|
94
|
+
* One-shot `notify-pending` command + optional systemd user timer/service for
|
|
95
|
+
reliable processing while the interactive app is closed and after restarts.
|
|
96
|
+
* Optional per-note encryption (authenticated, passphrase-derived key).
|
|
97
|
+
* XDG-compliant config/data paths.
|
|
98
|
+
* CLI `config` subcommand and TUI settings; no manual file editing required.
|
|
99
|
+
* Backward-compatible migration of existing upstream `memory.db`.
|
|
100
|
+
|
|
101
|
+
## Explicit non-goals
|
|
102
|
+
|
|
103
|
+
* Calendar, task manager, project manager, to-do app, document editor.
|
|
104
|
+
* Personal wiki, knowledge graph, second-brain, kanban, Markdown knowledge base.
|
|
105
|
+
* Cloud sync, collaboration, user accounts, team features, mobile apps.
|
|
106
|
+
* Vector databases, embeddings, semantic-search/RAG pipelines.
|
|
107
|
+
* Recurring reminder engines / complex recurrence rules (v1).
|
|
108
|
+
* Custom daemons, IPC, RPC, socket servers, or service frameworks.
|
|
109
|
+
* Telegram/ntfy/email/SMS/mobile push/webhook notification transports (v1).
|
|
110
|
+
|
|
111
|
+
## Quick-note behavior
|
|
112
|
+
|
|
113
|
+
* `better-dontforget "anything"` captures a note instantly.
|
|
114
|
+
* Capture is synchronous and local; AI tagging is best-effort and failures are
|
|
115
|
+
non-fatal (note is still saved, possibly without tags).
|
|
116
|
+
* A normal note never requires a reminder or encryption.
|
|
117
|
+
* Optional flags: `--encrypt` (encrypted note), `--remind "<when>"` (attach
|
|
118
|
+
reminder). Encrypted notes are not sent to AI.
|
|
119
|
+
|
|
120
|
+
## AI behavior
|
|
121
|
+
|
|
122
|
+
* On capture: AI generates search tags (best-effort).
|
|
123
|
+
* On query (`remind`/`ask`): AI extracts keywords, FTS retrieves candidates, AI
|
|
124
|
+
synthesizes an answer. If AI is unavailable, falls back to raw FTS listing.
|
|
125
|
+
* On `search`: direct FTS listing (no AI).
|
|
126
|
+
* Only the content needed for the requested operation is sent to the provider.
|
|
127
|
+
|
|
128
|
+
## Multiple-provider behavior
|
|
129
|
+
|
|
130
|
+
* Providers: `gemini` (default), `openai` (OpenAI-compatible: OpenAI, OpenRouter),
|
|
131
|
+
`groq` (OpenAI-compatible: Groq).
|
|
132
|
+
* Selected via `config set provider <name>`.
|
|
133
|
+
* Credentials read from config or environment (`GEMINI_API_KEY`, `OPENAI_API_KEY`).
|
|
134
|
+
* `openai` provider supports a configurable `base_url` for OpenRouter/self-hosted.
|
|
135
|
+
* Provider calls are mockable; tests never use real keys.
|
|
136
|
+
|
|
137
|
+
## Optional-reminder behavior
|
|
138
|
+
|
|
139
|
+
* A reminder is an optional `reminder_at` timestamp on a note.
|
|
140
|
+
* Set via `--remind "<spec>"` or from natural-language intent ("remind me
|
|
141
|
+
tomorrow to …") parsed by a deterministic heuristic.
|
|
142
|
+
* Ordinary notes remain ordinary notes.
|
|
143
|
+
* No calendar semantics, recurrence, or task-completion workflow in v1.
|
|
144
|
+
|
|
145
|
+
## Desktop-notification behavior
|
|
146
|
+
|
|
147
|
+
* When a reminder becomes due, a local desktop notification is sent via
|
|
148
|
+
`notify-send` (libnotify), the established Linux mechanism.
|
|
149
|
+
* Notification is attempted only for due, not-yet-delivered reminders.
|
|
150
|
+
* Marked delivered only after successful delivery; duplicates avoided.
|
|
151
|
+
|
|
152
|
+
## Persistent missed-reminder behavior
|
|
153
|
+
|
|
154
|
+
* Reminders are persisted in the database.
|
|
155
|
+
* A reminder due while the machine is off cannot notify at that instant.
|
|
156
|
+
* On next `notify-pending` run (e.g. after login via systemd timer), due and
|
|
157
|
+
unnotified reminders (including overdue ones) are detected and notified.
|
|
158
|
+
* Policy: all due unnotified reminders are notified; no recurrence, so volume is
|
|
159
|
+
naturally bounded. No silent discarding.
|
|
160
|
+
|
|
161
|
+
## Optional per-note encryption
|
|
162
|
+
|
|
163
|
+
* Explicit only: `--encrypt` flag or TUI explicit action.
|
|
164
|
+
* Uses `cryptography` Fernet (authenticated) with PBKDF2 key derivation from a
|
|
165
|
+
passphrase (prompted at runtime, never stored).
|
|
166
|
+
* Encrypted content is not sent to external AI.
|
|
167
|
+
* Plaintext is never persisted; decrypted content is never logged.
|
|
168
|
+
* Incorrect passphrase fails closed (decryption error surfaced, no leak).
|
|
169
|
+
|
|
170
|
+
## TUI requirements
|
|
171
|
+
|
|
172
|
+
* View, add, edit, delete notes; search/filter; inspect reminder state; attach/
|
|
173
|
+
remove reminder; create encrypted note; unlock/decrypt; access settings.
|
|
174
|
+
* Keyboard-driven; handles resize and ordinary errors gracefully.
|
|
175
|
+
* Not a full notes editor: no analytics, kanban, calendar, nested trees.
|
|
176
|
+
|
|
177
|
+
## CLI requirements
|
|
178
|
+
|
|
179
|
+
* `better-dontforget "text"` quick capture; `--encrypt`, `--remind`.
|
|
180
|
+
* Subcommands: `remind`/`ask`, `search`, `list`, `delete`, `tui`, `config`,
|
|
181
|
+
`notify-pending`.
|
|
182
|
+
* Backward-compatible intent with upstream `mem` (remember/remind/delete).
|
|
183
|
+
|
|
184
|
+
## Configuration behavior
|
|
185
|
+
|
|
186
|
+
* Stored as TOML in `$XDG_CONFIG_HOME/better-dontforget/config.toml`.
|
|
187
|
+
* Managed via `config show|set|reset` and TUI settings.
|
|
188
|
+
* `config show` masks secrets ("API key: configured").
|
|
189
|
+
* No manual file editing required.
|
|
190
|
+
|
|
191
|
+
## XDG requirements
|
|
192
|
+
|
|
193
|
+
* Config: `$XDG_CONFIG_HOME/better-dontforget/`
|
|
194
|
+
* Data (DB): `$XDG_DATA_HOME/better-dontforget/`
|
|
195
|
+
* State/cache/runtime only if actually needed (not created speculatively).
|
|
196
|
+
* Fallbacks to `~/.config`, `~/.local/share` when base vars unset.
|
|
197
|
+
* Existing `./memory.db` is migrated into the XDG data dir on first run.
|
|
198
|
+
|
|
199
|
+
## Reliability requirements
|
|
200
|
+
|
|
201
|
+
See "Reliability invariants" in the mission. Key: capture never lost; AI failure
|
|
202
|
+
non-fatal; reminder/encryption optional and explicit; notification success gated
|
|
203
|
+
on delivery; config + data in XDG; no secret leakage.
|
|
204
|
+
|
|
205
|
+
## Error-handling expectations
|
|
206
|
+
|
|
207
|
+
* Missing/invalid credentials: clear message; capture and local search still work.
|
|
208
|
+
* AI rate limits/timeouts/malformed responses: degrade gracefully, never lose input.
|
|
209
|
+
* Notification failure: leave reminder unnotified, retry next run.
|
|
210
|
+
* Wrong encryption passphrase: fail closed.
|
|
211
|
+
|
|
212
|
+
## Compatibility expectations
|
|
213
|
+
|
|
214
|
+
* Existing upstream `memory.db` data is preserved via migration.
|
|
215
|
+
* Upstream behavior (tags, FTS retrieval) preserved.
|
|
216
|
+
* Legacy `mem`/server retained under `legacy/` for attribution only.
|
|
217
|
+
|
|
218
|
+
## Acceptance criteria
|
|
219
|
+
|
|
220
|
+
1. Quick capture works offline and without AI.
|
|
221
|
+
2. `just check` passes (fmt, lint, type, tests, build).
|
|
222
|
+
3. Multiple providers work; tests mock providers, no real keys.
|
|
223
|
+
4. Reminders persist; due + overdue detection works; no duplicate notify.
|
|
224
|
+
5. `notify-pending` works while app closed; systemd user unit documented.
|
|
225
|
+
6. Per-note encryption round-trips; wrong passphrase fails closed.
|
|
226
|
+
7. XDG paths used; config via CLI/TUI; secrets masked.
|
|
227
|
+
8. TUI supports required operations.
|
|
228
|
+
9. Docs match implementation; scope not expanded.
|
|
229
|
+
|
|
230
|
+
## Definition of done
|
|
231
|
+
|
|
232
|
+
All items in the mission's Definition of Done are satisfied: `just check` passes,
|
|
233
|
+
PRD/AGENTS/ROADMAP/docs consistent, features implemented and tested, scope
|
|
234
|
+
preserved as a focused improvement of `dontforget`.
|