mattermost/examples/hello_python/CLAUDE.md
Nick Misasi 9b43bb3542 docs(13-04): create example plugin CLAUDE.md
Add AI development guidance for plugin developers using the hello_python
example as a template. Includes setup commands, architecture overview,
hook patterns, API usage, and best practices.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 10:41:03 -05:00

2.5 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with Mattermost Python plugins.

Repository Purpose

This is an example Mattermost Python plugin demonstrating the Python Plugin SDK. Use it as a template for building your own Python plugins.

Key Commands

Setup

# Create virtual environment with SDK
make venv

# Activate the environment
source venv/bin/activate

Development

# Run linting
make lint

# Package for upload to Mattermost
make dist

Packaging

# Create plugin bundle (includes vendored SDK)
make dist

# Create minimal bundle (server must have SDK installed)
make dist-minimal

# Clean build artifacts
make clean

Architecture Overview

Plugin Structure

  • plugin.json - Plugin manifest defining metadata and runtime
  • plugin.py - Main plugin implementation
  • requirements.txt - Python dependencies

Plugin Implementation Pattern

from mattermost_plugin import Plugin, hook, HookName

class MyPlugin(Plugin):
    @hook(HookName.OnActivate)
    def on_activate(self) -> None:
        self.logger.info("Plugin activated!")
        # Initialize state, register commands

    @hook(HookName.MessageWillBePosted)
    def filter_message(self, context, post):
        # Return (post, "") to allow, (None, "reason") to reject
        return post, ""

if __name__ == "__main__":
    from mattermost_plugin.server import run_plugin
    run_plugin(MyPlugin)

Available Hooks

  • OnActivate / OnDeactivate - Lifecycle events
  • MessageWillBePosted / MessageHasBeenPosted - Message filtering
  • ExecuteCommand - Slash command handling
  • ServeHTTP - HTTP endpoint handling
  • See mattermost_plugin.HookName for full list

API Client Usage

# In any hook handler, use self.api:
user = self.api.get_user(user_id)
self.api.create_post(post)
self.api.kv_set("key", value_bytes)

Best Practices

  1. Logging: Use self.logger instead of print()
  2. Error Handling: Wrap API calls in try/except
  3. State: Use KV store for persistent state, not module-level variables
  4. Commands: Register commands in OnActivate, they persist across restarts
  5. Testing: Test locally before packaging

Manifest Format (plugin.json)

{
  "id": "com.example.my-plugin",
  "name": "My Plugin",
  "version": "1.0.0",
  "min_server_version": "10.0.0",
  "server": {
    "executable": "plugin.py",
    "runtime": "python",
    "python_version": ">=3.9"
  }
}