Skip to content

Latest commit

 

History

History
314 lines (222 loc) · 8.89 KB

File metadata and controls

314 lines (222 loc) · 8.89 KB

Development

Prerequisites

Quick Start

bun install
bun run pg
# configure .env (see below)
bun run setup
bun run server
# in another terminal:
bun run packages/cli/index.ts --server http://localhost:3000 login

Step by Step

1. Install dependencies

bun install

2. Start PostgreSQL

The project requires PostgreSQL 18 with three extensions: pgvector, pg_textsearch, and ltree. The included Dockerfile builds a pre-configured image:

bun run pg

This builds the Docker image and starts a container named me-postgres on localhost:5432 with trust authentication (no password).

Other database commands:

Command Description
bun run pg:rm Stop and remove the container
bun run psql Connect with psql

3. Configure .env

Copy the sample and fill in the required values:

cp .env.sample .env

Required variables

Database connections — both point to the local Docker Postgres, but use separate databases:

ACCOUNTS_DATABASE_URL=postgres://postgres@localhost:5432/accounts
ENGINE_DATABASE_URL=postgres://postgres@localhost:5432/shard1

Encryption master key — 32-byte hex string for encrypting API keys at rest:

bun run generate:master-key

Paste the output into .env:

ACCOUNTS_MASTER_KEY=<output from above>

Server URL and portAPI_BASE_URL is used to construct OAuth callback URLs. PORT controls which port the server listens on. They must be consistent:

API_BASE_URL=http://localhost:3000
PORT=3000

If you change the port (e.g. because something else is on 3000), update both:

API_BASE_URL=http://localhost:3132
PORT=3132

Embedding API key — an OpenAI API key (or compatible provider):

EMBEDDING_API_KEY=sk-...

OAuth provider (at least one required)

Google:

  1. Go to Google Cloud Console > Credentials
  2. Create an OAuth client ID (Web application)
  3. Add authorized redirect URI: http://localhost:<PORT>/api/v1/auth/callback/google
  4. Copy the client ID and secret:
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...

GitHub:

  1. Go to GitHub Developer Settings
  2. Create a new OAuth App
  3. Set the callback URL to: http://localhost:<PORT>/api/v1/auth/callback/github
  4. Copy the client ID and secret:
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...

The redirect URI must match your API_BASE_URL exactly, including the port.

Complete .env example

# Database
ACCOUNTS_DATABASE_URL=postgres://postgres@localhost:5432/accounts
ENGINE_DATABASE_URL=postgres://postgres@localhost:5432/shard1
ACCOUNTS_MASTER_KEY=<bun run generate:master-key>

# Server
API_BASE_URL=http://localhost:3000
PORT=3000

# Embedding
EMBEDDING_API_KEY=sk-...

# OAuth (at least one)
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...

# Telemetry (optional) — omit to disable
# LOGFIRE_TOKEN=...
# LOGFIRE_ENVIRONMENT=dev

4. Run setup

bun run setup

This is idempotent (safe to run multiple times) and will:

  1. Create the accounts and shard1 databases if they don't exist
  2. Run account schema migrations
  3. Create and activate an encryption data key
  4. Bootstrap the engine database (extensions and roles)

5. Start the server

bun run server

6. Test with the CLI

In another terminal:

bun run packages/cli/index.ts --server http://localhost:3000 login

Or set ME_SERVER to avoid passing --server every time:

export ME_SERVER=http://localhost:3000
bun run packages/cli/index.ts login

After login, the server URL is stored as the default in ~/.config/me/credentials.yaml, so subsequent commands don't need --server.

All Commands

Command Description
bun run server Start the server
bun run setup Create databases, run migrations, bootstrap engine
bun run pg Build and start PostgreSQL in Docker
bun run pg:rm Stop and remove the PostgreSQL container
bun run psql Connect to PostgreSQL with psql
bun run test Run tests
bun run check Format + lint + typecheck
bun run build Compile CLI binary (current platform)
bun run build:all Cross-compile CLI for all platforms
bun run install:local Build and install local CLI binary to your PATH
bun run clean Remove build artifacts
bun run generate:master-key Generate a new encryption master key
bun run release:client Cut a client release (CLI + npm packages)
bun run release:server Cut a server release (deploys to prod)

