Metadata-Version: 2.5
Name: opendesk-local
Version: 0.1.3
Summary: OpenDesk: local-first workspace observatory. Search, map, clean, and question your own local files privately.
Project-URL: Homepage, https://github.com/shubhanand18091111-bruno/opendesk
Project-URL: Documentation, https://github.com/shubhanand18091111-bruno/opendesk#readme
Project-URL: License, https://www.apache.org/licenses/LICENSE-2.0
Author: OpenDesk Contributors
License: Apache-2.0
License-File: LICENSE
Keywords: cli,fts5,local-first,search,sqlite
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Utilities
Requires-Python: >=3.12
Requires-Dist: fastapi>=0.110.0
Requires-Dist: typer>=0.9.0
Requires-Dist: uvicorn>=0.29.0
Provides-Extra: test
Requires-Dist: httpx>=0.27.0; extra == 'test'
Requires-Dist: pytest>=8.0.0; extra == 'test'
Requires-Dist: pyyaml>=6.0; extra == 'test'
Description-Content-Type: text/markdown

# OpenDesk

[![CI](https://github.com/shubhanand18091111-bruno/opendesk/actions/workflows/ci.yml/badge.svg)](https://github.com/shubhanand18091111-bruno/opendesk/actions/workflows/ci.yml)

**Search, map, and question your local files privately.**

OpenDesk is a local-first, open-source alternative to cloud document search. It gives you private file search, personal knowledge search, and optional local AI document Q&A over your own folders — with a self-hosted document search index that never leaves your machine.

```powershell
pipx install opendesk-local
opendesk scan ~/my-folder
opendesk search "quarterly notes"
```

No account. No telemetry. No cloud. Your files stay yours.

![OpenDesk search UI with real results](docs/screenshot.png)
*Real local output: searching the `docs/demo-workspace` notebook for "tomato".*

## The problem

- Finding things means `grep`, guessing filenames, or paying a cloud service to index your documents.
- Basic Q&A over your own notes requires uploading documents to someone else's AI.
- Duplicates pile up across folders and nobody hunts them down.
- Notes scatter across formats (Markdown, text, code, PDFs) with no single private search.

## The solution

OpenDesk indexes a folder you choose into a local SQLite database (FTS5 full-text search) and lets you:

- **Search** everything offline with scored snippets (`opendesk search`).
- **Map** workspace health: duplicates, empty/large/stale files, missing READMEs (`opendesk report`).
- **Clean up** with workspace cleanup guidance (redacted secret detection, safe recommendations, nothing auto-deleted).
- **Question** your files with optional local AI document Q&A that cites sources (`opendesk ask`).
- **Export** evidence to Markdown or JSON (`opendesk export`).
- **Browse** a localhost-only web UI (`opendesk serve` → http://localhost:8484).

Core search works with zero AI. AI is opt-in, uses only an endpoint you configure, and only ever receives the top retrieved chunks — never your whole workspace.

## What OpenDesk does

| Need | Command |
|---|---|
| Index a folder | `opendesk scan <folder>` |
| Private file search | `opendesk search "query"` |
| Workspace health + cleanup | `opendesk report [folder]` |
| Local AI document Q&A (optional) | `opendesk ask "question"` |
| Evidence export | `opendesk export --format md\|json` |
| Local web UI | `opendesk serve` (http://localhost:8484) |

Supported text types (v0): `.md .txt .rst .csv .json .py .js .ts .html .pdf`.
Skips `.git`, `node_modules`, `__pycache__`, `.venv`, and files over 50 MB by default.

## Privacy promise

- **Local-first, always.** Scan, index, search, report, export, and the UI run on your machine. No network calls in the core path.
- **No telemetry.** No analytics, no tracking, no phone-home.
- **No account, no cloud.** The index is a SQLite file in your user data dir (override with `OPENDESK_DATA_DIR` or `--db`).
- **AI is optional and user-controlled.** Set `OPENDESK_AI_ENDPOINT` (Ollama, OpenAI-compatible, or custom) only if you want it. Keys live in your environment, never in the database or exports.
- **Nothing is auto-deleted.** OpenDesk reads your files; it writes only its own index elsewhere.
- Details: [SECURITY.md](SECURITY.md).

## Install

Requires Python 3.12+.

The command is simply: `opendesk` (if your shell can't find it, `python -m opendesk` always works — see Troubleshooting).

With pipx (recommended):

```powershell
pipx install opendesk-local   # PyPI distribution name; the command stays `opendesk`
opendesk --help
```

Install from source (cloned repo):

```powershell
pipx install .
opendesk --help
```

With pip:

```powershell
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install .
opendesk --help
```

For development:

```powershell
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -e ".[test]"
python -m pytest -q
```

With Docker (optional, local only):

```powershell
docker build -t opendesk .
docker run --rm opendesk --help
# Or pull the release image (no account needed for public packages):
docker run --rm ghcr.io/shubhanand18091111-bruno/opendesk:latest --help
```

No `docker-compose.yml`: OpenDesk is one local process with nothing to orchestrate.

## Quickstart (60 seconds)

```powershell
# 0. Install (15s)
pipx install opendesk-local
# 1. Make a demo workspace (5s)
mkdir demo_ws
"hello opendesk local search" | Out-File demo_ws\notes.md -Encoding utf8
"print('hi')" | Out-File demo_ws\app.py -Encoding utf8
# 2. Index it (10s) — first real command (`opendesk init <folder>` pre-registration is optional)
opendesk scan demo_ws
# 3. Search it (5s)
opendesk search "opendesk" --limit 5
# 4. Health report (10s)
opendesk report demo_ws
# 5. Ask — offline fallback unless AI is configured (5s)
opendesk ask "opendesk" --limit 5
# 6. Web UI (10s) — open http://localhost:8484
opendesk serve
```

Expected: scan prints `files indexed`, search prints scored snippets, report prints counts + recommendations, ask prints citations.

## Screenshots

All visuals are real product output from the sample notebook in
[`docs/demo-workspace/`](docs/demo-workspace/) — no mock data, no CDN assets.
Regenerate anytime (dev-only deps: `playwright`, Chromium, `pillow`):

```powershell
pip install playwright pillow
python -m playwright install chromium
python docs/capture_screenshots.py
```

![OpenDesk search with results](docs/screenshot.png)
*Search for "tomato": PDF + Markdown hits with snippets, file types, scores.*

![Workspace health report panel](docs/report.png)

![Settings panel](docs/settings.png)

![UI flow: search → report → settings](docs/demo.gif)
*Short loop captured from the real local UI.*

Manual alternative (no Playwright): `python docs/make_demo_workspace.py`,
then `opendesk scan docs/demo-workspace --db demo.db`,
then `opendesk serve --db demo.db`, and screenshot
http://localhost:8484 yourself. For a full 30–60 s narrated demo
(scan → search → report), record your terminal + browser with a free tool
such as ScreenToGif (Windows) or OBS Studio, and keep the clip small.

## Commands

| Command | Purpose |
|---|---|
| `opendesk --help` / `--version` | Help, version |
| `opendesk init <folder> [--db PATH]` | Register a workspace (optional pre-registration; scan works without it) |
| `opendesk scan <folder> [--db PATH] [--max-bytes N]` | Index supported files; prints found/indexed/skipped/chunks/database |
| `opendesk search "query" [--type md] [--limit 10] [--db PATH] [--workspace PATH]` | Offline search (default: all workspaces) with snippet, score, type, modified time |
| `opendesk workspaces [--db PATH]` | List indexed workspaces with file/chunk counts and last-scanned time |
| `opendesk forget <folder> [--yes] [--db PATH]` | Remove a workspace from the index only (never touches your files) |
| `opendesk report [folder] [--format text\|md\|json] [--db PATH] [--output FILE] [--workspace PATH]` | Health report (default workspace: most recently scanned); snapshots to DB for export |
| `opendesk ask "question" [--limit 5] [--db PATH] [--workspace PATH]` | Retrieval + optional AI answer with citations (default workspace: most recently scanned) |
| `opendesk export --format md\|json [--db PATH] [--output FILE]` | Evidence export, secrets redacted, no API keys |
| `opendesk serve [--host 127.0.0.1] [--port 8484] [--db PATH]` | Localhost-only web UI |

AI configuration (optional, env only):

```powershell
$env:OPENDESK_AI_ENDPOINT = "http://localhost:11434/api/generate"
$env:OPENDESK_AI_TYPE = "ollama"   # ollama | openai | custom (auto-detected if omitted)
$env:OPENDESK_AI_MODEL = "llama3"
```

Demo commands:

```powershell
opendesk scan demo_ws --db demo.db
opendesk search "hello" --db demo.db --limit 5
opendesk search "hello" --db demo.db --type md
opendesk report demo_ws --db demo.db --format md
opendesk ask "hello" --db demo.db
opendesk export --format md --db demo.db
opendesk export --format json --db demo.db --output evidence.json
```

## Honest comparison

OpenDesk replaces, for personal/local use:

- manual file searching (`grep`, guessing filenames, digging through folders)
- uploading documents to cloud AI for basic Q&A
- duplicate hunting by hand
- scattered note search across formats with no single index

OpenDesk does **not** replace:

- cloud backup (it indexes files; it does not back them up)
- team collaboration suites (single-machine SQLite, no sync)
- enterprise permission systems (no ACLs, no audit log)
- professional legal/medical advice (AI answers cite your files; they are not professional counsel)

If you need hosted search, shared workspaces, or compliance controls, use a tool built for that. OpenDesk is the open-source alternative for people who want their personal knowledge search to stay home.

## FAQ

**Does OpenDesk upload my files?**
No. Indexing, search, reports, and the UI are fully local.

**Do I need AI?**
No. Without an endpoint, `ask` prints: "AI answers are not configured. Search results are shown instead."

**What does the AI endpoint receive?**
Only the top retrieved chunks (default 5, truncated to 500 chars each) plus your question. Never the whole workspace, never the web.

**Where is my data?**
One SQLite file: `%LOCALAPPDATA%\opendesk\opendesk.db` on Windows, `~/.local/share/opendesk/opendesk.db` elsewhere. Override per-command with `--db PATH` or globally with `OPENDESK_DATA_DIR`.

**PDFs?**
Text is extracted when a PDF library is available; otherwise metadata-only with status `text_extraction_failed`, flagged in the report.

**Login, billing, sync?**
None exist. Out of scope by design (see CHARTER.md).

**How does OpenDesk compare to Everything, Notion AI, ChatGPT, Copilot…?**
See [docs/comparisons.md](docs/comparisons.md): per-tool "replaces for / does
not replace for" with honest limits.

## Troubleshooting

### `opendesk` command not found after install

The installer puts `opendesk.exe`/`opendesk` in Python's Scripts/bin directory,
which is not always on `PATH`. First find where it went:

```powershell
python -c "import sysconfig; print(sysconfig.get_path('scripts'))"
```

Reliable fallback — always works, no PATH change needed:

```powershell
python -m opendesk --help
```

Windows (per-user `pip install`): the Scripts dir looks like
`C:\Users\<you>\AppData\Roaming\Python\Python314\Scripts` (version varies).
Add it for the current session:

```powershell
$scripts = python -c "import sysconfig; print(sysconfig.get_path('scripts'))"
$env:Path += ";$scripts"
```

Permanent: Settings → "Edit the system environment variables" → Environment
Variables → Path → New → paste the Scripts path. Or: `setx PATH "$env:Path;$scripts"`,
then open a new terminal.

macOS / Linux: the script lands in `~/.local/bin`. Add to your shell once:

```sh
export PATH="$HOME/.local/bin:$PATH"   # put in ~/.bashrc or ~/.zshrc
```

Cleanest option on any OS: [pipx](https://pipx.pypa.io/) isolates the install
and handles `PATH` for you:

```sh
pipx install .
pipx ensurepath
opendesk --help
```

### `search` says "0 results …"

The message names the scope, e.g. `0 results in 2 indexed workspaces
(18 chunks)`. No workspaces at all means nothing is indexed yet — run
`opendesk scan <folder>` first, then search.

### On Windows with OneDrive backup, Desktop and Documents may live under C:\Users\<you>\OneDrive\... instead of C:\Users\<you>\.... When in doubt use `.` (the current folder) or copy the path from Explorer.

### Odd `\U0001f389`-style escapes in output

Legacy Windows consoles (cp1252) cannot display emoji/CJK characters, so
OpenDesk prints `\U` escapes there instead of crashing. Use Windows Terminal
(UTF-8) to see the real characters.

## Performance (measured)

Honest numbers from a synthetic corpus (Windows desktop, Python 3.14, SSD):

- Indexing: ~750 chunks/sec — 502 files / 25,123 chunks / 21 MB took ~34 s
  one-time. Re-scans are incremental (unchanged files are skipped by hash).
- Search at 25,000 chunks: cold ~7 ms, warm ~2 ms, common-term top-10 ~43 ms —
  comfortably under the 200 ms target.
- Ranking is BM25 best-first (higher term frequency ranks first; verified).

## Limitations

- Text-based types only (v0 list above); anything else is ignored except secret-looking names (metadata only).
- FTS5 keyword ranking — no embeddings yet, so paraphrase search is weak.
- Single-machine scale; 100k+ file workspaces are untested.
- Scanned-image PDFs yield metadata only.
- AI quality depends entirely on your endpoint; weak evidence returns "Not enough evidence."

## Roadmap

- Richer cleanup rules (dependency and binary hygiene).
- UI polish (saved searches, keyboard-first flows).
- Optional local embeddings — still offline, still opt-in.
- OS packaging (pipx works today; native installers later).
- Never: accounts, telemetry, hosted services.

## License

Apache-2.0. See [LICENSE](LICENSE).
