A local-first workspace for notes, tasks, and projects.
Website: copper.potion.sh
Copper brings Notes and Tasks into one desktop workspace. A Vault is any folder you choose. Notes, projects, and issues are Markdown files in that folder. There is no account and no cloud. The SQLite search index lives in app data, not inside your notes.
Browse notes, edit Markdown, and manage properties in one workspace.
Plan work in Tasks: find issues, set priorities, and keep projects close at hand.
Switch between project overview, issue list, and board. Move cards as work progresses.
Choose light and dark palettes, or follow your system appearance.
- mise, which selects the project’s pinned Node.js 24.22.0 and pnpm 12.14.0 versions automatically.
- Platform tooling for Electron:
- macOS: Xcode Command Line Tools (
xcode-select --install) - Linux: see docs/release/linux.md
- Windows: see docs/release/windows.md
- macOS: Xcode Command Line Tools (
Native module better-sqlite3 is rebuilt for Electron during mise run setup
(electron-builder install-app-deps).
One-time setup from the repository root:
mise trust
mise install
mise run setupThen start development:
mise run devmise.toml pins the tool versions and exposes the existing package scripts as
tasks. mise run selects those tools without requiring shell activation or a
manual Node/pnpm switch. Run mise tasks to see the available commands. CI uses
the same pinned versions. Both tool releases are more than two days old.
mise run dev opens the native Copper Dev window (Electron + Chromium). Vite serves the
renderer on http://localhost:1420. On macOS, mise run dev copies Electron into
apps/desktop/.copper-electron/ and stamps it with Copper Dev’s name and distinct icon. Development uses its own
app data and does not update or replace the installed Copper app. Use a separate
test Vault: opening the same folder in both apps still edits the same files. For the browser-only frontend, use
mise run dev:web.
Use Open Vault and pick any folder of Markdown files. A small demo vault
lives at apps/desktop/tests/fixtures/demo-vault if you want sample notes.
This is a pnpm + Turborepo monorepo:
apps/desktop: the existing Electron app, renderer, native tests, and packaging.apps/landing: the Astro site forcopper.potion.sh, with Tailwind CSS and shadcn/ui.docsandscripts: shared documentation, screenshots, and repository security checks.
mise run dev:landing # http://127.0.0.1:4321
mise run dev:desktop # native Copper app (also mise run dev)
mise run dev:all # both appsmise run build builds both apps without packaging or publishing.
mise run build:landing builds only the static site into apps/landing/dist;
mise run preview serves that build locally. mise run build:web still builds the
browser version of the desktop renderer.
The landing page is hosted on Vercel at copper.potion.sh.
The copper Vercel project connects to this repository with its root directory
left at the repository root. vercel.json installs only the landing workspace
with install scripts disabled, builds the site, and serves apps/landing/dist.
Pushes to main deploy the production site. This does not package or publish
the desktop app. Cloudflare manages the DNS-only CNAME for copper.
The landing page and README share the current Notes, Tasks list, project board,
and Appearance screenshots in docs/images. They show the real renderer with
demo data. To refresh them, start mise run dev:web --host 127.0.0.1 --port 1422,
then run bash scripts/capture-readme-screenshots.sh (requires agent-browser).
Edit copy and links in apps/landing/src/lib/site.ts. The reusable shadcn Button
is rendered as static HTML through Astro’s React integration; FAQ disclosure
uses native HTML and needs no client JavaScript. Setup follows the
shadcn Astro guide and
Tailwind Astro guide.
New dependencies are pinned to releases at least two days old. Turbo 2.11.3
is used because 2.11.4 had not reached that age when this change was made.
TypeScript 6.0.3 is the newest supported by Astro’s checker; TypeScript 7 is not
yet compatible. Existing desktop dependency versions are preserved. Astro’s
checker validates its templates; Biome checks their frontmatter and the other
source files.
Copper’s full file tree intentionally opens a fixed set of local formats:
- Markdown:
.md,.markdown(Live Preview or source) - Markdown/source:
.mdx(source only) - Plain text and tabular:
.txt,.text,.log,.csv,.tsv - Data and configuration:
.json,.jsonc,.yaml,.yml,.toml,.xml,.ini,.cfg,.conf - Web, code, and scripts:
.js,.jsx,.mjs,.cjs,.ts,.tsx,.css,.scss,.less,.html,.htm,.py,.rb,.rs,.go,.java,.kt,.kts,.c,.h,.cpp,.cc,.cxx,.hpp,.cs,.php,.sh,.bash,.zsh,.fish,.sql,.graphql,.gql,.vue,.svelte - Read-only raster images:
.png,.jpg,.jpeg,.gif,.webp,.bmp
Extension matching is case-insensitive. An extensionless regular file is shown only when its complete contents are valid UTF-8, contain no NUL byte, and fit the size limit. Supported text is validated as UTF-8 when opened; image content must match its extension’s binary signature. Text and image reads are limited to 25 MiB and canonically contained inside the active Vault. SVG, PDF, audio, video, executables, archives, office documents, non-UTF-8 text, hidden entries, and other arbitrary binaries are not opened.
Opening, previewing, switching, or closing a supported file without an actual CodeMirror document edit does not save, normalize, reformat, or change its bytes or modified time. Edited UTF-8 text uses Copper’s atomic replacement path. Images are read-only. Search, backlinks, Properties, favorites, and the disposable SQLite index remain Markdown-only.
Choose Editor settings… from a note’s three-dot menu, or open Settings → Editor, to change the font face, size, and line spacing for all notes. Inter, Lora, and JetBrains Mono are bundled for offline use; system sans, Georgia, and system mono are also available with platform fallbacks. These preferences stay in Copper’s app data and do not change your Markdown files.
New notes start with an empty body; Copper does not insert a duplicate title heading. Click the title above the editor to rename the file, press Enter to save, or Escape to cancel. The file extension is preserved. Existing Markdown headings stay in your content. Right-click notes in the list or Pinned section to open a tab, rename, archive, or move them to Trash. File and folder naming uses app dialogs, including in the folder tree.
Archive/ at the Vault root is reserved and hidden from the tree. Archive
moves a Markdown note to Archive/<original-relative-path> in the same Vault;
Restore from Archive removes that prefix. Neither operation overwrites an
existing destination. Archived Markdown is omitted from All Notes, favorites,
quick open, and ordinary search, and is available through the Archive view.
Tasks use lowercase .copper/tasks/issues/ and .copper/tasks/projects/ inside
the Vault. Their Markdown source stays in Git, while Copper hides it from the
Notes folder tree, All Notes, favorites, and ordinary note search. Choose
Edit source from an issue or project’s right-click menu, or its detail header,
to open the full Markdown in an editor tab. Open in Tasks returns to its task
view. Source edits update Tasks through the same file watcher and index.
Copper moves recognized legacy files from Tasks/Issues/, Tasks/Projects/,
and their archived equivalents when opening a Vault. IDs, metadata, and note
references are preserved; ordinary notes in those folders stay where they are.
Conflicting files are never overwritten. Task archives use
.copper/tasks/archive/issues/ and .copper/tasks/archive/projects/. The hidden
folder holds portable task sources; the SQLite index and app preferences stay
in app data. Copper does not add .copper to .gitignore.
Tasks mode uses a compact task navigation pane and one full-width issue canvas.
It includes All issues, user-managed Pinned and Projects navigation, project
Overview, Issues, and Board tabs, searchable and filterable issue lists, and
pointer- plus keyboard-accessible kanban movement. Set statuses, priorities,
labels, and due dates; customize a project’s workflow; and keep multiple task
tabs open alongside your notes. Issue and project
forms reuse compact property controls, native date fields, and dismissible
detail sheets. Failed writes keep the current draft or restore the optimistic
board order so the user can retry. These views still read and write only the
same type: issue and type: project Markdown frontmatter described above;
saved views, dependencies, milestones, and note-checkbox ingestion remain
separately scoped in tasks-advanced-workflows.
Move to Trash… sends a confirmed file or folder to the operating system’s Trash/Recycle Bin after an in-Vault path check. Copper never falls back to permanent deletion when that operation fails. Recovery is handled through the operating system.
These are the same three steps GitHub Actions runs:
mise run test
mise run typecheck
mise run lintmise run lint and mise run format use Biome. Use mise run test (Vitest), not a separate test runner.
Or run them together:
mise run checkDownload installers from GitHub Releases. See the installation guide for macOS, Windows, and Linux. The app version is 0.2.2. Public macOS installers support Apple Silicon only and are Developer ID signed and Apple-notarized, with in-app updates. Windows installers remain unsigned; Windows and Linux updates use the latest installer. The maintainer process is in docs/release/github.md.
mise run setup
mise run packageThis produces local test artifacts under apps/desktop/release/ and never publishes them.
Public releases follow the approved installer policy and checks in
SECURITY.md and docs/release/github.md.
Outstanding work and release prerequisites are tracked in TODO.md.
Copper is licensed under the GNU Affero General Public License v3.0.



