# Contributing Issues, pull requests, bug reports, and documentation fixes are welcome. ## Before you start - Search existing issues and pull requests before starting a large change. - Keep changes focused. Add tests for behavior that can regress. - Never commit credentials, customer configuration, meeting content, or other private data. - Use [docs.anarlog.so](https://docs.anarlog.so) for product, CLI, and MCP behavior. Use this file and the repository's `AGENTS.md` files for development guidance. ## Set up the repository You need: - Node.js 22 or later - pnpm 11.1.1 - Rust 1.94.0 - [process-compose](https://f1bonacc1.github.io/process-compose/installation/) 1.122.0 or later (`brew install process-compose` on macOS) - The [Tauri v2 system dependencies](https://v2.tauri.app/start/prerequisites/) - On Apple Silicon Macs, Xcode with its Metal Toolchain component. The Command Line Tools alone cannot compile the MLX shader library used by Soniqo local transcription. Xcode 26 and later install the component separately with `DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcodebuild -downloadComponent MetalToolchain`; Xcode does not need to be selected with `xcode-select`. On Debian or Ubuntu, install the supported toolchains and system packages with: ```bash bash scripts/setup-linux.sh ``` Then install the workspace: ```bash pnpm install --frozen-lockfile ``` The desktop app and website start without secrets for local-first workflows. ## Run the apps ```bash # Tauri desktop app pnpm dev:desktop # Website pnpm dev:web ``` Process Compose manages the processes and logs. It runs the shared UI build through Turbo before starting either app. The existing `pnpm exec turbo dev:desktop` and `pnpm exec turbo dev:web` commands also work. On macOS, install and select the full Xcode application, including its Metal toolchain (`xcodebuild -downloadComponent MetalToolchain`). Command Line Tools alone cannot build the on-device transcription dependencies. If the checkout path contains spaces, set `CARGO_TARGET_DIR` to a path without spaces before starting the desktop app; some native dependencies use Autotools, which rejects build directories containing spaces. For the combined desktop, web, API, and local Supabase stack: ```bash pnpm dev # Only local Supabase and the API pnpm dev:api ``` These commands require Docker and [Task](https://taskfile.dev/installation/) (`brew install go-task` on macOS), plus the API configuration described in [apps/api/AGENTS.md](apps/api/AGENTS.md). The Linux setup installs Task and process-compose. The combined stack runs `task supabase-start` to prepare local Supabase and `.env.supabase`, waits for API readiness, then starts web and desktop. Package `.env` files are still loaded by the apps; Process Compose does not inject the root `.env` into every process. Provider credentials and service-specific configuration are not required for `pnpm dev:desktop` or `pnpm dev:web`. The underlying `task supabase-start` and `cargo run -p api` commands remain available. Supabase's Docker containers persist when Process Compose exits; stop them explicitly with `task supabase-stop`. Use the Process Compose TUI to view logs or restart individual processes. Logs are also written under `.process-compose//`, with rotation; set `PC_LOG_DIR` to override that directory. The launcher disables the TUI automatically without a terminal, or you can set `PC_DISABLE_TUI=1`. The control ports are 18080 for `pnpm dev`, 18081 for desktop, 18082 for web, and 18083 for API. Set `PC_PORT_NUM` to override a control port; app ports remain 1422 (desktop Vite), 3000 (web), and 3001 (API). Stop other apps using those app ports before starting the same services here. ```bash # Validate configuration without starting apps pnpm dev --dry-run # Start web without the TUI and restart it from another terminal pnpm dev:web -t=false process-compose -p 18082 process restart web process-compose -p 18082 down ``` ### Develop the Google Drive automation Run the desktop, web (`:3000`), and API (`:3001`) development commands above in separate terminals. Configure the existing Nango `google-drive` integration with `https://www.googleapis.com/auth/drive.file` and the team's development OAuth client. Enable the Google Drive and Google Picker APIs in that client's Google Cloud project. Existing connections with broader scopes must be reauthorized. To test hosted transcription and summaries while keeping Drive requests local, set `VITE_API_URL=http://localhost:3001` and `VITE_AI_API_URL=https://api.anarlog.so` in `apps/desktop/.env`, then restart the desktop dev process. This requires an account and Pro entitlement accepted by the hosted service. The local API can remain `ANARLOG_SERVICE=core`. Omitting `VITE_AI_API_URL` keeps AI requests on `VITE_API_URL`. Explicit provider base URL settings still take precedence. Audio and summary requests use the hosted service and its normal usage limits. Set `GOOGLE_DRIVE_PICKER_REDIRECT_URI` in `apps/api/.env` to `http://localhost:3000/app/google-drive-picker` for local development. Register that exact URI on the **same Google OAuth client configured in Nango**, in its authorized redirect URIs. Keep Nango's existing callback URI as well. Production must use the deployed web origin with HTTPS and this same route path. Folder selection opens Google's OAuth page directly using `trigger_onepick` and `drive.file`; it does not embed the JavaScript Picker. No Picker API key or `VITE_GOOGLE_DRIVE_PICKER_*` variables are needed. The API obtains the OAuth client credentials from Nango, validates signed user-bound state and PKCE, checks that the selected Google account matches the existing connection, and imports the new credentials into that same Nango connection. The Nango API key must permit reading integration credentials and importing connections. The web page uses same-tab session storage only for return routing, clears the OAuth code from the URL before telemetry, and hands it to the authenticated desktop for API completion. Access and refresh tokens stay on the server. Restart selection from the desktop if the callback tab is refreshed or closed. Nango's new-connection webhook still needs a reachable local tunnel; the direct folder-selection callback goes to the web app and does not use that tunnel. Validate with a test My Drive folder and a test shared-drive folder. Verify folder selection, a first upload, an update after regenerating a summary, and a failed upload retry. Deploy the API and web support before distributing a desktop build that exposes the action. ## Find the right code | Path | Scope | | ---------------- | ------------------------------------------------------- | | `apps/desktop` | React desktop UI and Tauri application | | `apps/web` | Marketing site, account portal, and shared-note pages | | `apps/api` | Hosted API routes | | `apps/cli` | CLI and MCP server | | `apps/mobile` | Expo mobile client | | `plugins/*` | Tauri plugin boundaries | | `crates/*` | Rust libraries and services | | `packages/*` | Shared TypeScript packages | | `crates/db-app` | SQLite schema and migrations | | `supabase` | Hosted database schema, functions, and tests | | `skills/anarlog` | Published CLI and MCP agent skill | | `enterprise` | Commercially licensed capture and deployment components | | `docs` | Mintlify product and reference documentation | Sessions are the core data entity. Notes, transcripts, and summaries are all backed by sessions. ProseMirror documents use the TipTap JSON dialect. ## Validate your change Always format before committing: ```bash pnpm exec dprint fmt pnpm fmt:check ``` On Linux, the full format check cannot run the macOS-only Swift formatter. Run a scoped dprint check for every changed non-Swift path and report the skipped Swift check. Run checks for every package you changed. Common commands include: ```bash # Desktop TypeScript pnpm -F desktop typecheck pnpm -F desktop test pnpm exec oxlint --quiet --format=github apps/desktop/src/ # Changes spanning TypeScript packages pnpm -r typecheck # Rust cargo check cargo test -p ``` For documentation changes: ```bash pnpm exec dprint fmt 'docs/**/*' pnpm exec dprint check 'docs/**/*' cd docs mint validate mint broken-links --check-anchors --check-redirects ``` Check the affected workflow under `.github/workflows/` for stricter package-specific commands. ## Open a pull request - Write the title as a specific action that states the intended outcome. Do not use a file name, ticket number, or a generic label as the title. - Write one or two sentences on the labeled `Intent` line: what problem you saw, and what this change should do instead. Cubic already summarizes the code diff, so do not paste a generated commit log, a file-by-file recap, or a long write-up: keep it short. - Attach a short screen recording or GIF in the `Demo` section showing the problem and the fix in action. This, plus the one-line intent, is what lets a maintainer understand a contribution without reading a wall of text. Docs-only or non-functional changes can skip the video by writing `N/A` and a one-line reason. - List the commands and manual checks you used to verify the change. - CI enforces the title, the labeled `Intent` line, and the `Demo` section for external contributors. Org members, collaborators, owners, and bots are not gated. ## Licensing and contribution boundary By submitting a contribution outside `enterprise/`, you agree that it may be distributed under the repository's [MIT License](LICENSE). Only submit material you have the right to license this way. Do not submit changes under `enterprise/` unless Fastrepl has confirmed the applicable contribution terms in writing. Never include customer configuration, credentials, confidential material, or untracked third-party code. Record the immutable upstream revision and license before reusing third-party material. See [Licensing and product boundary](LICENSING.md) for the component-placement and provenance rules.