# User guide — Codescry

Codescry points an **on-device model** at a folder of projects and grades each one across
five axes, then turns an "About Me" profile into personal project ideas. There is no account
and no server: scanning, analysis, results and your profile all stay on this machine.

- [Before you start](#before-you-start)
- [First run](#first-run)
- [Your first scan](#your-first-scan)
- [Reading a report](#reading-a-report)
- [Resolve and snooze](#resolve-and-snooze)
- [The five axes](#the-five-axes)
- [Offline mode](#offline-mode)
- [Exporting](#exporting)
- [Idea generator](#idea-generator)
- [Where your data lives](#where-your-data-lives)
- [Back up and restore](#back-up-and-restore)
- [Troubleshooting](#troubleshooting)

---

## Before you start

Codescry does the analysis itself, but it needs a **local model engine** to run the model:
install [Ollama](https://ollama.com) and leave it running. Codescry talks to it on
`127.0.0.1:11434` and nowhere else — it downloads the model *through* the engine, so you
don't have to fetch one by hand.

Rough requirements for the default model: 8 GB of system RAM (~6 GB free for the model) and
~4 GB of disk. A GPU is optional — everything works on CPU, just slower. Bigger models want
more (see the table in [First run](#first-run)).

## First run

Onboarding is four steps — **Welcome → Folder → Model → Axes**. The stepper at the top lets
you jump back to a completed step; you can also re-run the whole thing later from
**Settings → Folders & scanning → Re-run onboarding**.

### 1. Welcome

What the app does, and the point worth repeating: everything runs on your machine, nothing
is uploaded. Click **Choose projects folder**.

### 2. Pick your root folder

Point Codescry at the folder that *contains* your projects — not at a single project.
**Each top-level subfolder is treated as one project.**

`Scan depth` decides how far down it looks:

| Depth | Behavior |
|---|---|
| **Top-level only** | Every direct subfolder of the root is one project |
| **2 levels** | Also descends into a subfolder when it looks generic and has no `.git` — for a root organized as `code/web/my-app`, `code/games/my-game` |

Codescry detects the project type from what's on disk — Node, Python, Rust, .NET, Godot, Go,
Java, or `generic` when nothing matches. Type drives what "missing" and "outdated" even mean,
so a Rust project isn't graded against a Node checklist. You get a `detected N top-level
projects` count before continuing; if the folder can't be read, pick another one.

### 3. Confirm the on-device model

Codescry checks whether the engine is up and whether the model is present:

- **Model ready** — carry on.
- **Model not installed** — click **Download model**. Progress and byte counts stream live,
  then the checksum is verified. Analysis can't run until this finishes.
- **The local model engine (Ollama) isn't running** — start or install Ollama, then retry.

The catalog:

| Model | Size | RAM | Notes |
|---|---|---|---|
| `gemma3:4b` | ~3.3 GB | 6 GB | **Default** — balanced, and vision-capable, so the UI axis works |
| `qwen3:4b` | ~2.6 GB | 6 GB | Stronger code reasoning, no vision → UI axis unavailable |
| `gemma3:12b` | ~8.1 GB | 12 GB | Slower, better findings; needs a beefier machine |
| `llama3.2:3b` | ~2.0 GB | 4 GB | Smallest and fastest, lighter findings, no vision |

Pick a vision model if you care about the UI axis. You can switch, test or delete models
later in **Settings → On-device model**.

> **Model gate.** No ready model means no scanning: the Run button and every "run this axis"
> control stay disabled, with a `Scanning needs the on-device model` note pointing at Settings.

### 4. Default analysis axes

All five axes are on. Turn any off here or later in **Settings → Analysis axes** — a
toggled-off axis is skipped in every run. Note the one network warning on Outdated-tech (see
[Offline mode](#offline-mode)).

**Finish & go to dashboard.** The dashboard shows your projects detected but not yet analyzed.

## Your first scan

Hit **Run first scan** on the dashboard, one of the **Quick run** tiles, or the **Run** button
in the nav — it's available from any screen. The picker is a matrix: **scope × axis**.

| | |
|---|---|
| **Scope** | All projects · One project (searchable list) |
| **Axis** | All axes · one single axis |

So "outdated deps across everything" and "full audit of this one project" are the same control.

While a run is going, the **Run** screen shows the live queue:

- **Pause / Resume** — stops between units of work, keeps everything done so far.
- **Cancel** — either **Stop after current project** or **Stop now**. Finished results are kept either way.
- **Skip remaining axes on this project** / **Skip project** — for the one repo that's dragging.
- Per-project status (`queued`, `analyzing now`, `done`, `failed`, `skipped`), a rough ETA, and a
  live log line from the axis currently running.

The first full run takes a while — it's a local model doing real work per project per axis, not
a network call. Large projects show a `still working` note rather than looking stuck. When it
finishes you get a `Scan complete · N done` toast and a link to the portfolio report.

## Reading a report

Open a project from the dashboard or **Projects**.

### Health score

One number, 0–100, computed only from **open** findings — resolved and actively-snoozed ones
don't count:

```
health = 100 − (15 × critical + 5 × suggested + 1 × optional)     clamped to 0…100
```

| Score | Band |
|---|---|
| 80–100 | **Healthy** |
| 50–79 | **Fair** |
| 0–49 | **At risk** |

The delta next to it (`▲ +7 since last scan`) compares against the previous scan of that project.

### Severities

- **critical** — broken or genuinely risky; costs 15 points.
- **suggested** — should be fixed, isn't urgent; 5 points.
- **optional** — nice to have; 1 point.

### The five axis sections

Each axis is its own section with its own treatment: findings for most, a dependency table for
Outdated-tech, a screenshot critique for UI. An axis that hasn't run yet says
`Not analyzed yet — run this axis` with a button to run just that one; a failed axis shows
`Analysis incomplete` and a retry. Every finding card carries a title, an explanation, a
concrete recommendation, and file references where they exist.

### Portfolio view

**Portfolio Report** aggregates across projects: analyzed count, average health, total
criticals, most common issue, a **tech-debt heatmap** (project × axis, colored by worst open
severity — click a column to filter), and a **cross-project priority action list** ranked by
what actually hurts most, with an `in N projects` tag on repeated issues.

### History

**Scan History** needs two scans of a project to show anything useful. After that you get the
health-score trend and a change log per scan, tagging each finding `new`, `persisting` or
`resolved` — the diff of what you actually fixed between runs.

## Resolve and snooze

Every finding gets a stable **fingerprint** from project + axis + finding type + target. That
fingerprint is what makes the state stick across re-scans.

On any finding card:

- **✓ Mark resolved** — removed from the open set; health goes up immediately.
- **◷ Snooze 30d** — hidden and score-free for 30 days, then it comes back on its own.
- **↩ Reopen** — undo either.

What happens on the next scan:

| You did | Finding still detected | Result |
|---|---|---|
| Resolved | no | stays resolved, counted as fixed in history |
| Resolved | yes | reopens, tagged **reopened** — you marked it done but it's still there |
| Snoozed, window open | yes | stays snoozed and out of the score |
| Snoozed, window expired | yes | back to open |

Resolving is a judgment call, not a fix: it says "I've decided about this", which is exactly
why the `reopened` tag exists.

## The five axes

| Axis | Question it answers |
|---|---|
| **Missing pieces** | What a project of this type should have but doesn't |
| **Feature gaps** | Additions that fit what the project actually is |
| **Outdated tech** | Installed versions vs. latest from package registries |
| **UI quality** | What the running app actually looks like |
| **Bloat** | Files, dependencies and features that are dead weight |

Deterministic facts are measured in Rust; the model grades and explains. Model output is
always JSON-schema-constrained — raw prose never reaches the UI.

### Missing pieces

Two passes. First a **presence check** against the expected-artifact profile for the detected
type — README, LICENSE, `.gitignore`, tests, CI — each with a fixed severity and a specific
recommendation. Then a **model pass** for up to 3 deeper gaps the file listing can't reveal:
missing error handling around external calls, no `.env.example`, absent input validation, no
lockfile, undocumented setup.

### Feature gaps

Pure model pass over the file tree, README and manifest: 2–4 concrete additions that suit what
the project *is*, each with a rationale and an effort hint (S / M / L) inside the explanation.
Severity skews to suggested/optional — critical only if the project is unusable without it.

### Outdated tech

The only axis that touches the network. It parses dependency manifests (npm, PyPI, NuGet),
asks the public registries for the latest version of each package, and compares:

| Gap | Severity |
|---|---|
| 2+ major versions behind | **critical** |
| 1 major behind | **suggested** |
| 5+ minor behind | **suggested** |
| fewer minor / any patch | **optional** |

Results render as a table of installed → latest. Nothing to compare against (no supported
manifest) and the axis skips cleanly instead of inventing findings; everything current gives
you `Everything's up to date`. Version specs it can't resolve to a number — `workspace:`,
git URLs, `*`, `latest` — are skipped rather than guessed at.

Offline, or registries unreachable, and the axis records your installed versions with no
comparison and shows `Offline — latest-version data unavailable` plus a **Retry when online**.
It never fabricates a "latest" it couldn't fetch.

### UI quality

Source code can't judge a UI, so this axis needs a picture. **Attach screenshot** on the UI
section, and the model critiques the image locally — it's copied into the results folder, and
it is not uploaded anywhere. You get:

- a verdict — **modern / acceptable / dated**,
- a one-paragraph summary,
- per-aspect notes on **modernity, layout, spacing, contrast, typography**,
- 1–4 concrete findings.

Needs a vision-capable model (`gemma3:4b` or `gemma3:12b`). *Auto-capture of runnable web
projects* is a preview toggle only — the capture itself lands in a later build; attach a
screenshot for now.

### Bloat

Measured first, judged second. Directories over 30 MB and files over 10 MB are flagged with
their real sizes and how much you'd reclaim; `.git`, `node_modules`, `venv`, `.venv` and
`target` are excluded — those are normal dev artifacts, not project bloat. For Node projects
it also cross-references declared `dependencies` against actual imports and reports the ones
imported nowhere. Then a model pass adds up to 3 things the heuristics can't see: dead code
paths, generated artifacts committed to the repo, duplicated assets, legacy configs. The model
is explicitly forbidden from inventing sizes — every byte figure you see was measured.

## Offline mode

Codescry is local by default. Exactly two things ever leave the machine, both optional:

1. **Registry version lookups** for the Outdated-tech axis (npm · PyPI · NuGet) — package names
   only, no code, nothing about you.
2. **One update check per launch** against GitHub, asking whether a newer release exists.
   Codescry never downloads or installs an update on its own; the link opens the release page
   in your browser.

**Settings → Data & privacy → "Go fully offline"** stops both. The Outdated-tech axis then
lists your installed versions with no comparison; everything else — all four other axes, the
health scores, the portfolio report, the idea generator — works exactly the same, because none
of it was ever using the network. **Re-enable registry checks** turns it back on.

The degradation is also automatic: if the registries can't be reached, that run is treated as
offline rather than failing, with a `Registry check failed — axis marked offline` toast.

## Exporting

Three exports, all writing plain files wherever you point the save dialog.

| Where | What | Files |
|---|---|---|
| **Report → Export** | One project: header, health, every axis, every finding | `codescry-<project>.md` or `.json` |
| **Portfolio → Export action list** | Cross-project priority list, ranked | `codescry-priorities.md` or `.json` |
| **Settings → Data & privacy → Export all data** | Everything (see below) | `codescry-export.json` |

Markdown is for reading and pasting into an issue tracker; JSON is for feeding other tools.

`codescry-export.json` contains an `exported_at` timestamp, your `settings` and configured
`root`, `reports` (every project with findings, health score and scan history), your `profile`
and your `favorite_ideas`. It's the version-controllable, greppable, diffable record — readable
without Codescry installed.

Two limits worth knowing:

- **There is no import.** Exports are for reading, archiving and feeding other tools. To put
  results back *into* Codescry, restore the folder ([below](#back-up-and-restore)).
- **Screenshots are not embedded** — the export references them; the images live in
  `screenshots/` inside the results folder.

## Idea generator

The second module. It reads a profile you write and proposes personal projects — on-device,
same model, same privacy.

### 1. About Me

Six steps, saved as you go, resumable anytime:

| Step | What it's for |
|---|---|
| **Skills** | Languages and frameworks, each with a level — beginner / comfortable / expert |
| **Interests** | Free-form; steers the flavor of the ideas |
| **Tools** | Hardware and tools you actually own — grounds ideas in what you can build with |
| **Goals** | Pick from a list, plus anything specific in your own words |
| **Time** | Hours per week you realistically have; ideas respect it |
| **Domains** | The areas you want ideas in — these become the idea categories |

Minimum to generate: **your skills and at least one domain**.

### 2. Generate

**Generate ideas** produces **9 ideas** spread across your domains, on your machine. Each card
carries a title, a pitch, a category (one of your stated domains), an **effort** tag and an
**impact** tag, plus which of your own tools and skills it draws on:

| Effort | Means |
|---|---|
| **S** | A weekend |
| **M** | A couple of weeks of spare time |
| **L** | A longer commitment |

Impact is **low / med / high**. Filter by domain, sort by effort or impact, and star anything
worth keeping.

These are personal projects for your own use — the generator is explicitly told never to pitch
markets, monetization, startups or customers.

### 3. Keep, refine, regenerate

- **★** on a card saves it to the favorites lane. **Generated ideas are ephemeral — only
  favorites persist.**
- **↻** on a single card replaces just that one with a fresh idea in the same category,
  different from everything already on screen.
- **↻ Re-generate** rebuilds the whole set: **Keep favorites** preserves your saved lane,
  **Fresh set** clears it too.
- **Refine profile** goes back to About Me. Better profile, better ideas — the model only
  knows what you told it.

If generation fails, your previous set is left untouched.

## Where your data lives

Every project, scan, finding, note and screenshot lives in one folder on your machine. There
is no account and no server copy, so **that folder is your only copy** — back it up like you
would any other document folder.

The results store is the app-data directory for the bundle id `org.helveticlabs.codescry`:

| OS | Path |
|---|---|
| Windows | `%APPDATA%\org.helveticlabs.codescry` — i.e. `C:\Users\<you>\AppData\Roaming\org.helveticlabs.codescry` |
| macOS | `~/Library/Application Support/org.helveticlabs.codescry` |
| Linux | `$XDG_DATA_HOME/org.helveticlabs.codescry`, defaulting to `~/.local/share/org.helveticlabs.codescry` |

The app shows the resolved path for your machine in **Settings → Data & privacy**, next to
"Results stored at". Copy it from there rather than typing the table above by hand.

What's inside:

| Item | What it is |
|---|---|
| `codescry.db` | SQLite database — roots, projects, scans, findings, resolve/snooze state, history, settings, About-Me profile, favorited ideas |
| `codescry.db-wal`, `codescry.db-shm` | SQLite write-ahead-log sidecars. Present while the app runs (and sometimes after). Part of the database — never copy `codescry.db` without them |
| `screenshots/` | UI screenshots you attached to projects, copied in so results are self-contained |
| `logs/` | Local crash log — `codescry.log` plus up to three rotated archives. One JSON line per uncaught UI error (message, stack, screen, app version), written for you to read; nothing is sent anywhere |

Nothing else on the system holds your results. Uninstalling Codescry removes the binary but
leaves this folder; deleting the folder removes every trace of your data — see
[Delete everything](#delete-everything) below, and [PRIVACY.md](../PRIVACY.md) for the full
footprint (including the webview cache the OS creates under the same bundle id, and the
model weights that belong to Ollama rather than to Codescry).

**Settings → Data & privacy → Clear results & history** wipes scan results, findings and
history while keeping your projects and settings.

## Back up and restore

### Back up

1. **Quit Codescry.** Copying the database while a scan is running can capture a half-written
   WAL. Closing the app checkpoints it cleanly.
2. **Copy the whole folder** to your backup location — external drive, another directory, a
   synced folder. Copy the directory itself, not selected files: the `-wal`/`-shm` sidecars and
   `screenshots/` are all part of one consistent snapshot.

```bash
# macOS
cp -R ~/Library/Application\ Support/org.helveticlabs.codescry ~/Backups/codescry-2026-09-03

# Linux
cp -R ~/.local/share/org.helveticlabs.codescry ~/Backups/codescry-2026-09-03
```

```powershell
# Windows (PowerShell)
Copy-Item -Recurse "$env:APPDATA\org.helveticlabs.codescry" "$HOME\Backups\codescry-2026-09-03"
```

Date-stamp the copies; the store has no built-in version history.

### Restore

1. Quit Codescry.
2. Move the current folder aside (rename it, don't delete it — that's your rollback).
3. Copy the backup folder into place under the exact path from the table above.
4. Relaunch. The app reopens the database it finds there; no import step.

### Restoring on a different machine or user account

This works, with one caveat: the database stores **absolute paths**. A project row remembers
`C:\Users\alice\code\my-app`, and each screenshot row points at the old `screenshots/` file
path. Restore onto a machine where those paths don't resolve and:

- projects still list, with their scores, findings and history intact,
- but their folders read as missing until you re-add the root at its new location, and
- screenshot thumbnails fail to load.

Also, "Results stored at" keeps the path string captured on the original machine — it is a
recorded setting, not a live lookup, and the app only fills it when empty. Cosmetic; the
database in use is always the one in the app-data directory.

So: same machine, same paths → a folder copy is a faithful restore. Different machine → expect
to re-point the scan root.

Practical setup: folder copy as the real backup, `codescry-export.json` alongside it as the
portable, human-readable record.

## Delete everything

Three levels, smallest first. [PRIVACY.md](../PRIVACY.md) has the exhaustive version, including
what each one leaves behind.

### 1. Clear results & history

**Settings → Data & privacy → "Clear results & history"** drops findings, scans, axis
results, dependency checks, screenshot records and health scores. Projects, the root folder,
your settings, the About Me profile and favorited ideas all survive, so the next run starts
from a known-empty slate without re-onboarding. The screenshot **image files** stay on disk
in `screenshots/` — the rows pointing at them are gone, the bytes are not.

### 2. Delete all local data & reset

**Settings → Data & privacy → "Delete all local data & reset"** empties every table *and*
deletes the `screenshots/` and `logs/` folders, then `VACUUM`s the database and truncates its
WAL so the freed pages stop holding readable content. The app drops back to onboarding with default
settings.

It refuses to run while a scan is in progress — cancel the run first. There is no undo and no
server copy, so export first if you want a record. Your project folders and files are never
touched by any of this; Codescry only ever reads them.

What survives: an empty `codescry.db` in the app-data folder, anything you exported yourself,
and the Ollama models (`~/.ollama`, or `%USERPROFILE%\.ollama` on Windows) — those are
Ollama's to remove, not Codescry's.

### 3. Remove Codescry completely

1. Quit Codescry.
2. Uninstall the app — Windows: Settings → Apps → Installed apps → Codescry.
   macOS: drag `Codescry.app` to the Trash. Linux: `sudo apt remove codescry`, or delete the
   `.AppImage`.
3. Delete the data directory (and the webview cache, if the uninstaller left one):

```bash
# macOS
rm -rf ~/Library/Application\ Support/org.helveticlabs.codescry
rm -rf ~/Library/WebKit/org.helveticlabs.codescry
rm -rf ~/Library/Caches/org.helveticlabs.codescry
rm -rf ~/Library/Saved\ Application\ State/org.helveticlabs.codescry.savedState

# Linux
rm -rf ~/.local/share/org.helveticlabs.codescry ~/.cache/org.helveticlabs.codescry
```

```powershell
# Windows (PowerShell)
Remove-Item -Recurse -Force "$env:APPDATA\org.helveticlabs.codescry"
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\org.helveticlabs.codescry"
```

4. Optionally `ollama rm <model>` and uninstall Ollama — gigabytes of weights that nothing
   else here touches.

Searching your home directory for `org.helveticlabs.codescry` afterwards should turn up
nothing but exports you saved yourself.

## Troubleshooting

**"The local model engine (Ollama) isn't running."** Start Ollama and retry. Codescry only ever
looks for it on `127.0.0.1:11434` — it will not reach out to a remote engine.

**Run button is disabled.** The model gate: no ready model, no scanning. **Settings →
On-device model** → download or select one, then **Test** to confirm.

**"Projects folder not found."** The root moved or the drive isn't mounted. **Relink folder**
on the dashboard.

**"No projects found here."** Codescry treats each *top-level subfolder* as a project. Either
you pointed it at a single project instead of the folder containing them, or your layout nests
one level deeper — raise **Scan depth** to 2 levels.

**An axis says "Analysis incomplete."** The model call failed or timed out on that project.
**Retry axis** — results for the other axes are already saved.

**The UI axis has no findings.** It needs a screenshot, and a vision-capable model
(`gemma3:4b`, `gemma3:12b`). With `qwen3:4b` or `llama3.2:3b` the axis can't run.

**Scans are slow.** Expected — a local model analyzing every project across every axis. Narrow
the scope in the run picker (one axis, or one project), turn off axes you don't care about, or
move to a smaller model.

---

Codescry is MIT-licensed. Source, issues and releases:
[github.com/makr07-sec/codescry](https://github.com/makr07-sec/codescry).
