DreamLake

Onboarding — for the next person

Read this first if you've just been handed the keys. It assumes Python + TypeScript + a little Rust, and that you know roughly what Lakeshore does. It does not assume you have seen the repos before.

By the end you should be able to boot a local stack, run the smoke test, ship a docs change, and know where to look when something breaks.

The shape

Lakeshore is not a monorepo. Every component is an independent repository with its own tests, lockfile, CI, and release cadence. There are no workspace:* dependencies across them and no cross-repo source imports; anything shared has to become a published package.

lakeshore-docs — the repo you are reading — owns the docs site, the local-dev tooling (mprocs.yaml, docker-compose.yml, scripts/dev-up.sh), and the version-coordination scripts. It does not contain the sibling checkouts.

lakeshore-docs/                 (dreamlake-ai/lakeshore-docs)
├── docs/                       the docs site — Vike + MDX → Netlify
├── dev/                        design notes + local daemon config
├── scripts/                    dev-up.sh, dev-down.sh, smoke-exec.sh, version tooling
├── mprocs.yaml                 local-dev pane definitions
├── docker-compose.yml          the local Mongo
└── netlify.toml

To get the whole stack side by side, clone the container repo — it carries each sibling as a submodule:

bash
git clone --recurse-submodules \
  https://github.com/dreamlake-ai/lakeshore-workspace.git
export LAKESHORE_WORKSPACE=~/lakeshore-workspace

Repo map

DirectoryLanguageSource repoDistribution
lakeshore/TypeScriptdreamlake-ai/lakeshorenpm: @dreamlake/lakeshore
lakeshore-controlplane/TypeScript (Fastify 5 + Prisma 5)dreamlake-ai/lakeshore-controlplaneHeroku — live at api.lakeshore.dreamlake.ai
lakeshore-py/Python (httpx + msgpack)dreamlake-ai/dreamlake-lakeshorePyPI: dreamlake-lakeshore
nymph/Rust (tokio + reqwest)dreamlake-ai/nymphCloudflare R2 (publish = false — never on crates.io)
lakeshore-web/TypeScriptdreamlake-ai/lakeshore-webNetlify — demo.lakeshore.dreamlake.ai
lakeshore-examples/Python + YAMLdreamlake-ai/lakeshore-examplesnot published; clone and run
lakeshore-docs/MDXdreamlake-ai/lakeshore-docsNetlify — lakeshore.dreamlake.ai

Spending your first hour

mprocs drives the local stack. Only the db pane autostarts; everything else is opt-in with s on the pane.

bash
cd $LAKESHORE_WORKSPACE
mprocs
# `db` (Mongo) autostarts. Press `s` on `lakeshore` (control plane),
# then `s` on `nymph` (the Rust daemon).

Then, from a shell:

bash
export LAKESHORE_URL=http://localhost:8080
lakeshore daemon list          # one row, state=active

./scripts/smoke-exec.sh        # ten-section exec smoke, bails on first failure