Releases

The client (CLI, npm packages) and the server (deployed container) are released independently. They carry separate version counters, use separate tag prefixes, and are triggered by separate scripts.

Two versions

Constant Source of truth Exposed via
CLIENT_VERSION root package.json me --version, MCP handshake, npm-published packages
SERVER_VERSION packages/server/package.json Logfire serviceVersion, migration applied_at_version and <schema>.version, gitRevision fallback in prod

Both are exported from version.ts. Migration tracking — including the downgrade-rejection guard in the runners — uses SERVER_VERSION, so the DB's recorded version advances only when the server is released.

Two scripts

bun run release:client — bumps the version in:

  • package.json
  • packages/cli/package.json
  • packages/client/package.json
  • packages/protocol/package.json

Commits, creates an annotated tag v<version>, and pushes.

The v* tag triggers .github/workflows/release.yml, which:

  • Publishes @memory.build/protocol and @memory.build/client to npm.
  • Builds the me CLI for all platforms.
  • Creates a GitHub Release with the binaries.
  • Publishes the CLI wrapper to npm.
  • Updates the Homebrew formula.

bun run release:server — bumps the version in the server-side packages in lockstep:

  • packages/accounts/package.json
  • packages/embedding/package.json
  • packages/engine/package.json
  • packages/server/package.json (canonical source)
  • packages/worker/package.json

Commits, creates an annotated tag server/v<version>, and pushes.

The server/v* tag triggers .github/workflows/deploy-prod.yaml, which builds the server image from packages/server/Dockerfile and deploys it to prod.

The dev environment is redeployed automatically by .github/workflows/deploy-dev.yaml on every push to main that touches a server path — no tag required.

Usage

bun run release:client 0.2.0       # explicit version
bun run release:client patch       # 0.1.16 -> 0.1.17
bun run release:client minor       # 0.1.16 -> 0.2.0
bun run release:client             # prompts for version

bun run release:server patch       # same arg shapes; tags server/v<...>

Both scripts require:

  • Clean working tree, on main, up to date with origin/main.
  • Version strictly greater than the current one.
  • Tag doesn't already exist.
  • Explicit y confirmation at the prompt.

Typical workflow

Because the client and server release independently, the typical sequence for a change that spans both sides is:

  1. Land a backwards-compatible server change on main. Dev auto-deploys.
  2. bun run release:server to tag server/v<next> and deploy prod.
  3. Land the client change on main that depends on the new server behavior.
  4. bun run release:client to publish the CLI and npm packages.

The server counter and the client counter will diverge over time — that's expected. They're not related after this split.

Adding a migration

Database migrations run at server startup using SERVER_VERSION as the serverVersion passed to the runners. When you add a new migration file under packages/engine/migrate/migrations/ or packages/accounts/migrate/migrations/:

  • Cut a server release afterwards (bun run release:server) to advance SERVER_VERSION and propagate the migration to prod.
  • The migration's applied_at_version column and the schema's version row will reflect the new SERVER_VERSION.
  • Rolling back to an older server image will then trip the downgrade guard in the migration runners — by design.

Troubleshooting

CLI says "Failed to start device flow: HTTP 405"

The CLI defaults to http://localhost:3000. If your server is on a different port, pass --server http://localhost:<PORT> or set ME_SERVER.

Google OAuth "redirect_uri_mismatch"

The redirect URI registered in Google Cloud Console must exactly match <API_BASE_URL>/api/v1/auth/callback/google, including the port.

API_BASE_URL vs PORT

PORT controls where the server listens. API_BASE_URL is used to build OAuth callback URLs sent to providers. If they don't match, OAuth callbacks will fail.