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 <nick13misasi@gmail.com>

* 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 <nick13misasi@gmail.com>

* 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 <nick13misasi@gmail.com>

* 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 <nick13misasi@gmail.com>

* 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 <nick13misasi@gmail.com>

* 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 <nick13misasi@gmail.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
Nick Misasi
2026-03-06 19:19:06 +00:00
committed by GitHub
co-authored by Nick Misasi Cursor Agent
parent e31f471498
commit 5ddd76ec39
2 changed files with 132 additions and 0 deletions
+1
View File
@@ -162,5 +162,6 @@ docker-compose.override.yaml
**/CLAUDE.local.md
**/CLAUDE.md
AGENTS.md
.cursorrules
.cursor/
+131
View File
@@ -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`).