Skip to content

docs: rewrite CLAUDE.md as a contributor guide - #28

Open
menor wants to merge 2 commits into
mainfrom
docs/lean-claude-md
Open

docs: rewrite CLAUDE.md as a contributor guide#28
menor wants to merge 2 commits into
mainfrom
docs/lean-claude-md

Conversation

@menor

@menor menor commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What

Rewrites CLAUDE.md. 412 lines down to 127.

The file had drifted into a second copy of the README — hosted-vs-local setup, an env var table, a command list, a full directory tree. All of that lives in README.md or in upsun-mcp/package.json, and duplicated content rots: the old tree predated both core/transport/ and core/lean.ts.

What's left is the material a contributor — or a coding agent — cannot get from skimming the code.

The five invariants it now documents

Each one lets the server compile, pass a smoke test, and fail in production:

  1. Session binding is to the token, not the session id. A mismatch and an unknown id both return 404 Session not found, deliberately indistinguishable. (fix(auth): bind MCP sessions to the credential token hash #24)
  2. 401 forwarding needs enableJsonResponse: true. SSE commits 200 headers immediately, so it cannot forward. (fix: use stateless streamable HTTP for OAuth #25)
  3. lean.ts strips HAL from resource objects, never from the list envelope — the pagination cursors live there. (feat(read-tools): strip HAL envelope from read output, full opt-out #27, feat: add pagination params to list-project and list-organization #23)
  4. list() returns snake_case HAL; info()/get() return camelCase. The generated .d.ts claims otherwise.
  5. Two API-key env vars, split by transport.

Also

The "adding a command" recipe now covers read tools. It previously ended at Response.json(result) — a read tool written to that recipe ships the full HAL envelope, undoing #27. The missing steps are full: Schema.full() and lean(result, { itemsKey }).

Two broken package.json scripts are recorded as traps, since neither is covered by CI:

  • watch runs tsx watch index.ts; that file does not exist (the entry is src/index.ts), so it exits with ERR_MODULE_NOT_FOUND.
  • coverage:verify calls ./scripts/check-coverage.sh, which is not in the repo.

Happy to fix both in a follow-up and drop that paragraph — kept out of here so this stays docs-only.

Verification

Every claim was checked against the code on main rather than carried over from the old file. The core/ tree matches git ls-tree. No source files touched.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown

Coverage after merging docs/lean-claude-md into main will be

92.64%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   mcpUpsun.ts96%75%100%97.44%171–172
src/command
   activity.ts100%100%100%100%
   backup.ts100%100%100%100%
   certificate.ts100%100%100%100%
   domain.ts100%100%100%100%
   environment.ts98.70%94.44%100%100%339
   organization.ts100%100%100%100%
   project.ts91.49%66.67%100%100%139, 173, 71, 78
   route.ts100%100%100%100%
   ssh.ts100%100%100%100%
src/core
   authentication.ts85.71%77.08%95%88.89%113–114, 133, 218–219, 221, 296–298, 321, 332–333, 353–354, 354, 354, 354, 354–355
   config.ts91.47%91.04%100%91.04%121, 133, 140, 140, 140, 140, 142, 145, 149, 156, 156, 160, 162, 316, 353, 36, 51, 62
   gateway.ts80.52%100%66.67%81.67%261–264, 288, 291–292, 294–295, 299, 303
   helper.ts89.84%81.48%100%91.43%208–209, 241–242, 337, 341–342, 349, 353, 422–424, 461–462, 512–513, 517, 544–545
   lean.ts90.70%88.89%100%90.91%85, 88, 91, 95
   logger.ts98.61%96.15%100%100%83
   requestContext.ts100%100%100%100%
   telemetry.ts92.09%88.57%100%92.55%163, 200–201, 250–251, 299–300, 350–351, 372–373
   types.ts100%100%100%100%
src/core/transport
   http.ts83.56%80%81.25%85.26%102, 102, 102–103, 158–159, 174–175, 183–184, 189–190, 204–205, 208, 51–52, 55, 92, 95, 97
   sse.ts82.29%63.64%85.71%88.06%100, 102–103, 114, 135, 54–55, 58, 81–82, 85, 99, 99, 99, 99, 99
src/task
   config.ts100%100%100%100%

CLAUDE.md duplicated the README: hosted-vs-local setup, env var tables,
command lists, a full directory tree. That content rots and pushes the
useful parts out of an agent's context. The old tree predated both
core/transport/ and core/lean.ts.

Keep only what code and README cannot tell you:

- Five non-obvious invariants — session binding to the token hash, 401
  forwarding needing enableJsonResponse, the lean.ts denylist sparing the
  list envelope so pagination survives, list() vs info() shape divergence,
  and the two API-key env vars split by transport.
- The command-registration convention, including the two extra steps a
  read tool needs to avoid shipping the HAL envelope.
- Two package.json scripts that are broken: watch targets a missing
  index.ts, coverage:verify calls a missing check-coverage.sh.

412 lines to 127.
@menor-pro
menor-pro force-pushed the docs/lean-claude-md branch from 96c5f42 to d70bc79 Compare July 29, 2026 01:36
@github-actions

Copy link
Copy Markdown

Coverage after merging docs/lean-claude-md into main will be

92.64%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   mcpUpsun.ts96%75%100%97.44%171–172
src/command
   activity.ts100%100%100%100%
   backup.ts100%100%100%100%
   certificate.ts100%100%100%100%
   domain.ts100%100%100%100%
   environment.ts98.70%94.44%100%100%339
   organization.ts100%100%100%100%
   project.ts91.49%66.67%100%100%139, 173, 71, 78
   route.ts100%100%100%100%
   ssh.ts100%100%100%100%
src/core
   authentication.ts85.71%77.08%95%88.89%113–114, 133, 218–219, 221, 296–298, 321, 332–333, 353–354, 354, 354, 354, 354–355
   config.ts91.47%91.04%100%91.04%121, 133, 140, 140, 140, 140, 142, 145, 149, 156, 156, 160, 162, 316, 353, 36, 51, 62
   gateway.ts80.52%100%66.67%81.67%261–264, 288, 291–292, 294–295, 299, 303
   helper.ts89.84%81.48%100%91.43%208–209, 241–242, 337, 341–342, 349, 353, 422–424, 461–462, 512–513, 517, 544–545
   lean.ts90.70%88.89%100%90.91%85, 88, 91, 95
   logger.ts98.61%96.15%100%100%83
   requestContext.ts100%100%100%100%
   telemetry.ts92.09%88.57%100%92.55%163, 200–201, 250–251, 299–300, 350–351, 372–373
   types.ts100%100%100%100%
src/core/transport
   http.ts83.56%80%81.25%85.26%102, 102, 102–103, 158–159, 174–175, 183–184, 189–190, 204–205, 208, 51–52, 55, 92, 95, 97
   sse.ts82.29%63.64%85.71%88.06%100, 102–103, 114, 135, 54–55, 58, 81–82, 85, 99, 99, 99, 99, 99
src/task
   config.ts100%100%100%100%

@menor

menor commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Merge order: #29 first. It fixes the broken watch script and removes the unused coverage:verify. The latest commit here then drops the stale broken-scripts warning from the Quick loop section.

@github-actions

Copy link
Copy Markdown

Coverage after merging docs/lean-claude-md into main will be

92.64%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   mcpUpsun.ts96%75%100%97.44%171–172
src/command
   activity.ts100%100%100%100%
   backup.ts100%100%100%100%
   certificate.ts100%100%100%100%
   domain.ts100%100%100%100%
   environment.ts98.70%94.44%100%100%339
   organization.ts100%100%100%100%
   project.ts91.49%66.67%100%100%139, 173, 71, 78
   route.ts100%100%100%100%
   ssh.ts100%100%100%100%
src/core
   authentication.ts85.71%77.08%95%88.89%113–114, 133, 218–219, 221, 296–298, 321, 332–333, 353–354, 354, 354, 354, 354–355
   config.ts91.47%91.04%100%91.04%121, 133, 140, 140, 140, 140, 142, 145, 149, 156, 156, 160, 162, 316, 353, 36, 51, 62
   gateway.ts80.52%100%66.67%81.67%261–264, 288, 291–292, 294–295, 299, 303
   helper.ts89.84%81.48%100%91.43%208–209, 241–242, 337, 341–342, 349, 353, 422–424, 461–462, 512–513, 517, 544–545
   lean.ts90.70%88.89%100%90.91%85, 88, 91, 95
   logger.ts98.61%96.15%100%100%83
   requestContext.ts100%100%100%100%
   telemetry.ts92.09%88.57%100%92.55%163, 200–201, 250–251, 299–300, 350–351, 372–373
   types.ts100%100%100%100%
src/core/transport
   http.ts83.56%80%81.25%85.26%102, 102, 102–103, 158–159, 174–175, 183–184, 189–190, 204–205, 208, 51–52, 55, 92, 95, 97
   sse.ts82.29%63.64%85.71%88.06%100, 102–103, 114, 135, 54–55, 58, 81–82, 85, 99, 99, 99, 99, 99
src/task
   config.ts100%100%100%100%

@menor-pro
menor-pro force-pushed the docs/lean-claude-md branch from 257997a to d70bc79 Compare July 29, 2026 05:01
@github-actions

Copy link
Copy Markdown

Coverage after merging docs/lean-claude-md into main will be

92.64%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   mcpUpsun.ts96%75%100%97.44%171–172
src/command
   activity.ts100%100%100%100%
   backup.ts100%100%100%100%
   certificate.ts100%100%100%100%
   domain.ts100%100%100%100%
   environment.ts98.70%94.44%100%100%339
   organization.ts100%100%100%100%
   project.ts91.49%66.67%100%100%139, 173, 71, 78
   route.ts100%100%100%100%
   ssh.ts100%100%100%100%
src/core
   authentication.ts85.71%77.08%95%88.89%113–114, 133, 218–219, 221, 296–298, 321, 332–333, 353–354, 354, 354, 354, 354–355
   config.ts91.47%91.04%100%91.04%121, 133, 140, 140, 140, 140, 142, 145, 149, 156, 156, 160, 162, 316, 353, 36, 51, 62
   gateway.ts80.52%100%66.67%81.67%261–264, 288, 291–292, 294–295, 299, 303
   helper.ts89.84%81.48%100%91.43%208–209, 241–242, 337, 341–342, 349, 353, 422–424, 461–462, 512–513, 517, 544–545
   lean.ts90.70%88.89%100%90.91%85, 88, 91, 95
   logger.ts98.61%96.15%100%100%83
   requestContext.ts100%100%100%100%
   telemetry.ts92.09%88.57%100%92.55%163, 200–201, 250–251, 299–300, 350–351, 372–373
   types.ts100%100%100%100%
src/core/transport
   http.ts83.56%80%81.25%85.26%102, 102, 102–103, 158–159, 174–175, 183–184, 189–190, 204–205, 208, 51–52, 55, 92, 95, 97
   sse.ts82.29%63.64%85.71%88.06%100, 102–103, 114, 135, 54–55, 58, 81–82, 85, 99, 99, 99, 99, 99
src/task
   config.ts100%100%100%100%

@github-actions

Copy link
Copy Markdown

Coverage after merging docs/lean-claude-md into main will be

92.64%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   mcpUpsun.ts96%75%100%97.44%171–172
src/command
   activity.ts100%100%100%100%
   backup.ts100%100%100%100%
   certificate.ts100%100%100%100%
   domain.ts100%100%100%100%
   environment.ts98.70%94.44%100%100%339
   organization.ts100%100%100%100%
   project.ts91.49%66.67%100%100%139, 173, 71, 78
   route.ts100%100%100%100%
   ssh.ts100%100%100%100%
src/core
   authentication.ts85.71%77.08%95%88.89%113–114, 133, 218–219, 221, 296–298, 321, 332–333, 353–354, 354, 354, 354, 354–355
   config.ts91.47%91.04%100%91.04%121, 133, 140, 140, 140, 140, 142, 145, 149, 156, 156, 160, 162, 316, 353, 36, 51, 62
   gateway.ts80.52%100%66.67%81.67%261–264, 288, 291–292, 294–295, 299, 303
   helper.ts89.84%81.48%100%91.43%208–209, 241–242, 337, 341–342, 349, 353, 422–424, 461–462, 512–513, 517, 544–545
   lean.ts90.70%88.89%100%90.91%85, 88, 91, 95
   logger.ts98.61%96.15%100%100%83
   requestContext.ts100%100%100%100%
   telemetry.ts92.09%88.57%100%92.55%163, 200–201, 250–251, 299–300, 350–351, 372–373
   types.ts100%100%100%100%
src/core/transport
   http.ts83.56%80%81.25%85.26%102, 102, 102–103, 158–159, 174–175, 183–184, 189–190, 204–205, 208, 51–52, 55, 92, 95, 97
   sse.ts82.29%63.64%85.71%88.06%100, 102–103, 114, 135, 54–55, 58, 81–82, 85, 99, 99, 99, 99, 99
src/task
   config.ts100%100%100%100%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant