From 5ddd76ec39f94f177c7f8a21d6855d822346f421 Mon Sep 17 00:00:00 2001 From: Nick Misasi Date: Fri, 6 Mar 2026 14:19:06 -0500 Subject: [PATCH] Development environment setup (#35513) * Add AGENTS.md with Cursor Cloud development environment instructions - Documents service architecture (Go server + React webapp + PostgreSQL) - Covers how to start services, run lint/tests/builds - Notes key gotchas for dev setup (config auto-generation, client symlink, SMTP errors) - Specifies Node.js 24.11 and Go 1.24.13 version requirements Co-authored-by: Nick Misasi * Update AGENTS.md with dual-repo enterprise development setup - Document enterprise repo at $HOME/enterprise and plugin-agents at $HOME/mattermost-plugin-agents - Add git authentication instructions for cross-repo operations with CURSOR_GH_TOKEN - Document enterprise server build, run, and plugin deployment workflow - Add cross-repo PR workflow instructions - Include BUILD_ENTERPRISE_DIR usage for all make commands Co-authored-by: Nick Misasi * Rewrite AGENTS.md: add plugin config docs, move automatable steps to update script - Add Agents plugin configuration section with full JSON structure and API usage - Document ANTHROPIC_API_KEY requirement and config-must-be-object gotcha - Remove instructions now handled by update script: config.override.mk, client symlink, git insteadOf cleanup, remote URL cleanup - Trim redundant sections for conciseness Co-authored-by: Nick Misasi * AGENTS.md: use make run/restart-server workflow, document TEAM EDITION gotcha - Replace manual go build/run instructions with make run and make restart-server - Emphasize BUILD_ENTERPRISE_DIR must be passed to every make command - Document that 'TEAM EDITION' label is license-dependent, not build-dependent - Add verification steps for confirming enterprise code is loaded Co-authored-by: Nick Misasi * AGENTS.md: add TEST_LICENSE/MM_LICENSE for enterprise licensing - Pass MM_LICENSE=$TEST_LICENSE in make run and make restart-server commands - Document that the license unlocks enterprise features and removes TEAM EDITION badge - Simplify the TEAM EDITION gotcha to focus on the fix Co-authored-by: Nick Misasi * Rename AGENTS.md to AGENTS.CLOUD.md, gitignore AGENTS.md AGENTS.md is a standard file that affects real editors. To avoid impacting non-cloud workflows, the cloud-specific instructions now live in AGENTS.CLOUD.md (committed) and the update script copies it to AGENTS.md (gitignored) on startup so Cursor Cloud agents still pick it up. Co-authored-by: Nick Misasi --------- Co-authored-by: Cursor Agent --- .gitignore | 1 + AGENTS.CLOUD.md | 131 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 AGENTS.CLOUD.md diff --git a/.gitignore b/.gitignore index 3f2a0e8e900..8ed1d5c54e1 100644 --- a/.gitignore +++ b/.gitignore @@ -162,5 +162,6 @@ docker-compose.override.yaml **/CLAUDE.local.md **/CLAUDE.md +AGENTS.md .cursorrules .cursor/ diff --git a/AGENTS.CLOUD.md b/AGENTS.CLOUD.md new file mode 100644 index 00000000000..23257d2b25a --- /dev/null +++ b/AGENTS.CLOUD.md @@ -0,0 +1,131 @@ +# AGENTS.md + +## Cursor Cloud specific instructions + +### Overview + +This is a **dual-repo** Mattermost enterprise development environment: + +| Repository | Location | Purpose | +|------------|----------|---------| +| `mattermost/mattermost` | `/workspace` | Primary monorepo (Go server + React webapp) | +| `mattermost/enterprise` | `$HOME/enterprise` | Private enterprise code (Go, linked via `go.work`) | +| `mattermost/mattermost-plugin-agents` | `$HOME/mattermost-plugin-agents` | AI plugin for validation/testing | + +PostgreSQL 14 is the only required external dependency, run via Docker Compose. + +The update script handles: git auth, repo cloning, npm install, Go workspace setup, config.override.mk, and the client symlink. See below for what remains manual. + +### Starting services + +After the update script has run: + +1. **Start Docker daemon** (if not already running): `sudo dockerd &>/tmp/dockerd.log &` — wait a few seconds, verify with `docker info`. +2. **Start server + webapp together:** + ``` + cd /workspace/server && \ + MM_LICENSE="$TEST_LICENSE" \ + MM_PLUGINSETTINGS_ENABLEUPLOADS=true \ + MM_PLUGINSETTINGS_ENABLE=true \ + MM_SERVICESETTINGS_SITEURL=http://localhost:8065 \ + make BUILD_ENTERPRISE_DIR="$HOME/enterprise" run + ``` + This single command starts Docker (postgres), builds mmctl, sets up the `go.work` and client symlink, compiles the Go server with enterprise tags, runs it in the background, then starts the webpack watcher for the webapp. The server listens on `:8065`. +3. **Restart server after code changes:** + ``` + cd /workspace/server && \ + MM_LICENSE="$TEST_LICENSE" \ + make BUILD_ENTERPRISE_DIR="$HOME/enterprise" restart-server + ``` + This stops the running server and re-runs it with enterprise. Webapp changes are picked up by webpack automatically (browser refresh needed). + +The `TEST_LICENSE` secret provides a Mattermost Enterprise Advanced license. When set via `MM_LICENSE`, the server logs `"License key from ENV is valid, unlocking enterprise features."` and the "TEAM EDITION" badge disappears from the UI. + +**You MUST pass `BUILD_ENTERPRISE_DIR="$HOME/enterprise"` to every `make` command** — `run`, `restart-server`, `run-server`, `test-server`, `check-style`, etc. Without it, the Makefile defaults to `../../enterprise` (which doesn't exist), and the build silently falls back to team edition. + +### Agents plugin configuration + +The plugin is deployed from `$HOME/mattermost-plugin-agents` using: +``` +cd $HOME/mattermost-plugin-agents && MM_SERVICESETTINGS_SITEURL=http://localhost:8065 make deploy +``` + +To configure a service and agent, patch the Mattermost config API. The `ANTHROPIC_API_KEY` environment variable must be set. + +**Critical gotcha:** The `config` field under `mattermost-ai` must be a JSON **object**, not a JSON string. If stored as a string, the plugin logs `LoadPluginConfiguration API failed to unmarshal`. + +Example config patch (use python to safely inject the API key from env): +```python +import json, os +config = { + "PluginSettings": { + "Plugins": { + "mattermost-ai": { + "config": { # MUST be an object, NOT json.dumps(...) + "services": [{ + "id": "anthropic-svc-001", + "name": "Anthropic Claude", + "type": "anthropic", + "apiKey": os.environ["ANTHROPIC_API_KEY"], + "defaultModel": "claude-sonnet-4-6", + "tokenLimit": 200000, + "outputTokenLimit": 16000, + "streamingTimeoutSeconds": 300 + }], + "bots": [{ + "id": "claude-bot-001", + "name": "claude", + "displayName": "Claude Assistant", + "serviceID": "anthropic-svc-001", + "customInstructions": "You are a helpful AI assistant.", + "enableVision": True, + "disableTools": False, + "channelAccessLevel": 0, + "userAccessLevel": 0, + "reasoningEnabled": True, + "thinkingBudget": 1024 + }], + "defaultBotName": "claude" + } + } + } + } +} +# Write to temp file, then: curl -X PUT http://localhost:8065/api/v4/config/patch -H "Authorization: Bearer $TOKEN" -d @file.json +``` + +Supported service types: `openai`, `openaicompatible`, `azure`, `anthropic`, `asage`, `cohere`, `bedrock`, `mistral`. The API key goes in `services[].apiKey`. Never log or print it. + +### Key gotchas + +- **"TEAM EDITION" means no license, not no enterprise code.** The webapp shows "TEAM EDITION" when `license.IsLicensed === 'false'`, regardless of `BuildEnterpriseReady`. Fix: pass `MM_LICENSE="$TEST_LICENSE"` when starting the server. To verify enterprise code is loaded independently: check server logs for `"Enterprise Build", enterprise_build: true` or the API at `/api/v4/config/client?format=old` for `BuildEnterpriseReady: true`. +- The server auto-generates `server/config/config.json` on first run; default SQL points to `postgres://mmuser:mostest@localhost/mattermost_test` matching Docker Compose. +- The first user created via `/api/v4/users` gets `system_admin` role automatically. +- SMTP errors and plugin directory warnings on startup are expected in dev — non-blocking. +- License errors in logs ("Failed to read license set in environment") are normal — enterprise features requiring a license won't be available but the server runs fine. +- The enterprise repo must be on a compatible branch with the main repo. +- The VM's global gitconfig may have `url.*.insteadOf` rules embedding the default Cursor agent token, which only has access to `mattermost/mattermost`. The update script cleans these and sets up `gh auth` with `CURSOR_GH_TOKEN` instead. + +### Lint, test, and build + +**Server (with enterprise):** all commands from `/workspace/server/`, always include `BUILD_ENTERPRISE_DIR="$HOME/enterprise"`: +- **Run:** `make BUILD_ENTERPRISE_DIR="$HOME/enterprise" run` +- **Restart:** `make BUILD_ENTERPRISE_DIR="$HOME/enterprise" restart-server` +- **Lint:** `make BUILD_ENTERPRISE_DIR="$HOME/enterprise" check-style` +- **Tests:** `make BUILD_ENTERPRISE_DIR="$HOME/enterprise" test-server` (needs Docker). Quick: `go test ./public/model/...` +- **Standalone build:** `make BUILD_ENTERPRISE_DIR="$HOME/enterprise" build-linux` (or use `go build -tags 'enterprise sourceavailable' ...` directly) + +**Webapp:** run from `/workspace/webapp/` +- **Lint:** `npm run check` +- **Tests:** `npm run test` (Jest 30) +- **Type check:** `npm run check-types` +- **Build:** `npm run build` + +### Cross-repo PR workflow + +When changes span both repos, create branches and PRs independently. Use `gh pr create --repo mattermost/mattermost ...` and `gh pr create --repo mattermost/enterprise ...`. Link companion PRs in the body and state merge order. + +### Versions + +- Node.js: see `.nvmrc` (currently `24.11`); `nvm use` from workspace root. +- Go: see `server/go.mod` (currently `1.24.13`).