|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +## What opendoc is |
| 4 | + |
| 5 | +opendoc is a one-way sync engine that mirrors documents you've authorized in |
| 6 | +Notion and Feishu into a local, read-only Markdown tree. It never writes |
| 7 | +back to the source platform. The mirror is meant to be consumed directly by |
| 8 | +coding agents with Grep/Glob/Read — no API calls, no credentials, no network |
| 9 | +access needed at read time. A companion Claude Code plugin (`skill/`) wraps |
| 10 | +the `opendoc` binary and exposes it to agents as a skill. |
| 11 | + |
| 12 | +## Repo layout |
| 13 | + |
| 14 | +- `cmd/opendoc` — CLI entrypoint (`main.go`), wires subcommands to `internal/cli`. |
| 15 | +- `internal/adapter` — platform-agnostic contract between the engine and a |
| 16 | + concrete source (Notion, Feishu, ...); the engine only depends on this interface. |
| 17 | +- `internal/cli` — subcommand dispatch and flag parsing (init, sync, status, |
| 18 | + doctor, resolve, schedule). |
| 19 | +- `internal/config` — on-disk mirror configuration (`.internal/config.toml`) |
| 20 | + and its readers/writers. |
| 21 | +- `internal/engine` — the sync pipeline: fetch, diff, write, index, manifest bookkeeping. |
| 22 | +- `internal/feishu` — Feishu/Lark adapter (bitable, doc fetch, metadata). |
| 23 | +- `internal/frontmatter` — deterministic YAML frontmatter rendering for mirrored files. |
| 24 | +- `internal/layout` — mirror-root resolution and on-disk directory layout. |
| 25 | +- `internal/manifest` — `manifest.sqlite`, the sync engine's bookkeeping ledger. |
| 26 | +- `internal/naming` — filesystem-safe path/file naming and collision rules. |
| 27 | +- `internal/notion` — Notion adapter (query, fetch, properties→frontmatter mapping). |
| 28 | +- `internal/ratelimit` — token bucket + backoff helpers for platform QPS limits. |
| 29 | + |
| 30 | +## Build & test |
| 31 | + |
| 32 | +``` |
| 33 | +go build ./... |
| 34 | +go test ./... |
| 35 | +./scripts/build-skill.sh # builds the binary into skill/bin/opendoc and symlinks it into ~/.claude/skills/opendoc |
| 36 | +``` |
| 37 | + |
| 38 | +## Key invariants |
| 39 | + |
| 40 | +- **Fidelity-first**: never silently drop content. Anything that can't be |
| 41 | + rendered faithfully gets a placeholder tag, and the loss is counted in the |
| 42 | + sync report — not swallowed. |
| 43 | +- **Mirror is read-only**: nothing in the mirrored tree is ever written back |
| 44 | + to Notion or Feishu. |
| 45 | +- **Manifest keys are platform-native IDs**: the sync ledger is keyed by the |
| 46 | + source platform's own document/page/row IDs, not derived or local ones. |
| 47 | +- **content_hash is computed before link rewriting**: the hash that drives |
| 48 | + change detection reflects the fetched content, not the post-processed |
| 49 | + (link-rewritten) output. |
| 50 | +- **Doctor codes are stable identifiers**: probe/failure codes (e.g. `F1`, |
| 51 | + `F2-NOAUTH`, `N2-INVALID`, `N3-EMPTY`, `G2-QUOTA-LOW`) and exit codes (e.g. |
| 52 | + `3` = `ExitNotInitialized`) are part of the tool's contract. Don't rename |
| 53 | + or renumber them — scripts and docs key off the literal strings. |
| 54 | + |
| 55 | +## `skill/SKILL.md` |
| 56 | + |
| 57 | +This file is runtime instructions read by coding agents, not just |
| 58 | +documentation. Its semantics (what it tells an agent to do, and when) must |
| 59 | +not drift casually — treat behavioral changes there with the same care as a |
| 60 | +CLI flag change. |
0 commit comments