scripts/dev-up.sh is the non-interactive equivalent of the db + lakeshore + nymph panes — background processes, logs under /tmp/lakeshore-dev/*.log, idempotent, torn back down with scripts/dev-down.sh.

For the docs site itself:

bash
pnpm install
pnpm dev          # → http://localhost:5173
LAKESHORE_URL, not LAKESHORE_SERVER

Every CLI command except the auth group resolves the control plane from LAKESHORE_URL (with LAKESHORE_NAMESPACE, default default). LAKESHORE_SERVER is read only by lakeshore auth login/status. Setting the wrong one is the most common "why is it not talking to my local stack" bug. Note also that when LAKESHORE_URL is set the CLI sends no bearer token at all — it deliberately bypasses the saved auth file.

How each component releases

Each repo ships on its own. You can release one without touching any other.

CLI (lakeshore/ → npm)

bash
cd $LAKESHORE_WORKSPACE/lakeshore
# bump version in package.json
pnpm build
pass otp npmjs && pnpm publish --access public

The npm OTP expires fast — generate it immediately before publishing.

Python SDK (lakeshore-py/ → PyPI)

bash
cd $LAKESHORE_WORKSPACE/lakeshore-py
# bump version in pyproject.toml
uv build
uv publish dist/dreamlake_lakeshore-<ver>*

Daemon (nymph/ → R2)

CI builds on a v* tag push, for three targets: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, and aarch64-apple-darwin. Intel macOS was dropped. Each target ships a .tar.gz (for scripts/install.sh) and a raw binary (for the OTA path), each with a .sha256 sidecar, into the R2 bucket lakeshore-releases under dreamlake/nymph/<version>/.

bash
cd $LAKESHORE_WORKSPACE/nymph
# bump Cargo.toml version
git commit -am "chore: release nymph X.Y.Z"
git push origin main
git tag vX.Y.Z && git push origin vX.Y.Z

Control plane (lakeshore-controlplane/ → Heroku)

bash
cd $LAKESHORE_WORKSPACE/lakeshore-controlplane
pnpm staging   # git push -f origin HEAD:heroku-staging
pnpm prod      # git push -f origin HEAD:heroku-production

No version bump — the deploy is git-sha based. See Deployment for the env-var contract and the schema-push step.

Docs site (this repo → Netlify)

A push to main gets you a branch-deploy preview, not production. Production is a command:

bash
pnpm set-version 0.X.Y    # rewrites root + docs/ package.json together
pnpm install              # refresh the lockfile
git commit -am "release(docs): v0.X.Y"
pnpm prod                 # v/0.X.Y snapshot + build + netlify-production

pnpm prod refuses to run when the two package.json versions disagree.

Where to look when something breaks

SymptomFirst place
lakeshore exec hangs locally/tmp/lakeshore-dev/nymph.log and controlplane.log, or the mprocs panes
CLI says "server not configured"LAKESHORE_URL unset and no saved auth login
CP build fails on the Heroku pushThe push output — usually Prisma schema drift or a stale pnpm-lock.yaml
Daemon registers but gets no workCheck Worker.queues — default-queue membership is the empty array, not a literal "default" entry
Nymph won't build with gcc-11 not foundA stale CC export. unset CC, or use the mprocs nymph pane, which forces CC=clang
Docs site 404s a new pagedocs/pages/<slug>/+Page.mdx needs all three required frontmatter fields (title, section, order)
pnpm install says the lockfile is out of syncSomeone bumped a dep without committing pnpm-lock.yaml. Re-run and commit it — Netlify uses --frozen-lockfile

Reading the design notes

Everything under /dev/* is internal design rationale — hidden from the public sidebar, reachable by URL. Each is the source of truth for its concept; the public pages are user-facing distillations. Start with:

Rough edges that bite everyone

  1. Two config-file families, easily conflated. .dreamrc is the YAML with !providers.<Kind> tags (providers + modes, seven-step resolution chain including a server pull). .lakeshore / .lakeshore.local hold project defaults for daemon launch and are walked up from cwd, stopping at the git root. lakeshore.yaml is the compose file for up/down/ps/status/logs, and is looked up in cwd only.

  2. Compose verbs are top level. lakeshore up, down, ps, status, logs — there is no lakeshore compose command, even though the source lives in src/cli/compose/.

  3. The Python SDK reads LAKESHORE_URL + LAKESHORE_CLIENT_TOKEN. The legacy name LAKESHORE_TOKEN still works with a one-time stderr deprecation warning. With LAKESHORE_URL unset the SDK falls back to a local SQLite plane under LAKESHORE_HOME (default ~/.lakeshore) — tests that "pass locally but not against staging" are usually this.

  4. Heroku does not run Prisma migrations. This project uses schema-push: after changing prisma/schema.prisma, run pnpm prisma db push against the target database yourself.

  5. Nymph's keep_alive_s defaults to 300. A daemon you started for testing exits after five idle minutes. -1 is pool mode (never idle-exit) and 0 exits the moment it goes idle. The local dev config at dev/local-udf-daemon.toml also drops the poll wait so smoke steps don't sit in a long-poll.

  6. Sibling checkouts are independent repos. The container repo pins submodule commits, but each checkout has its own branches and remotes. git status inside a checkout before assuming it matches origin/main.

  7. Parallel git operations on one checkout clobber each other. Two terminals in lakeshore/, one switches branches, the other's working tree silently changes. Use git worktree add for parallel work.

When in doubt

  • Read CLAUDE.md at the root of whichever repo you are in — those are the "what is load-bearing here" briefs.
  • RUNBOOK.md carries copy-paste recipes for smoke, release, and deploy.
  • mprocs.yaml is heavily commented and is the fastest description of the local topology.
  • Git history is short and well-commented; git log --oneline in a sibling repo gives you the whole story.

Welcome aboard.