A local-first workspace for Markdown notes, outlines, compilations, flashcards, and knowledge graphs, with a Pi agent beside your notes in local mode. Your content stays in Git; run the interface locally or deploy with Docker, Docker Compose, or Vercel.
Live Demo · Flashcard Demo · Example Workspace
Local-first tools keep files on your device; cloud-document tools give you a browser and multi-device experience. MyGitNotes points both ways of working at the same Markdown and Git workspace. There is no second cloud copy to export, import, or reconcile.
Markdown is the content source, Git records and publishes changes, and the repository owner controls credentials and access. A local checkout, Docker container, or Vercel deployment provides the interface and MCP endpoint; remote mode reads and writes the selected GitHub or GitLab repository.
One repository uses two branches in separate worktrees:
- core contains product source, packages, tests, scripts, and documentation.
- main contains workspace configuration, notebooks, assets, and workspace Agent settings.
Requires Node.js 22+, pnpm 9+, and Git 2.42+. Local mode needs no OAuth account.
git clone --branch core --single-branch https://github.com/wayne930242/MyGitNotes.git mygitnotes
cd mygitnotes
pnpm install
pnpm build # builds the packages the bootstrap script needs
pnpm bootstrap-workspace # creates the main worktree in ./workspace (ignored by Git), writes MYGITNOTES_LOCAL_PATH to .env, and sets up the upstream remote
pnpm devBootstrap renames the MyGitNotes remote from origin to upstream (or adds upstream when origin is already your repository), so origin can be your own repository while pnpm update-core keeps fetching Core from upstream. To keep your notes in your repository, create an empty one and push both branches:
git remote add origin <your-repository-url>
git push -u origin core mainOpen http://localhost:5173; the new workspace appears in the Notes view.
Already have a workspace? Instead of bootstrap, run from the Core checkout:
pnpm link-workspace "/absolute/path/to/workspace"
pnpm devlink-workspace validates the existing manifest and schema, then saves MYGITNOTES_SOURCE=local and the absolute MYGITNOTES_LOCAL_PATH in Core's .env, preserving unrelated settings.
It does not change notes or Git remotes, create worktrees, or migrate the workspace.
For an older schema, run pnpm migrate-workspace --workspace "/absolute/path/to/workspace" explicitly before linking; for a newer schema, update Core first.
An existing nonempty REPO_ROOT in .env follows the linked workspace too; an absent or empty value stays unchanged.
Shell environment settings still override .env.
pnpm dev:remote shares the same local workspace through Tailscale; it does not select a GitHub/GitLab source.
Both dev commands show link-workspace guidance if the workspace is missing.
The deployment guide covers each path step by step:
- Vercel through GitHub Actions sparse checkout (default), or through the Vercel Git integration
- Docker Compose or plain Docker with a remote repository, optionally behind a reverse proxy
- A local checkout inside a container
- GitLab as the note source
- GitHub Enterprise as the note source
- Private R2 assets
- The agent panel through Pi on your own computer (
npx mygitnotes-pi-bridge)
Run pnpm update-core from a clean core checkout; it fast-forwards core from upstream/core. Then pnpm install && pnpm dev. Hosted GitHub deployments that name their product repository (MYGITNOTES_PRODUCT_REPOSITORY) update from Settings. See Core updates and Update and migrate.
- Notes use ordinary Markdown with optional YAML frontmatter; Git preserves history and records explicit commits.
- Browse notes flat (every note under the selected folder, the default), by folder (one level with its subfolders), or on a Kanban board; the notes show as a table where the page has room and as cards where it is narrow (below 720px, such as beside the agent panel or on a phone). The toolbar's sort menu (an icon showing the current order) orders the list; its Group by folder button splits a list spanning subfolders into one group per folder, in the sidebar's folder order, with the sort applied within each group (off by default); clicking a folder's heading collapses its notes. The Notes page shows one notebook, picked in the header, and the sidebar selects one folder at a time; search full text, manage folders and files, and explore a knowledge graph, whose filters still take several folders and can span every notebook.
- In the sidebar, drag a folder to reorder it among its siblings or drop it into another folder (with a mouse at once, on touch after a long press), and drop a note from the note list or its cards on a folder or its notebook to move it there (on touch, long-press the note, then drag; letting go without moving selects it); its Move button picks a folder too. A move stops only when the notes it moves hold drafts, and names them; a single moved note takes its own draft along.
- The note toolbar starts with its view: one button switches live preview and source (its icon is the mode in use, in a graph card too; in zoom and in a Focus pane the leader
Mod+Shift+EthenMdoes the same, besideFfor find and/for the outline), beside the line numbers toggle; adding to an outline or Focus, the file actions and the panels follow. - Settings → Editor turns on Vim keys for this browser in live preview and the file source editor, with Vim's status line below the text; a note's source mode stays a plain text box.
:wdoes what the note's Commit does (Save in a note saved by hand),:qcloses a zoomed note, and:wqor:xcommits, then closes only if the commit succeeded. In normal mode Escape still closes the note's panel. The shortcut help (Mod+/) then lists the Vim keys as their own group, which filtering forvimshows whole. - Compilations organize notebook content and replace the old Screen lanes; Markdown pages can also become flashcards.
- Local mode offers a Pi agent in a dock on the right edge, and
pnpm dev:remoteopens the workspace from your other devices. - Choose from nine palette families, each with light and dark variants. Flexoki is the default; choices are saved in the browser.
- Connect local agents through stdio or remote agents through Streamable HTTP MCP with named read-only or write grants.
- The Files page manages notebook folders, notes, text files, and attachments: 3 MiB uploads, 5 MiB reads and changes, up to 200 changed files per operation.
A compilation is a <name>.compilation.yml file in a notebook, tracked and synced by Git like a note.
Its members are picked by hand (notes, folders, attachments or YouTube videos) or gathered dynamically by tag or folder.
Dynamic compilations sort by updated time, created time, title or status, or by your own order.
They display as a card row (thumbnail, small, medium), a book with a contents list, or a graph.
Click a card or a book section to edit its note in place; its title opens the note in zoom.
A book reads as one continuous scroll or one chapter at a time (Paged, with Previous/Next, ← and →, and swipes on a touch screen); the choice is kept in this browser, not in the file.
In a narrow pane or on a phone, the cards stack top to bottom.
A compilation also keeps study settings for reading and reviewing its members; see the study and flashcard guide.
The old Screen lanes are now compilations.
Running pnpm migrate-workspace on a schema 2 workspace turns each lane into a compilation and points Focus lane tabs at the new files.
Use New → New outline to create a named *.outline.md note, or Add to outline from a note or compilation to insert its link into an existing or new outline.
A notebook can contain multiple outlines; find them under Outlines and edit them in the normal live/raw note editor.
Items can contain text, multiple optional Markdown links, annotations and children.
Enter adds a sibling, Shift+Enter adds an annotation, and Tab/Shift+Tab indent or promote a subtree.
The live editor also supports same-document drag handles and one-step undo; toolbar indentation works without a hardware keyboard, and Escape then Tab leaves the editor.
Deleting an item does not delete linked content.
HTTP(S) links open explicitly with opener isolation, without preview fetching.
Outlines use normal note saves and Changes: local saves write the worktree; remote saves stage browser drafts until you commit. Managed moves update relative links together with the moved files, scoped to their repository. Read-only and recovery behavior follows the normal editor.
New → Import legacy bookmarks offers exact saved-source export and a read-only preview, including on read-only repositories. Choose the repository, notebook, new title/path and entry IDs explicitly. Note, compilation and safe web links can become outline items; old groups become text parents. Positions, queries and folders remain in the original source with their IDs, labels and reasons shown. Converting only the representable subset requires partial import acknowledgement. Apply creates a new file only: a local worktree file or one remote commit, as the preview states. Cancel writes nothing, and uncertain results require inspecting the original destination rather than automatic retry.
The original .mygitnotes-bookmarks.yaml is retained and protected; legacy editing and resolver endpoints are retired.
A workspace notice exposes pending browser envelopes from every configured repository, including unavailable repositories and malformed drafts.
Export preserves the exact envelope and its original base/revision; discard requires repository-specific confirmation and refuses a changed draft.
Legacy drafts never autosave, merge into saved source or enter normal Changes.
They remain a file-move blocker until explicitly discarded.
With Pi installed, local mode adds the assistant dock: a column on the right edge of the window, beside the right rail, a zoomed note, a zoomed compilation, a Focus and the Files page.
The agent button in the header and the one at the end of the editor toolbar open and close it; they are hidden when pi (or the command in MYGITNOTES_PI_COMMAND) is not found, and the header then offers the Agents page button in their place.
While the dock is offered, the Agents page opens from the dock's header.
Cmd+' on macOS (Ctrl+` elsewhere) from outside the dock opens it, focuses the message box and starts Pi if none runs; from the message box it returns to the editor the agent names, or closes the dock when no note is open.
- The dock is 380px wide by default. Drag its left edge, or focus the edge and press the arrow keys, to resize it between 320px and half the window; Expand switches to half the window, at most 760px. Whether it is open and how wide persist in the browser, and a zoomed note or compilation ends at the dock's left edge, so the two sit side by side. Below 768px the dock is a full-screen sheet with a close button.
pi --mode rpcstarts in the background when the workspace loads; after a page reload or apnpm devrestart, the dock resumes the same conversation.- Pi runs in an agent workspace: a folder with its own core instructions (
AGENTS.md) and skills (.agents/skills/), set up on the Agents page. It starts at the repository root; click the workspace name in the header to switch, which ends the current conversation. - MCP servers are configured in Pi itself (
pi mcp add, or/mcpin the chat), never in the repository. - Each message can name the open file. The context chip above the message box shows the target (
file:line, the path, or No file) and opens a menu: Line adds the caret line or selection, Path only adds just the path, and None adds nothing. Paths are relative to the folder Pi runs in. - Switch the model and thinking level from the selects in the message box's bottom row. Replies render as Markdown, links to notes open in the app, and questions Pi's extensions ask appear as cards in the conversation. Consecutive tool calls fold into one row (Ran 2 tools: bash, read) that opens onto the calls; it stays open while a tool runs or after one failed.
- When Pi changes a file on disk, the open editor updates at once. Unsaved edits are merged first; if they cannot be merged, the editor blocks and keeps your draft.
- Pi decides from
~/.pi/agent/trust.jsonwhether to load project settings. Buttons in the message box's top row, beside the context chip, open its trust decision, MCP servers and extension status.
Pi runs as your local user and can run any command, so the agent accepts only local connections; through pnpm dev:remote it admits only the Tailscale login that owns this machine.
See the security model.
pnpm dev:remote runs pnpm dev and shares it over HTTPS with Tailscale Serve, so a tablet or phone on the same tailnet can open it from another room.
It shares the same local workspace; it does not select a GitHub/GitLab source.
Other tailnet members can open the notes, while the Pi agent stays with the machine's owner; on a phone the dock takes the full screen.
If it does not connect, see Remote access with Tailscale below.
- Deployment guide
- Agent and developer documentation
- Architecture
- MCP interface and security model
- Demo workspace
- Study and flashcard guide
The community edition is licensed under AGPL-3.0. Contributions need the Contributor License Agreement; see CONTRIBUTING.md.
If startup reports a missing workspace, use pnpm link-workspace "/absolute/path/to/workspace" for existing notes.
Use pnpm bootstrap-workspace only when creating a workspace; it is not a repair command for an existing one.
A pnpm warning about its native executable, followed by successful fallback to the JavaScript CLI, is nonfatal.
If startup exits, check the subsequent error rather than treating that warning as the cause.
-
Same tailnet: the server and browsing device must join the same tailnet. WSL and Windows may run separate Tailscale clients signed into different accounts or tailnets; check both.
-
DNS /
DNS_PROBE_FINISHED_NXDOMAIN: enable Use Tailscale DNS settings on the browsing device. Browser Secure DNS may bypass the system resolver; check the browser's resolver settings (chrome://settings/securityin Chrome) so the tailnet hostname uses Tailscale DNS. Do not disable browser security globally. -
Browser permission: if a trusted site's browser prompt requests local-network access, choose Allow local access. If previously denied, review that site's local-network permission. This permission is separate from DNS resolution: granting it does not fix NXDOMAIN, and it is not Tailscale's exit-node LAN-access setting.
-
Serve activation /
node not found: ensure the browser's Tailscale admin console is signed into the server's tailnet. Check browser local-network permission only if prompted or blocked; it is not a proven universal cause of this message. In the correct tailnet, open DNS settings → HTTPS Certificates, following the official HTTPS instructions. -
Access denied: serve config deniedon Linux/WSL: an administrator can run the following once on the server to grant the current user local Tailscale management:sudo tailscale set --operator="$USER"
This grants Tailscale management privileges to that user; do not run the entire
pnpm devorpnpm dev:remotecommand with sudo. -
Lifecycle:
dev:remoteruns Serve in the foreground; keep the command running while using the remote page. After changing tailnets, stop and rerunpnpm dev:remote, then open the newly printed URL rather than an old bookmark.
