diff --git a/.gitignore b/.gitignore index a5eb364..06d281a 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,11 @@ Desktop.ini .notch/index/ .notch/logs/ .notch/private/ + +# Local playground stores (do not commit personal .notch roots) +# Keep fixtures/ and intentional demo stores tracked separately. + +# Site local artifacts +site/public/test-results/ +site/node_modules/ +site/.wrangler/ diff --git a/README.md b/README.md index a3ebef5..74d7775 100644 --- a/README.md +++ b/README.md @@ -2,263 +2,205 @@ **Save the working state your AI tools won't.** -[**Website →**](https://3notch.dev) · [**Docs →**](https://3notch.dev/docs/) · [**Quickstart →**](https://3notch.dev/docs/quickstart/) · [**npm →**](https://www.npmjs.com/package/@3notch/cli) +[Website](https://3notch.dev) · [Docs](https://3notch.dev/docs/) · [Quickstart](https://3notch.dev/docs/quickstart/) · [npm](https://www.npmjs.com/package/@3notch/cli) [![CI](https://img.shields.io/github/actions/workflow/status/coldlogicAI/3notch/ci.yml?branch=main&style=flat-square)](https://github.com/coldlogicAI/3notch/actions/workflows/ci.yml) [![npm](https://img.shields.io/npm/v/@3notch/cli?style=flat-square)](https://www.npmjs.com/package/@3notch/cli) [![Node](https://img.shields.io/node/v/@3notch/cli?style=flat-square)](https://nodejs.org) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE) -Your AI session died — rate limited, context compacted, model went down. Six hours of decisions, constraints, and working state gone. The next agent starts from scratch because nothing portable survived the switch. +Rate limits, model failures, context compaction, tool switches — the code is still in git. The objective, decisions, and next steps often are not. The next session rebuilds that state from scratch. -3Notch is a local CLI and MCP server that saves your working state as portable checkpoints. When a session crashes, the next one picks up where you left off. When you switch tools — Claude to Codex, Cursor to ChatGPT — your context travels with you. When work moves to another repo or machine, you package the handoff. +3Notch is a **local CLI and MCP server** for: -No cloud service. No account. No telemetry. No lock-in. Everything stays on your machine. +- **Continuation checkpoints** — when Claude Code is configured, recover after rate limits, model-down failures, and compaction +- **Portable packets** — hand off selected work across tools, repos, and machines +- **Durable inbox** — async delivery between stores that share a mailbox root ---- - -## Get Started - -Give this to your agent: +No cloud service. No account. No telemetry. Records stay on disk as Markdown (and optional artifacts) under `.notch/`. -> Install @3notch/cli and set up context checkpoints for this repo. When a session crashes or I hit a rate limit, save where I was so the next session can pick up. When I switch tools, package the handoff. +--- -Or install directly: +## Install ```bash npm install -g @3notch/cli notch onboard ``` -Then pick the flow that matches your situation. +Agent prompt (optional): + +> Install @3notch/cli, run `notch onboard` in this repo, and set up continuation checkpoints if I use Claude Code. Use packets for handoffs across tools or repos. Read the package README before changing MCP config. + +--- + +## Common flows -### Session crashed — pick up where you left off +### Resume after a failed session -When a session hits a rate limit or compacts, 3Notch saves your working state automatically. The next session offers to resume: +With [continuation checkpoints](docs/guides/continuation-checkpoints.md) enabled for Claude Code, 3Notch can write a fallback from task state and git when the session hits a rate limit, model-down failure, or compaction. The next session may offer that checkpoint once; you approve before it is loaded. ```bash notch packet list -# Shows your latest checkpoint with objective, completed work, blockers, and next action +notch packet preview ``` -### Switching tools — take your context with you - -Moving from Claude Code to Codex? The outgoing agent writes a checkpoint. The incoming agent reads it: +### Hand off between tools ```bash notch packet create \ --title "Auth refactor checkpoint" \ - --summary "Token validation done, session store migration blocked." \ + --summary "Token validation done; session store migration blocked." \ --next-steps "Implement Redis session adapter" -``` -### Different repo or machine — package the handoff +notch packet preview +# other tool / session imports and continues +``` -Bundle selected files, decisions, and next steps into a portable packet: +### Ship files to another repo or machine ```bash notch packet create \ --title "Brand handoff" \ - --summary "Brand handoff for the launch page." \ - --to-agent codex \ - --to-repo ../brand-site \ + --summary "Assets and layout for the launch page." \ --file mascot.jpg:asset \ --file showcase.html:source \ - --next-steps "Build the launch page using showcase.html as the layout and mascot.jpg in the hero." -``` + --next-steps "Build the launch page from showcase.html and mascot.jpg." -The packet lands as a folder in `.notch/outbox/` with `packet.md`, `manifest.json`, and copied bytes under `artifacts/`. The destination imports it: - -```bash -notch packet import ../source/.notch/outbox//packet.md -notch packet preview +notch packet pack +# move .notchpkt however you prefer, then: +notch packet unpack .notchpkt ``` -### Cross-machine +### Async agents — durable inbox -Pack the folder into a `.notchpkt` archive, move it however you want (scp, iCloud, Tailscale, email, git), unpack on the other side: +Both sides register the same mailbox root, then pack/send and pull/ack: ```bash -notch packet pack -# move .notchpkt to the destination machine -notch packet unpack .notchpkt -``` - -### Async agents or repos — use durable inbox - -When two agents cannot rely on one live chat or shared store, point both at one explicit local mailbox root: - -```bash -# Run once in each store with a unique name and the same root notch inbox init --name review-agent --root /shared/3notch-mailbox +notch packet pack +notch send .notchpkt --to local:review-agent +# forward the printed delivery notice via chat, Slack, etc. -# Pack and send from the source -notch packet pack -notch send .notchpkt --to local:review-agent -notch inbox status --at local:review-agent - -# Verify and import at the receiver notch inbox list notch inbox pull --import notch inbox ack ``` -`notch send` prints an agent-readable delivery notice that can move through Claude cross-session messaging, Slack, email, or any other text channel. The local address is a routing label, not authenticated identity. Deliveries are hashed, validated, scanned, retained after ack, and traced locally. See [Durable inbox](docs/guides/durable-inbox.md). - -### Browser-only chats (fallback) +`local:` addresses are routing labels, not authenticated identity. See [Durable inbox](docs/guides/durable-inbox.md). -Web chats that can't reach local MCP use a clipboard bridge: +### Web chat without MCP ```bash notch prompt --client claude-chat -# paste the prompt into the chat, ask for a packet, copy the result +# paste into the chat, copy the packet back pbpaste | notch packet import - ``` ### Personal capture -When you just want to remember something for yourself: - ```bash -notch mark --summary "Decided to keep browser auth cookie-based" --tags auth +notch mark --summary "Keep browser auth cookie-based" --tags auth ``` --- -## How It Works +## How it works -Checkpoints and packets are plain Markdown files with structured frontmatter. You can read, edit, and version them like anything else in your repo. +1. You or an agent write selected context through the CLI or MCP tools. +2. 3Notch validates, secret-scans, and stores records under `.notch/`. +3. Preview before another agent relies on the content. +4. The next session, tool, or store imports or resumes from that record. -1. You or your agent ask 3Notch to save the current working state. -2. 3Notch validates the record, scans it for secrets, and writes it under `.notch/`. -3. You preview the checkpoint before another tool relies on it. -4. The next session, tool, or repo reads and resumes from it. +Targeting fields (`--to-agent`, `--to-repo`) are intent metadata. Bytes move via your transport (scp, git, AirDrop, Tailscale) or the durable inbox mailbox — not a 3Notch-hosted relay. -Targeting fields (`--to-agent`, `--to-repo`) remain intent metadata. Manual transports move archives directly; durable inbox uses a separate registered `local:` address as its delivery control. +--- ## Commands ```text -notch onboard initialize .notch/ and MCP setup -notch packet create create a checkpoint or packet (--file, --ref, --next-steps) -notch packet import import a packet into .notch/inbox/ -notch packet preview show what an agent will read -notch packet pack produce a .notchpkt archive -notch packet unpack import a .notchpkt archive -notch inbox init/list/status/pull/ack configure and process durable deliveries -notch send --to
send a packed project handoff -notch packet list / show list / inspect packets -notch reply typed reply to a packet -notch mark self-addressed private capture -notch brief / brief create / list / show scoped task briefs -notch seed from private context seeding -notch prompt --client optional copy-paste agent instruction pack -notch scan standalone secret scanner -notch check deterministic corpus integrity checks -notch doctor store diagnostics -notch status store summary -notch mcp serve local stdio MCP server +notch onboard initialize .notch/ and MCP setup +notch packet create create a packet (--file, --ref, --next-steps) +notch packet import import into .notch/inbox/ +notch packet preview show what an agent will read +notch packet pack / unpack .notchpkt archive round-trip +notch packet list / show list / inspect packets +notch inbox init/list/status/pull/ack durable delivery lifecycle +notch send --to
send a packed project handoff +notch reply typed reply to a packet +notch mark self-addressed private capture +notch brief / brief create|list|show scoped task briefs +notch seed from private context seeding +notch prompt --client agent / web-chat instruction packs +notch scan secret scanner +notch check structural corpus checks +notch doctor store diagnostics +notch status store summary +notch mcp serve local stdio MCP server ``` -## MCP - -`notch mcp serve` exposes these tools over local stdio: - -- Read-only: `get_brief`, `list_briefs`, `get_targeted_brief`, `get_packet`, `list_packets`, `list_inbox`, `get_inbox_delivery`, `get_status`, `check_store`, `run_doctor` -- Write: `create_brief`, `create_packet`, `create_mark`, `create_reply`, `create_seed_packet`, `import_packet`, `import_seed_packet`, `inbox_init`, `send_packet`, `pull_inbox_packet`, `ack_inbox_delivery` - -Private records under `.notch/private/` are hidden unless the server starts with `--include-private`. See [docs/guides/mcp-setup.md](docs/guides/mcp-setup.md) for client-specific setup. +--- -## Docs +## MCP -Full index: [docs/README.md](docs/README.md). +`notch mcp serve` over local stdio: -| Goal | Doc | +| | Tools | | --- | --- | -| Move context between repos | [docs/guides/cross-repo-packets.md](docs/guides/cross-repo-packets.md) | -| Move context between tools | [docs/guides/cross-tool-handoff.md](docs/guides/cross-tool-handoff.md) | -| Deliver packets asynchronously | [docs/guides/durable-inbox.md](docs/guides/durable-inbox.md) | -| Carry preferences into a new repo | [docs/guides/private-context-seeding.md](docs/guides/private-context-seeding.md) | -| Brief an agent on scoped work | [docs/guides/targeted-brief-workflow.md](docs/guides/targeted-brief-workflow.md) | -| Set up continuation checkpoints | [docs/guides/continuation-checkpoints.md](docs/guides/continuation-checkpoints.md) | -| Set up MCP clients | [docs/guides/mcp-setup.md](docs/guides/mcp-setup.md) | -| Understand privacy posture | [docs/reference/privacy.md](docs/reference/privacy.md) | -| Understand the security model | [docs/reference/security-story.md](docs/reference/security-story.md) | -| Use the web-chat bridge | [docs/prompts/web-chat-to-project.md](docs/prompts/web-chat-to-project.md) | - -## Boundaries - -3Notch is deliberately narrow. - -- Local files by default. No cloud dependency, no hosted relay, no account system. -- No telemetry. -- No vector database or native database dependency. -- No arbitrary shell execution through MCP. -- Manual transports or the explicit local durable inbox move bytes; 3Notch validates, scans, hashes, and stores them. - -A regression-guard test (`tests/unit/no-deferred-commands.test.ts`) prevents accidental scope creep. - -## Where We Want Help +| **Read** | `get_brief`, `list_briefs`, `get_targeted_brief`, `get_packet`, `list_packets`, `list_inbox`, `get_inbox_delivery`, `get_status`, `check_store`, `run_doctor` | +| **Write** | `create_brief`, `create_packet`, `create_mark`, `create_reply`, `create_seed_packet`, `import_packet`, `import_seed_packet`, `inbox_init`, `send_packet`, `pull_inbox_packet`, `ack_inbox_delivery` | -3Notch is open source because the cross-vendor context problem can only be solved neutrally. These are known gaps where contributor input is welcome: +Private records under `.notch/private/` stay hidden unless the server starts with `--include-private`. Client setup: [docs/guides/mcp-setup.md](docs/guides/mcp-setup.md). -**Reaching more surfaces** -- **Web-chat ingest via custom connectors / remote MCP.** An optional HTTP/SSE MCP mode a user wires to Claude.ai via Anthropic's custom-connector flow plus a user-controlled tunnel (Tailscale, Cloudflare). No hosted relay. -- **Onboarding for additional clients** — Gemini CLI, future MCP-capable agents. -- **Mobile / voice intake.** -- **Claude Code → web-chat sharing** (reverse of the current bridge). - -**Moving packets between machines and people** -- **Hosted authenticated transport** that preserves the durable-inbox CLI/MCP contract without putting accounts or network listeners in the local core. -- **Cross-machine transport recipes** for Tailscale, iCloud, Syncthing, git, scp/rsync — opinionated adapter docs and honest sync guarantees. -- **Cross-user / teammate workflows** — conventions for handing packets through whatever channel a team already uses. +--- -**Distribution polish** -- **DXT packaging** for one-click Claude Desktop install. -- **Notarized / signed installers.** +## Documentation -**Capture ergonomics** -- **Agent prompt packs / skills** that wrap "save artifact to disk, then `create_packet`" for specific clients. -- **Per-language / per-framework brief templates.** +| Topic | Guide | +| --- | --- | +| Index | [docs/README.md](docs/README.md) | +| Cross-repo packets | [docs/guides/cross-repo-packets.md](docs/guides/cross-repo-packets.md) | +| Cross-tool handoff | [docs/guides/cross-tool-handoff.md](docs/guides/cross-tool-handoff.md) | +| Durable inbox | [docs/guides/durable-inbox.md](docs/guides/durable-inbox.md) | +| Continuation checkpoints | [docs/guides/continuation-checkpoints.md](docs/guides/continuation-checkpoints.md) | +| MCP setup | [docs/guides/mcp-setup.md](docs/guides/mcp-setup.md) | +| Privacy | [docs/reference/privacy.md](docs/reference/privacy.md) | +| Security | [docs/reference/security-story.md](docs/reference/security-story.md) | +| Releases (maintainers) | [docs/guides/release.md](docs/guides/release.md) | + +Website docs mirror: [https://3notch.dev/docs/](https://3notch.dev/docs/). -**Surfaces on top of the stable substrate** -- **Reply-surfacing UX patterns.** The schema (`replyTo`, `replyType`, `status`) is shipped; the surfacing layer is deferred so contributors can experiment. -- **Wiki / browse / graph views** over `relationships.json`. Out of core by design; contributor surfaces welcome. -- **Additional `notch check` rules** — contribute once you've hit the pain. +--- -**Hardening** -- **Encryption at rest** for `.notch/private/`. -- **Scanner rule contributions** — org-specific, industry-specific, or platform-specific patterns. +## Boundaries -If you're considering a contribution, open an issue first so we can align on scope. +- Local files by default — no hosted relay, account system, or telemetry +- No vector DB / native DB dependency +- No arbitrary shell execution through MCP +- You move bytes; 3Notch validates, scans, hashes, and stores them -## Repo Structure +Regression guard: `tests/unit/no-deferred-commands.test.ts`. -``` -src/ CLI, core services, MCP server, schemas, types -tests/ unit, CLI, MCP, schema, e2e tests + fixtures -fixtures/ demo .notch/ stores used by docs and e2e tests -docs/ guides, reference, agent prompts, archived plans -.github/ CI workflow, issue templates, PR template -``` +--- -For internal architecture (record types, store layout, services), see [docs/archived-plans/v1/3notch-v1-technical-spec.md](docs/archived-plans/v1/3notch-v1-technical-spec.md). +## Contributing -## Development +Prefer opening an issue before large features. See open issues and [CONTRIBUTING.md](CONTRIBUTING.md). ```bash -git clone +git clone https://github.com/coldlogicAI/3notch.git cd 3notch npm install -npm run lint -npm run type-check -npm run build -npm test -npm run test:e2e -node dist/cli/index.js --help +npm run lint && npm run type-check && npm run build +npm test && npm run test:e2e +npm run release:check ``` -See [CONTRIBUTING.md](CONTRIBUTING.md) for the full contributor loop, including a working cross-repo demo you can run from a fresh clone. +See [CONTRIBUTING.md](CONTRIBUTING.md). + +Architecture reference (historical but still useful): [docs/archived-plans/v1/3notch-v1-technical-spec.md](docs/archived-plans/v1/3notch-v1-technical-spec.md). + +--- ## License diff --git a/docs/README.md b/docs/README.md index 9d6187b..72688a3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ Task-shaped how-tos for the main flows. - [Targeted brief workflow](guides/targeted-brief-workflow.md) — scoped task briefs vs cross-boundary packets. - [MCP setup](guides/mcp-setup.md) — server flags, available tools, agent instruction packs. - [Continuation checkpoints](guides/continuation-checkpoints.md) — opt-in Claude task aggregation, compaction fallback, model-down StopFailure recovery, and resume confirmation. -- [Release](guides/release.md) — version surfaces, manual npm publish (token + temp config), and release-check automation. +- [Release](guides/release.md) — maintainer version surfaces, publish recipe, and release-check. ## Reference diff --git a/docs/guides/release.md b/docs/guides/release.md index 7f91201..ac4d3d3 100644 --- a/docs/guides/release.md +++ b/docs/guides/release.md @@ -114,6 +114,10 @@ Optional second token name for CI later: `3notch-cli-publish-gha` (no IP lock; s From the project root, with `package.json` already at the release version: ```bash +# Publish from the tree you intend to ship (usually up-to-date main) +git checkout main && git pull +node -p "require('./package.json').version" # confirm expected version + npm run build npm run release:check @@ -121,26 +125,27 @@ npm run release:check read -rs "NPM_TOKEN?Paste npm token from 1Password: " echo export NPM_TOKEN +test -n "$NPM_TOKEN" || { echo "empty token"; exit 1; } npm_cfg="$(mktemp)" chmod 600 "$npm_cfg" -printf '%s\n' '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' > "$npm_cfg" +# Double quotes required so ${NPM_TOKEN} expands (single quotes write the literal text) +printf '%s\n' "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > "$npm_cfg" export NPM_CONFIG_USERCONFIG="$npm_cfg" -trap 'rm -f -- "$npm_cfg"' EXIT +trap 'rm -f -- "$npm_cfg"; unset NPM_TOKEN' EXIT npm whoami npm publish --access public - -unset NPM_TOKEN +npm view @3notch/cli version npm run release:status -- --require-published ``` What this does: -- Keeps the token out of the project tree and out of your permanent user `.npmrc` if you prefer +- Publishes the current checkout (not whatever happens to be on GitHub unless you pulled) +- Keeps the token out of the project tree and out of a permanent project `.npmrc` - Uses a mode-`600` temp npm userconfig and deletes it on shell exit -- Confirms identity before publish -- Fails the status check until registry `latest` equals `package.json` +- Confirms identity before publish; fails status check until registry `latest` equals `package.json` Dry-run (no registry write): diff --git a/eslint.config.mjs b/eslint.config.mjs index 76b2b00..d55a6f2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -13,4 +13,14 @@ export default tseslint.config( 'no-undef': 'off', }, }, + { + files: ['scripts/**/*.{js,mjs,cjs}'], + languageOptions: { + globals: { + console: 'readonly', + fetch: 'readonly', + process: 'readonly', + }, + }, + }, ); diff --git a/site/README.md b/site/README.md index 5d788a1..0ac0b04 100644 --- a/site/README.md +++ b/site/README.md @@ -41,10 +41,15 @@ npm run dev This uses `npx serve` (no install needed). Open the URL, edit `public/index.html`, refresh. +**Preview with `npm run dev`, not by opening HTML as a file.** The site uses root-absolute paths (`/docs/`, `/docs/docs.css`) so production and `serve` behave the same. `file://` will break those links. + --- ## Deploy to Cloudflare Pages +**Canonical path:** Wrangler → Cloudflare Pages project `3notch`. +There is no GitHub Pages workflow for this site in-repo. If you ever saw a GitHub deploy, it was one-off or external—not the maintained path. + ### One-time setup 1. **Create a Cloudflare account** at https://dash.cloudflare.com (free). @@ -60,9 +65,10 @@ This uses `npx serve` (no install needed). Open the URL, edit `public/index.html ### Ship it -From `site/`: +From `site/` (after copy/version changes are on the branch you want live): ```bash +cd site npm run deploy ``` diff --git a/site/public/index.html b/site/public/index.html index fa0a57a..15bddc6 100644 --- a/site/public/index.html +++ b/site/public/index.html @@ -3,36 +3,64 @@ -3Notch — Mark your trail. - +3Notch — Local AI checkpoints and portable handoff packets + + + + - - + + + + + - - + + + - + +