Skip to content

Latest commit

 

History

History
269 lines (191 loc) · 7.57 KB

File metadata and controls

269 lines (191 loc) · 7.57 KB

Contributing to NeverWrite

Thanks for your interest in contributing to NeverWrite. This guide covers everything you need to get started.

Prerequisites

Tool Version Notes
Node.js 22+ Required for desktop app and CI
npm 11+ Package manager for apps/desktop
pnpm 10.33+ Package manager for apps/web-clipper
Rust 1.96.0 Pinned by rust-toolchain.toml; Edition 2021 across all crates

Platform-specific

  • macOS: Xcode Command Line Tools (xcode-select --install)
  • Windows: MSVC Build Tools, WebView2
  • Linux: Standard build essentials for Rust and Electron packaging (build-essential, pkg-config, curl, wget)

Repository structure

apps/
  desktop/            Electron + React desktop app (npm)
  web-clipper/        WXT browser extension (pnpm)
crates/
  types/              Shared DTOs and domain models
  vault/              Vault scanning, parsing, filesystem watching
  index/              Search, link resolution, indexing
  diff/               Diff engine + WASM bindings
  ai/                 Shared AI domain types
vendor/               Vendored ACP runtimes
scripts/              Automation utilities

Getting started

Desktop app

cd apps/desktop
npm install

# Frontend only (Vite dev server)
npm run renderer:dev

# Full Electron app with Rust sidecar
npm run dev

Web clipper

cd apps/web-clipper
pnpm install
pnpm dev

Rust workspace

# From the repo root
cargo build
cargo test

Development workflow

1. Fork and clone

git clone <your-fork-url>
cd <your-clone-directory>

2. Create a branch

git checkout -b my-change

3. Make your changes

Follow the code style guidelines below, then verify:

# Desktop
cd apps/desktop
npm run lint          # ESLint
npm run build         # TypeScript check (tsc -b) + Vite build
npm test              # Vitest

# Web clipper
cd apps/web-clipper
pnpm run check        # TypeScript + tests + build (all-in-one)

# Rust
cargo test

4. Commit and push

git add <files>
git commit -m "fix(editor): resolve cursor jump on live preview toggle"
git push origin my-change

5. Open a pull request

Open a PR against main. Describe what changed and why. Link related issues if applicable.

Commit messages

We use a lightweight conventional format:

type(scope): short description

Types: fix, feat, refactor, chore, docs, test, perf

Scope is optional but encouraged for targeted changes (e.g., editor, vault, clipper, ai).

Examples:

fix(editor): resolve cursor jump on live preview toggle
feat(clipper): add selection-only clipping mode
refactor: simplify change rail review projection
chore: clean up pdf tab view zoom handling

Keep messages descriptive and action-focused. Write in lowercase unless starting with a proper noun.

Code style

TypeScript

  • Strict mode is enabled (strict: true, noUnusedLocals, noUnusedParameters)
  • Use import type for type-only imports (verbatimModuleSyntax is enforced)
  • Prefix unused parameters with _
  • ESLint with TypeScript strict rules — run npm run lint before committing

React

  • Functional components only
  • Zustand for state management — stores live in app/store/
  • Feature code goes in features/<feature-name>/
  • Shared components go in components/

Rust

  • Default rustfmt formatting
  • Edition 2021
  • Use cargo clippy for additional lint checks

General principles

  • Simplicity first — the simplest solution that works
  • Fix root causes — don't patch around broken abstractions
  • Bounded refactors — if a fix requires restructuring, keep it scoped to the affected module
  • No speculative cleanup — don't refactor code that your change doesn't touch

Testing

Frontend (Vitest + Testing Library)

# Desktop
cd apps/desktop
npm test              # Run once
npm run test:watch    # Watch mode

# Web clipper
cd apps/web-clipper
pnpm test             # Watch mode
pnpm test:run         # Run once
  • Test files live next to the code they test: MyComponent.test.tsx
  • Use describe(), it(), expect() from Vitest
  • Use Testing Library for component tests (@testing-library/react)
  • Mock desktop runtime APIs through @neverwrite/runtime helpers and vi.mocked()

Rust (cargo)

cargo test                          # All workspace tests
cargo test -p neverwrite-vault      # Single crate

Architecture notes

Frontend stack

  • React 19 + TypeScript + Vite
  • Tailwind CSS 4 — utility-first styling with CSS variables for theming
  • CodeMirror 6 — markdown editor with custom extensions (live preview, change tracking)
  • Zustand — lightweight state management with per-feature stores

Backend

  • Electron — desktop shell and IPC bridge
  • Tokio — async runtime
  • notify — filesystem watching
  • Node HTTP server — local desktop API for web clipper communication (127.0.0.1:32145)

Key patterns

  • Feature modules: each feature in features/ owns its components, hooks, and store slices
  • ActionLog: patch-based change tracking with author attribution (user vs AI)
  • Live preview: CodeMirror ViewPlugin that hides markdown syntax when the cursor is elsewhere
  • Wikilinks: parsed from markdown, resolved against the vault index for navigation and backlinks

Environment variables

For development, these optional variables can override default runtime paths:

Variable Purpose
NEVERWRITE_CODEX_ACP_BIN Override Codex ACP runtime binary
NEVERWRITE_CLAUDE_ACP_BIN Override Claude ACP runtime binary
NEVERWRITE_KILO_ACP_BIN Override Kilo ACP runtime binary
NEVERWRITE_WEB_CLIPPER_DEV_ORIGINS Allow unpacked extension origins

Versioning

We follow Semantic Versioning. During the 0.x phase, minor bumps may include breaking changes.

Versions are kept in sync across:

  • apps/desktop/package.json
  • apps/desktop/package-lock.json
  • apps/desktop/native-backend/Cargo.toml
  • apps/web-clipper/package.json
  • CHANGELOG.md

Use scripts/bump-version.sh to update the package, native backend, and Web Clipper version files at once, then add the matching CHANGELOG.md release entry. Before creating a release tag, run:

node scripts/validate-release-metadata.mjs --tag vX.Y.Z

Release automation

Desktop releases are maintainer-driven and run through the Electron release workflow in GitHub Actions. The same workflow validates and attaches the Web Clipper Chrome and Firefox MV3 zip artifacts to the GitHub Release.

Before triggering .github/workflows/release-desktop.yml:

  • Bump the desktop version sources with scripts/bump-version.sh X.Y.Z
  • Add or update the matching CHANGELOG.md entry
  • Run node scripts/validate-release-metadata.mjs --tag vX.Y.Z
  • Create and push the release tag, for example v0.2.1
  • Ensure the required signing secrets are configured in the GitHub repository settings
  • Review the Electron release topology and signing requirements documented in release/appcast/README.md

Reporting issues

  • Search the existing issue tracker before opening a new one
  • Include steps to reproduce, expected behavior, and actual behavior
  • For crashes, include the OS version and any relevant logs

License

By contributing, you agree that your contributions will be licensed under the Apache-2.0 License.