|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project |
| 6 | + |
| 7 | +VS Code extension (`pajoma.vscode-journal`) for daily markdown journaling. TypeScript, bundled with esbuild, runs in the workspace extension host. Requires Node 20+ and VS Code 1.118+. |
| 8 | + |
| 9 | +## Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +npm install |
| 13 | +npm run compile # esbuild → dist/extension.js (CJS, external 'vscode') |
| 14 | +npm run watch # esbuild watch (used as preLaunchTask for F5) |
| 15 | +npm run package # production build (minified, no sourcemap) |
| 16 | +npm run compile-tests # tsc -p . --outDir out (separate from extension bundle) |
| 17 | +npm run lint # eslint src |
| 18 | +npm test # @vscode/test-cli — pretest auto-runs compile-tests + compile + lint |
| 19 | +npm run check # lint + compile + test |
| 20 | +``` |
| 21 | + |
| 22 | +Run a single test by passing a Mocha grep through `@vscode/test-cli`: |
| 23 | + |
| 24 | +```bash |
| 25 | +npm test -- --grep "MatchInput" |
| 26 | +``` |
| 27 | + |
| 28 | +Tests live in `src/test/suite/**/*.test.ts`, compile to `out/test/suite/**/*.test.js`, and run inside a real Extension Host against the workspace `test/ws_unittests/`. Mocha TDD UI, 20s default timeout (`.vscode-test.mjs`). `src/test/direct/` contains plain-node debug scripts, not part of the suite. |
| 29 | + |
| 30 | +Launch configs (`.vscode/launch.json`): |
| 31 | +- **Run Extension** — opens Extension Development Host on `test/ws_manual/` (default F5) |
| 32 | +- **Run Extension without Workspace** — uses `test/ws_empty/` |
| 33 | +- **Extension Tests** — runs the suite with `watch-tests` as pre-launch |
| 34 | + |
| 35 | +CI (`.github/workflows/ci.yml`) runs lint → compile → compile-tests → `xvfb-run npm test` on push to `main`/`master`/`develop` and on PRs. |
| 36 | + |
| 37 | +## Architecture |
| 38 | + |
| 39 | +Entry: `src/extension.ts` → `Startup(config).run(context)` (in `src/ext/startup.ts`) which initializes the `Ctrl` service locator and registers commands, code actions, and optional syntax highlighting. |
| 40 | + |
| 41 | +**Service locator pattern.** `Ctrl` (`src/util/controller.ts`) owns one instance each of `Configuration`, `Parser`, `Writer`, `Reader`, `Inject`, `Dialogues`, and `Logger`. Every command/provider receives `Ctrl` in its constructor and reaches services through it. PLAN.md Phase 2.1 marks this for replacement with proper DI — new code should be written so it can accept narrower interfaces later, not lean harder on `Ctrl`. |
| 42 | + |
| 43 | +**Namespace barrel imports.** `src/index.ts` re-exports submodules as `J.Extension`, `J.Actions`, `J.Model`, `J.Util`, `J.Provider`. Existing code does `import * as J from '..'` and references `J.Util.Ctrl`, `J.Actions.Writer`, etc. PLAN.md Phase 2.3 marks this for replacement with named imports — prefer named imports in new files. |
| 44 | + |
| 45 | +**Module responsibilities** (need multiple files to grasp): |
| 46 | + |
| 47 | +- `src/ext/` — VS Code surface integration. `Configuration` (`conf.ts`) reads `journal.*` settings and resolves templates/scopes. `Dialogues` drives QuickPick/InputBox. `Startup` wires everything. i18n uses `vscode.l10n` — manifest strings in `package.nls*.json` at the repo root, runtime strings in `l10n/bundle.l10n*.json` (regenerated via `npm run l10n:export`). |
| 48 | +- `src/actions/` — Core domain logic, no direct command bindings. |
| 49 | + - `Parser` — turns user input/URIs into structured `Input` (date, note, memo, task, weekly). |
| 50 | + - `Reader` — loads entries/notes from the configured base directory using `vscode.workspace.fs`. |
| 51 | + - `Writer` — creates new files (entry, note, weekly) and opens text documents. |
| 52 | + - `Inject` — modifies existing documents (insert memo/task/file link, shift task). |
| 53 | +- `src/model/` — Plain data types: `Input`, `FileEntry`, `HeaderTemplate`/`InlineTemplate`/`ScopedTemplate`, scope/quickpick types. |
| 54 | +- `src/provider/` — VS Code-facing surface. |
| 55 | + - `commands/` — one file per registered command (`journal.today`, `journal.note`, `journal.printDuration`, etc.); each exports a static `create(ctrl)` that returns the `Disposable`. |
| 56 | + - `codeactions/` — markdown code actions for completed and open task lines. |
| 57 | + - `codelens/` — task migration/shift CodeLens providers (not all registered yet — see `Startup.registerCodeLens`). |
| 58 | + - `features/` — reusable building blocks: `MatchInput` (smart-input resolver), `ScanEntries` (directory walker + cache for QuickPick), `LoadNotes`, `SyncNoteLinks`. |
| 59 | +- `src/util/` — `Ctrl`, `Logger` (OutputChannel-backed), `dates.ts` (moment-based, slated for removal in Phase 3), `paths.ts`, `strings.ts`. |
| 60 | + |
| 61 | +**Smart-input flow.** User triggers `journal.day` (`Ctrl+Shift+J`) → `Dialogues` shows InputBox → `MatchInput.parseInput()` classifies the text (date expression, weekday, "memo:", "task:", "note ...", week reference) → command dispatches to `Reader`/`Writer`/`Inject`. The default path/file patterns (`${base}/${year}/${month}/${day}` for notes, `${base}/${year}/${month}/${day}.${ext}` for entries) come from `journal.patterns` in `package.json`. |
| 62 | + |
| 63 | +**Filesystem.** Always go through `vscode.workspace.fs` (the extension declares `extensionKind: ["workspace"]` so it runs on the remote host for Remote SSH/Codespaces). Avoid raw `fs` / `fs.promises` in new code — PLAN.md Phase 1.3 finished migrating the old `fs` call sites; do not reintroduce them. |
| 64 | + |
| 65 | +**Templates.** All user-facing inserted content comes from `journal.templates` (array of `{name, template, after?}`). Lookup happens via `Configuration.getInlineTemplate(name, fallback)`. Default template names: `memo`, `task`, `entry`, `time`, `note`, `files`, `weekly`. Issue #167 was a name-mismatch bug (`week` vs `weekly`) — when adding a new template type, register the name consistently in `package.json` defaults and the consumer. |
| 66 | + |
| 67 | +## Notes for changes |
| 68 | + |
| 69 | +- `PLAN.md` is the active modernization roadmap. Phases 0 and 1 are complete; Phase 2+ is open. Match the direction in the plan (DI, named imports, native `async`/`await` instead of `new Promise()` wrappers, `vscode.workspace.fs`, replacing moment with `Intl`/`date-fns`). |
| 70 | +- ESLint flat config (`eslint.config.mjs`) enforces `curly`, `eqeqeq`, `no-throw-literal`, `semi`. Import naming must be `camelCase` or `PascalCase`. |
| 71 | +- `tsconfig.json` runs `strict`, `noImplicitReturns`, `noFallthroughCasesInSwitch`. The bundle goes through esbuild, but tests are compiled via `tsc` — both must succeed for `npm test`. |
| 72 | +- `docs/` contains user-facing feature docs (entries, notes, memos, tasks, scopes, settings, codeactions) and `docs/analysis/` holds the analysis that produced `PLAN.md`. |
0 commit comments