{
  "markdown": "# Apple Notes Snapshot\n\nApple Notes Snapshot is the backup control room for Apple Notes on\nmacOS. Keep the upstream `notes-exporter` engine, then add path-aware exports,\n`launchd` scheduling, visible health checks, and a calmer recovery path when\nthe local backup loop drifts.\n\n> 🤝 **Sister repo**: looking to recover deleted notes after the fact, not back them up beforehand? See [**notes-recover**](https://github.com/xiaojiou176-open/notes-recover) — the forensic-grade reader for Apple Notes' `NoteStore.sqlite` (recover deleted notes, browse the raw store, ship audit-ready bundles). `notebackup` covers the *before*; `notes-recover` covers the *after*. Together they cover the full Apple Notes lifecycle on macOS.\n\nAfter the control room already makes sense, the repo also ships extra builder\nand diagnostics surfaces so humans and coding agents can inspect the same\nbackup state without turning the workflow into a hosted service.\n\n[Start the 3-step quickstart](https://xiaojiou176-open.github.io/apple-notes-snapshot/quickstart/) |\n[First-run troubleshooting](https://xiaojiou176-open.github.io/apple-notes-snapshot/troubleshooting/) |\n[Open the proof page](https://xiaojiou176-open.github.io/apple-notes-snapshot/proof/) |\n[Compare with upstream](https://xiaojiou176-open.github.io/apple-notes-snapshot/compare/) |\n[Browse release history](https://xiaojiou176-open.github.io/apple-notes-snapshot/releases/) |\n[Get support or routing help](https://xiaojiou176-open.github.io/apple-notes-snapshot/support/)\n\n[![Trusted CI](https://github.com/xiaojiou176-open/apple-notes-snapshot/actions/workflows/trusted-ci.yml/badge.svg)](https://github.com/xiaojiou176-open/apple-notes-snapshot/actions/workflows/trusted-ci.yml)\n[![Latest Release](https://img.shields.io/github/v/release/xiaojiou176-open/apple-notes-snapshot?display_name=tag&color=1d4ed8)](https://github.com/xiaojiou176-open/apple-notes-snapshot/releases)\n[![macOS only](https://img.shields.io/badge/platform-macOS-111827?logo=apple)](https://support.apple.com/macos)\n\n![Apple Notes Snapshot Web console showing run health, scheduler status, and quick actions](./assets/readme/hero-console.png)\n\n- **Keep the path obvious**\n  Review or override the export destination before the first snapshot writes.\n- **Turn one-off exports into a local loop**\n  Use `launchd` to schedule repeatable snapshots instead of babysitting manual exports.\n- **See health before you guess**\n  Check freshness, failure reasons, logs, and recovery clues when the loop drifts.\n- **Read the next safe move first**\n  The Web console now surfaces an operator focus deck above the raw transcript so you can see the next move, the reason, and the reading order before diving into action output.\n\n> Category: Apple Notes backup control room.\n> AI/agent hook: AI-assisted diagnostics plus optional coding-agent access once the operator workflow is already clear.\n> Result: a calmer, more reviewable backup workflow on your own Mac.\n\n> Best fit: people who already rely on Apple Notes and want a calmer,\n> reviewable backup routine on their own Mac.\n>\n> Not the goal: cloud sync, team collaboration, or two-way write-back into\n> Apple Notes.\n\n## At A Glance\n\nIf you only want the shortest truthful filter before reading deeper, use this\ntable first:\n\n| What you need to know | Current answer |\n| --- | --- |\n| Product thesis | an Apple Notes backup control room for macOS |\n| First success | `./notesctl run --no-status` -> `./notesctl install --minutes 30 --load` -> `./notesctl verify` |\n| First proof surface | the proof page after one healthy local loop exists |\n| Second ring only | AI Diagnose, Local Web API, and MCP come after the operator path already makes sense |\n| What it must never be reduced to | a hosted Notes service, cloud sync product, or generic AI dashboard |\n\n### What you can prove in one local pass\n\n- **The destination is obvious**: you can review or override the snapshot path before anything writes.\n- **The loop is real**: one manual run plus `launchd` turns a one-off export into a repeatable local rhythm.\n- **The control room is inspectable**: `status`, `verify`, `doctor`, logs, and proof pages all stay on the same local facts.\n- **Integration surfaces are optional**: AI Diagnose, the Local Web API, and MCP all stay behind the operator story instead of replacing it.\n\nIf you want the shortest public evidence trail after that first pass, open the\n[proof page](https://xiaojiou176-open.github.io/apple-notes-snapshot/proof/).\nIt collects the repo-owned gates, the GitHub-controlled release and Pages\nevidence, and the current access boundary in one place.\n\n## Start with Run -> Install -> Verify\n\nTreat the first healthy loop like a three-stop checklist, not like a dashboard\nto decode all at once.\n\n1. **Run**\n   Use `./notesctl run --no-status` once so macOS can surface permissions and\n   the local ledger can record a first successful baseline.\n2. **Install**\n   Use `./notesctl install --minutes 30 --load` after that first run so the\n   workflow becomes a repeatable `launchd` loop instead of a manual chore.\n3. **Verify**\n   Use `./notesctl verify` first, then `./notesctl doctor` only if warnings or\n   empty state remain.\n\nAfter that verified loop exists, the Web console, proof page, AI Diagnose,\nLocal Web API, and MCP surfaces become much easier to read because they are all\ndescribing a baseline you already proved.\n\n## Integration and maintainer routes after the operator path\n\nThe public product front door is still the local backup control room. The lanes\nbelow are for builders after the first healthy loop exists; they do not replace\n`Run -> Install -> Verify`.\n\n- **Public product front door: backup control room**\n  - the main story is still the local path review, the first snapshot run, the\n    `launchd` loop, and the health check surface on your own Mac\n- **Second ring builder protocol lane: pure MCP**\n  - the repo's main machine-facing surface is the local stdio MCP flow behind\n    `./notesctl mcp` and the root [`server.json`](./server.json)\n- **Second ring builder packet lane: pure skills**\n  - the public skill packet at\n    [`examples/public-skills/notes-snapshot-control-room/`](./examples/public-skills/notes-snapshot-control-room/)\n    teaches hosts how to attach to that same local control room\n- **Companion later lanes: plugin shell and `.mcpb` packaging**\n  - [`plugins/apple-notes-snapshot-control-room/`](./plugins/apple-notes-snapshot-control-room/)\n    and [`packaging/mcpb/`](./packaging/mcpb/) are host-shaped packaging\n    surfaces around the same local workflow\n  - they matter, but they are not the first story a new reviewer should read\n- **Current non-claims**\n  - no hosted Notes service\n  - no cloud sync product\n  - no official skill or plugin marketplace listing without fresh host-side\n    read-back\n  - no cross-machine attach guarantee\n\nUse the integration links below only after the operator loop already makes sense.\n\nSecondary integration reads after the first healthy loop:\n[AI Diagnose](https://xiaojiou176-open.github.io/apple-notes-snapshot/ai-diagnose/) |\n[Local Web API](https://xiaojiou176-open.github.io/apple-notes-snapshot/local-api/) |\n[MCP Provider](https://xiaojiou176-open.github.io/apple-notes-snapshot/mcp/) |\n[Distribution and listing boundaries](./DISTRIBUTION.md) |\n[For Codex / Claude Code integrations](https://xiaojiou176-open.github.io/apple-notes-snapshot/for-agents/)\n\n## Quickstart\n\nStart here if you want the shortest honest path from manual export to a\nrepeatable local snapshot loop. The first-successful-run promise is **3 steps\nand about 3 minutes**, not a zero-click install.\n\n1. Review `config/notes_snapshot.env` and keep or change the default export path.\n2. Run one snapshot so macOS can show Apple Notes / AppleScript permission prompts.\n3. Install the scheduler, then verify health.\n\n```bash\n# review config/notes_snapshot.env first\n./notesctl run --no-status\n./notesctl install --minutes 30 --load\n./notesctl verify\n./notesctl doctor\n```\n\nFail fast:\n\n- If `./notesctl verify` says `FAIL: no last_success record; run ./notesctl run`,\n  you have not completed the first manual export yet.\n- If macOS permissions block the first run, use `./notesctl permissions` and the\n  public [troubleshooting guide](https://xiaojiou176-open.github.io/apple-notes-snapshot/troubleshooting/).\n- The full, authoritative guide lives at\n  [docs/quickstart](https://xiaojiou176-open.github.io/apple-notes-snapshot/quickstart/).\n- The public\n  [proof page](https://xiaojiou176-open.github.io/apple-notes-snapshot/proof/)\n  shows the repo-side gates, live-surface checks, and trust boundary in one\n  place.\n- Maintainer-grade verification lives later in\n  [Proof and verification](#proof-and-verification); it is not required for the\n  first successful snapshot.\n\n## Choose the right lane\n\nKeep the operator lane and the maintainer lane separate.\n\n- **Operator lane**\n  - `./notesctl run --no-status`\n  - `./notesctl install --minutes 30 --load`\n  - `./notesctl verify`\n  - `./notesctl doctor`\n  - `./notesctl status --full`\n  - optional after the local state exists: `./notesctl ai-diagnose`, `./notesctl web`, and `./notesctl mcp`\n- **Maintainer lane**\n  - `./notesctl clean-cache --dry-run`\n  - `./notesctl clean-cache`\n  - `./notesctl rebuild-dev-env`\n  - `./notesctl update-vendor`\n  - `./notesctl setup` / `./notesctl self-heal`\n\nIf your goal is a healthy backup loop, stay in the operator lane first. The\nmaintainer lane is for repo upkeep and contributor verification after the local\nworkflow already makes sense.\n\n## Why this exists\n\nThe upstream [`notes-exporter`](https://github.com/storizzi/notes-exporter)\nproject is great when you want to export Apple Notes right now. This repository\nexists for the moment when \"run it once\" turns into \"keep it healthy every\nday.\"\n\nApple Notes Snapshot wraps the upstream exporter with:\n\n- one supported human entrypoint: `notesctl`\n- scheduled execution via `launchd`\n- lock protection to avoid overlapping runs\n- structured state and metrics files for health checks\n- log rotation and log-health summaries\n- an optional local Web console for status and safe actions\n\n## What you get over upstream notes-exporter\n\nThink of upstream as the engine and this repository as the control room\naround it. The wrapper tells you where snapshots will land,\nand makes the schedule and health surface easier to inspect when something\nbreaks.\n\n![Comparison card showing the difference between upstream notes-exporter and Apple Notes Snapshot](./assets/readme/upstream-vs-snapshot.png)\n\n| Need | Upstream `notes-exporter` | Apple Notes Snapshot |\n| --- | --- | --- |\n| Export notes once | Yes | Yes |\n| Schedule recurring exports | Manual setup | Built-in `launchd` flow |\n| Check freshness and last success | Limited | `status`, `verify`, and Web health UI |\n| See structured run metadata | Limited | State files, metrics, and summaries |\n| Rotate logs and inspect failures | Manual | Wrapper-owned log handling |\n| Use a local Web console | No | Optional, token-aware local control plane |\n\nUse upstream directly if you only need a one-time export. Use this repository\nwhen you want a repeatable local backup loop with visible scheduler state,\nclear snapshot paths, and easier recovery when something fails.\n\n## What the Web console shows\n\nThe local Web console is optional, and it makes the most sense after you have\nalready completed the first `run -> install -> verify` pass. Use it to watch\nthe loop you just proved, not as a replacement for that first proof.\n\nIt surfaces:\n\n- snapshot health, last success, launchd state, and failure reason\n- an operator focus deck that says what to do next and which panel to open first\n- doctor warnings and dependency readiness\n- recent metrics and trigger sources\n- log-health summaries\n- access policy and quick actions\n\n![Architecture diagram for Apple Notes Snapshot](./assets/readme/architecture.svg)\n\n## Optional AI and agent-facing surfaces\n\nThese are additive surfaces around the same local control room. They do not\nreplace `notesctl` or the deterministic runtime checks.\n\n- **AI Diagnose**\n  Use `./notesctl ai-diagnose` when you want an advisory explanation of the\n  current local state. It reads `status`, `doctor`, `log-health`, and recent-run\n  summaries, routes model calls through a local Switchyard runtime when AI is\n  enabled, and still works as a deterministic fallback when no AI provider is\n  configured. Read the public\n  [AI Diagnose guide](https://xiaojiou176-open.github.io/apple-notes-snapshot/ai-diagnose/).\n- **MCP Provider**\n  Use `./notesctl mcp` when you want a stdio-first, read-only-first MCP surface\n  for agents. It exposes local backup diagnostics and resources without turning\n  the Web console into a fake MCP API. Read the public\n  [MCP guide](https://xiaojiou176-open.github.io/apple-notes-snapshot/mcp/).\n- **Local Web API**\n  Use `./notesctl web` when you want the token-gated local browser control room\n  plus a small JSON API backed by the same repo-owned command surface. It is a\n  local operator API, not a public OpenAPI or hosted integration surface. Read\n  the public\n  [Local Web API guide](https://xiaojiou176-open.github.io/apple-notes-snapshot/local-api/).\n\n## How AI and agents fit\n\nUse this mental model if you care about Codex, Claude Code, MCP, or other\nhost-local integration ecosystems.\n\nNatural fit:\n\n- Codex- and Claude Code-style local workflows when the host can launch stdio MCP servers\n- MCP-aware coding agents that need the same local backup facts as a human operator\n\n- **AI Diagnose = operator next-step assistant**\n  - It explains local status, doctor, log-health, and recent-run evidence.\n  - It is not a generic chat overlay and it does not become the system truth.\n- **MCP Provider = read-only agent substrate**\n  - It exposes the same local backup state to MCP-aware hosts.\n  - It does not turn the project into a hosted agent platform or write-capable\n    remote control plane.\n- **Local Web API = token-gated browser/API surface**\n  - It serves the local Web console plus JSON endpoints like `status`,\n    `doctor`, `recent-runs`, and `access`.\n  - It is meant for browser or local HTTP workflows on your own machine, not as a\n    public OpenAPI promise.\n- **`notesctl` + `state.json` + aggregate summaries + token-gated Web API = current substrate**\n  - This repository does not ship a public OpenAPI, generated client, or SDK\n    today.\n  - The truthful integration entry points are the CLI contract, the web/API\n    surface, and the read-only MCP surface.\n\nIntegration-facing docs have their own shelves now, so this README does not need to carry\nevery host-specific setup detail:\n\n- Open the public\n  [For Agents guide](https://xiaojiou176-open.github.io/apple-notes-snapshot/for-agents/)\n  for the truthful builder overview and proof legend.\n- Open the\n  [Codex starter pack](https://xiaojiou176-open.github.io/apple-notes-snapshot/for-agents/codex-starter-pack/),\n  [Claude Code starter pack](https://xiaojiou176-open.github.io/apple-notes-snapshot/for-agents/claude-code-starter-pack/),\n  or\n  [OpenClaw starter pack](https://xiaojiou176-open.github.io/apple-notes-snapshot/for-agents/openclaw-starter-pack/)\n  when you need host-shaped install guidance.\n- Open the\n  [Builder integration pack](https://xiaojiou176-open.github.io/apple-notes-snapshot/for-agents/integration-pack/)\n  for the capability matrix and copyable examples, or the\n  [Public skills pack](https://xiaojiou176-open.github.io/apple-notes-snapshot/for-agents/public-skills/)\n  for the curated public-safe instruction subset.\n- Open the\n  [Local Web API guide](https://xiaojiou176-open.github.io/apple-notes-snapshot/local-api/)\n  if your workflow is browser- or local-HTTP-shaped instead of stdio MCP.\n\n## Typical workflows\n\n![Three-step run flow showing rebuild, first manual export, and scheduler verification](./assets/readme/run-flow.gif)\n\n### 1. Review the export path, then prove the first run\n\n```bash\n./notesctl run --no-status\n./notesctl install --minutes 30 --load\n```\n\nThis is the primary getting-started path. Everything else in the docs site is a\nsupporting surface around that flow.\n\n### 2. Check whether backups are still healthy\n\n```bash\n./notesctl status --full\n./notesctl verify\n./notesctl doctor\n```\n\n### 3. Open the local console when you want a control room\n\n```bash\nexport NOTES_SNAPSHOT_WEB_TOKEN=\"<long-random-token>\"\n./notesctl web\n```\n\n### 4. Refresh the vendored upstream when you maintain the wrapper\n\n```bash\n./notesctl update-vendor --ref <tag|branch|sha>\n```\n\n## Who this is for\n\n- People who already rely on Apple Notes and want local, repeatable snapshots\n- macOS users who prefer `launchd` over cloud schedulers\n- Anyone who wants backup health, logs, and operational visibility around Apple\n  Notes exports\n- Maintainers who want a reviewable wrapper instead of ad hoc shell snippets\n\n## Who this is not for\n\n- Teams looking for a shared cloud notes product\n- Anyone expecting two-way sync back into Apple Notes\n- Cross-platform note automation workflows\n- Hosted SaaS or desktop app buyers\n\n## Proof and verification\n\nThis repository ships with repo-owned verification commands instead of asking\nyou to trust screenshots alone. These are maintainer / contributor gates, not\nrequired for the first successful snapshot.\n\nIf you want the shorter public-facing evidence page first, open the\n[proof page](https://xiaojiou176-open.github.io/apple-notes-snapshot/proof/).\nIt keeps the repo-side gates, GitHub-controlled delivery facts, and the\ncurrent access boundary in one place. The ladder below remains the\nmaintainer-grade verification contract.\n\nDefault local maintainer lane:\n\n```bash\n./notesctl rebuild-dev-env\n./.runtime-cache/dev/venv/bin/python -m pre_commit run --all-files\nPYTHON_BIN=./.runtime-cache/dev/venv/bin/python scripts/checks/ci_gate.sh\n```\n\nMaintainer verification expects a local Python 3.11+ toolchain. `./notesctl rebuild-dev-env`\nrecreates `.runtime-cache/dev/venv` from scratch so the documented verification\ncommands stay aligned with the current checkout path and interpreter.\nGitHub Actions for this repo run on **GitHub-hosted runners**; the local ladder\nbelow is maintainer verification, not a self-hosted runner requirement.\n\nFive-layer CI contract:\n\n| Layer | Canonical home | What belongs here |\n| --- | --- | --- |\n| `pre-commit` | local hook | `gitleaks`, docs-link-root hygiene, legacy-path scan, and public-surface-sensitive scan |\n| `pre-push` | local hook | `scripts/checks/ci_gate.sh` for repo-local deterministic checks: docs/root hygiene, vendor tree hygiene, unit tests, and wrapper smoke |\n| `hosted` | GitHub Actions | `Canonical Quick Gate`, `Secret Scan`, `GitHub Alert Gate`, `Dependency Review`, `Actionlint`, `Zizmor`, `Trivy`, `CodeQL`, and `Pages` |\n| `nightly` | GitHub Actions schedule | `Nightly Deterministic Audit` reruns the repo-owned ladder on GitHub-hosted runners without making `pre-push` heavier |\n| `manual` | real machine / owner session | `notesctl run|verify|doctor|status`, real browser/session checks, Search Console, named-host attach proof, and other external control-plane evidence |\n\nGitHub-only governance gates:\n\n- `Dependency Review` runs on pull requests because it needs GitHub's base/head\n  dependency diff.\n- `CodeQL`, `Secret Scan`, `GitHub Alert Gate`, `Actionlint`, `Zizmor`, and\n  `Trivy` stay hosted-first; local reruns are optional maintainer repro steps,\n  not part of the default hook path.\n- Latest release tags should point at the current canonical closeout commit; do\n  not treat an older tag as proof of current repo-side closure.\n\n## Runtime and cache contract\n\nThink of the runtime layout as two rooms with one job each:\n\n- repo-local rebuildables live under `.runtime-cache/`\n- repo-owned machine-level residue lives under the current machine cache root\n  managed by `notesctl`\n\nCurrent repo-local contract:\n\n- `.runtime-cache/dev/venv` -> repo-owned maintainer virtual environment\n- `.runtime-cache/cache/apple-notes-snapshot` -> repo-local runtime cache/state support\n- `.runtime-cache/temp` -> scratch\n- `.runtime-cache/logs` -> repo-local logs\n- `.runtime-cache/pytest` -> pytest cache\n- `.runtime-cache/coverage` -> coverage data\n- `.runtime-cache/pycache` -> Python bytecode cache\n- `.runtime-cache/browser-proof` -> generated proof screenshots that can be rebuilt from the current docs surface\n- `.runtime-cache/phase1` -> historical hard-cut rollback artifacts, not current runtime truth\n- `.runtime-cache/phase1-history-rebuild` -> historical rebuild rollback artifacts, not current runtime truth\n- `.runtime-cache/mcp-registry-lane/out` -> release-ready MCP registry artifacts that can be rebuilt on demand\n\nCurrent external repo-owned contract:\n\n- launchd records for current and stale labels\n- runtime residue for launched repo-owned services\n- repo-scoped runtime copies used by the launchd wrapper\n- the persistent isolated browser root for this repo\n- disposable browser temp residue\n- the vendor-runtime current pointer/cache\n\nOlder machine-level Application Support and cache roots are migration inputs\nonly. New repo-owned runtime/cache writes should stay inside the current\nrepo-managed machine cache root.\n\n## Local cleanup and runtime audit\n\nThis is a maintainer-only cleanup lane. It is useful when you are rebuilding\nverification tooling or reclaiming repo-owned runtime residue, not when you are\ntrying to complete the first successful snapshot.\n\n- `./notesctl clean-cache --dry-run`\n  - previews repo-local rebuildable/disposable cleanup under `.runtime-cache/`\n- `./notesctl clean-cache`\n  - removes repo-local rebuildables, generated proof captures, historical rollback bundles, and disposable-generated residue\n- `./notesctl runtime-audit`\n  - reports repo-local support surfaces plus external repo-owned cache/runtime roots\n- `./notesctl clean-runtime --dry-run`\n  - previews cleanup for stale non-current residue under the repo-managed machine cache root\n- `./notesctl clean-runtime`\n  - removes stale external repo-owned residue while protecting current launchd labels\n- `./notesctl browser-bootstrap`\n  - copies the current `apple-notes-snapshot` source profile out of the default Chrome root into the repo-owned isolated root\n- `./notesctl browser-open`\n  - launches or attaches to the single repo-owned Chrome instance for this repo\n- `./notesctl rebuild-dev-env`\n  - restores the canonical path-aware maintainer environment after cleanup\n\nThe repo may still clean legacy `.pytest_cache`, `.coverage`, or scattered\n`__pycache__` directories if they are already present, but those are migration\nbackstops. The current contract routes repo-owned disposable artifacts into\n`.runtime-cache/*`, including historical rollback folders and proof captures\nthat are safe to regenerate when you no longer need them.\n\nAutomatic janitor hooks run on repo-owned entrypoints that create or reuse\nmachine-level residue, including `run`, `web`, `install`, `ensure`,\n`rebuild-dev-env`, and `runtime-audit`. The default policy is intentionally\nstrict:\n\n- external repo-owned budget: `2 GB`\n- general external TTL: `72 hours`\n- browser clone TTL: `24 hours`\n- current/protected launchd labels are never deleted by TTL alone\n- `browser/chrome-user-data/` is permanent state and excluded from TTL/cap cleanup\n\nThis repository does **not** have a repo-owned Docker cleanup lane today.\nThe automatic janitor does not touch Docker, system temp roots, or shared tool\ncaches from Cursor, Codex, Claude, Serena, Homebrew, pip, nodeenv, uv, or\nother machine-wide tooling.\n\n## Browser automation contract\n\nBrowser automation in this repository now uses an **isolated Chrome root +\nsingle repo-owned instance + CDP attach** contract.\n\n- `NOTES_SNAPSHOT_BROWSER_PROVIDER=chrome`\n- `NOTES_SNAPSHOT_BROWSER_ROOT=<repo-owned-browser-root>`\n- `NOTES_SNAPSHOT_CHROME_USER_DATA_DIR=<repo-owned-browser-root>/chrome-user-data`\n- `NOTES_SNAPSHOT_CHROME_PROFILE_NAME=apple-notes-snapshot`\n- `NOTES_SNAPSHOT_CHROME_PROFILE_DIR=Profile 1`\n- `NOTES_SNAPSHOT_CHROME_CDP_HOST=127.0.0.1`\n- `NOTES_SNAPSHOT_CHROME_CDP_PORT=9337`\n\nThe old default Chrome user-data root is now only a one-time read source for\n`./notesctl browser-bootstrap`. It is no longer the long-term runtime root for\nthis repo.\n\nTreat `browser-bootstrap` as a one-time migration, not as a routine sync step.\nIf you later add or refresh logins inside the isolated root, do **not** rerun\n`browser-bootstrap` unless you intentionally want to replace the isolated root\nfrom the default Chrome root again.\n\nUse these commands in order:\n\n- `./notesctl browser-bootstrap`\n  - one-time copy from the default Chrome root into the isolated repo-owned root\n- `./notesctl browser-open`\n  - launch the single repo-owned Chrome instance if it is not running yet\n  - otherwise return attach info instead of second-launching\n- `./notesctl browser-contract --json`\n  - print the canonical attach-first contract, including the CDP endpoint for Playwright/CDP clients\n\nIf `127.0.0.1:9337` is already occupied on your machine, the repo should fail\nfast instead of silently attaching to the wrong thing. In that case, use a\ndeliberate env override such as `NOTES_SNAPSHOT_CHROME_CDP_PORT=9347` before\nstarting or attaching to the repo-owned instance.\n\nThis repo does **not** silently fall back to bundled Chromium, and it does\n**not** keep launching new browser instances against the same user-data dir.\nHuman manual use and automation are expected to attach to the same repo-owned\nChrome instance.\n\n## CI contract\n\nThe repository keeps five verification layers, and they are not interchangeable:\n\n| Layer | Default trigger | Canonical home | Contract |\n| --- | --- | --- | --- |\n| `pre-commit` | every local commit attempt | local hook | quick hygiene only |\n| `pre-push` | every local push attempt | local hook | deterministic repo-local quick gate only |\n| `hosted` | pull request / push / workflow dispatch | GitHub-hosted runners | GitHub-state-aware security and policy gates |\n| `nightly` | scheduled GitHub run | `Nightly Deterministic Audit` reruns the repo-owned ladder on GitHub-hosted runners |\n| `manual` | deliberate human/operator action | real machine / owner session | live browser, desktop, provider, and external control-plane proof |\n\nThis open-source repository does **not** rely on a local self-hosted runner\nlane. Local verification exists so maintainers can reproduce the repo-owned\ngates before or after a pull request, not because CI is expected to run on the\ndeveloper's Mac.\n\nHigh-value local checks:\n\n```bash\n./notesctl status --full\n./notesctl verify\n./notesctl doctor\n```\n\nThe repo-owned quick gate now covers docs/root hygiene, vendor tree hygiene,\nunit tests, and wrapper-level JSON/help smoke checks. GitHub alert state moved\nfully into the hosted lane so the default local pre-push path stays lighter and\nmore deterministic. The 90%+ coverage bar still applies to repo-owned Python\nsurfaces under `scripts/ops`; the shell wrapper surface is guarded by smoke\nchecks rather than pretending it shares that coverage metric.\n\n## Verification ladder and test pyramid\n\nThink of the verification contract like a small testing pyramid instead of one\ngiant \"just run everything\" blob.\n\n- **Unit tests**\n  - fastest checks for repo-owned Python logic and deterministic report shaping\n  - examples: `tests/unit/test_ai_diagnose_unit.py`,\n    `tests/unit/test_mcp_server_unit.py`,\n    `tests/unit/test_web_server_unit.py`\n- **Wrapper smoke**\n  - repo-owned shell-contract checks for `notesctl` help, JSON surfaces, and\n    wrapper entrypoints\n  - example: `bash scripts/checks/run_wrapper_smoke.sh`\n- **E2E**\n  - slower integration checks for launchd, relocation, Web server behavior, and\n    real command orchestration\n  - example: `./.runtime-cache/dev/venv/bin/pytest tests/e2e --no-cov`\n- **Manual-local validation**\n  - the real operator path on a real Mac:\n    `run -> verify -> status -> doctor -> web`\n\nRead the pyramid as:\n\n1. unit tests catch logic regressions fastest\n2. wrapper smoke protects the shell contract\n3. E2E checks prove the repo-owned pieces still cooperate\n4. manual-local validation proves the actual machine is healthy\n\n## Security and privacy\n\nThis project is intentionally user-controlled on your own machine:\n\n- your Apple Notes content stays in your own Apple Notes account and export\n  destination\n- the optional Web console is local by default and token-aware when enabled\n- the repository documents private vulnerability reporting in `SECURITY.md`\n- secrets, runtime caches, generated launchd files, and logs are not part of\n  the tracked source surface\n\nRead [SECURITY.md](SECURITY.md) before reporting sensitive issues.\n\n## FAQ\n\n### Is this a replacement for the upstream exporter?\n\nNo. It is a wrapper that makes the upstream exporter safer and easier to operate\nas an ongoing local workflow.\n\n### Does it sync changes back into Apple Notes?\n\nNo. This repository is for snapshotting and exporting, not two-way sync.\n\n### Do I need the Web console?\n\nNo. `notesctl` is the supported human entrypoint. The Web console is optional.\n\n### How do I open the interactive menu?\n\nRun `./notesctl` with no arguments. The interactive menu lives on the canonical\ncommand surface now.\n\n### Do I need GitHub Pages to use the tool?\n\nNo. Pages is only for public documentation and search visibility. The actual\nworkflow stays local on your Mac.\n\n### What if I move the checkout to another path?\n\nReinstall the scheduler so the path-aware launchd surface points at the current\ncheckout. If you also use the repo-owned verification environment or the\noptional Web console, rebuild that environment too:\n\n```bash\n./notesctl install --minutes 30 --load\n./notesctl rebuild-dev-env\n```\n\n## Community\n\nUse the GitHub Discussions surface that matches your intent:\n\n- Questions and setup blockers:\n  [Q&A discussion](https://github.com/xiaojiou176-open/apple-notes-snapshot/discussions/categories/q-a)\n- Feature ideas and roadmap input:\n  [Ideas discussion](https://github.com/xiaojiou176-open/apple-notes-snapshot/discussions/categories/ideas)\n- Real-world usage examples:\n  [Show and tell discussion](https://github.com/xiaojiou176-open/apple-notes-snapshot/discussions/categories/show-and-tell)\n- Release announcements:\n  [Announcements discussion](https://github.com/xiaojiou176-open/apple-notes-snapshot/discussions/categories/announcements)\n\nIf you need a support-routing summary first, read [SUPPORT.md](SUPPORT.md) or the\npublic [support page](https://xiaojiou176-open.github.io/apple-notes-snapshot/support/).\n\n## Contributing\n\nRead [CONTRIBUTING.md](CONTRIBUTING.md) before changing wrapper logic, docs, or\npublic-facing copy. The project favors small, reviewable changes with explicit\nverification notes.\n\n## License\n\nThis repository is released under the [MIT License](LICENSE).\n",
  "bytes": 30863,
  "sha": "ad5f7a9fd7c20361e9e786bac26c103d4e8f797bfbdda5dbd3bf6434aa51bd28",
  "repo_slug": "xiaojiou176-open/apple-notes-snapshot",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_xiaojiou176_open_apple_notes_s_8262abc9/readme"
}