smithery.ai

gptme-plugin-development

Guide to creating gptme plugins with tools, hooks, and commands.

First seen Apr 1, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0
Allowed toolsRead, Write, Edit, Bash

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,386 B
  • docs SUMMARY.md 96 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

gptme Plugin Development

Description: Guide to creating gptme plugins with tools, hooks, and commands.

When to Use Plugins vs Skills/Lessons

Need Use Why
Share knowledge/workflows Skills/Lessons Lightweight bundles, no runtime
Custom tools (new actions) Plugins Extend capabilities via Python
Runtime hooks (lifecycle) Plugins Deep integration with gptme
Custom commands (/cmd) Plugins Add CLI commands

Plugin Structure

my_plugin/
├── pyproject.toml           # Package metadata + dependencies
├── README.md                # Documentation
├── src/
│   └── gptme_my_plugin/    # Package name
│       ├── __init__.py      # Simple init (avoid heavy imports)
│       └── tools/
│           └── __init__.py  # ToolSpec definitions
└── tests/
    └── test_my_plugin.py    # Tests

Step-by-Step: Creating a Tool Plugin

1. Create pyproject.toml

[project]
name = "gptme-my-plugin"
version = "0.1.0"
description = "My custom gptme plugin"
requires-python = ">=3.10"
dependencies = [
    "gptme>=0.27.0",  # Required for ToolSpec, etc.
]

[project.optional-dependencies]
test = [
    "pytest>=8.0.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/gptme_my_plugin"]

2. Create Simple init.py

Keep it simple to avoid import issues:

# src/gptme_my_plugin/__init__.py
"""My gptme plugin description."""

__version__ = "0.1.0"

Important: Don't import hooks or complex gptme internals here - it can cause import errors in tests.

3. Create the Tool

# src/gptme_my_plugin/tools/__init__.py
"""My plugin tools."""

from gptme.tools.base import ToolSpec, ToolUse


def my_function(arg1: str, arg2: int = 10) -> str:
    """
    Do something useful.

    Args:
        arg1: Description of arg1
        arg2: Description of arg2 (default: 10)

    Returns:
        Result description
    """
    return f"Result: {arg1} x {arg2}"


def examples(tool_format):
    return f'''
### Example usage
User: Do the thing
Assistant: I'll use my_function.
{ToolUse("ipython", [], "my_function('test', 5)").to_output(tool_format)}
'''


tool = ToolSpec(
    name="my_plugin",
    desc="Short description for tool list",
    examples=examples,
    functions=[my_function],
)

__doc__ = tool.get_doc(__doc__)

4. Write Tests

# tests/test_my_plugin.py
"""Tests for my plugin."""

from gptme_my_plugin.tools import my_function


def test_my_function():
    """Test the main function."""
    result = my_function("hello", 3)
    assert "hello" in result
    assert "3" in result

5. Run Tests

# From plugin directory
cd plugins/my_plugin

# Using uv in workspace
uv run pytest tests/ -v

# Or install and test
uv pip install -e ".[test]"
uv run pytest tests/ -v

Adding Hooks

For lifecycle hooks (SESSIONSTART, TOOLPRE_EXECUTE, etc.):

# src/gptme_my_plugin/hooks/__init__.py
from gptme.hooks import HookType, register_hook
from gptme.message import Message


def on_session_start(logdir, workspace, initial_msgs):
    """Hook called at session start."""
    yield Message("system", f"Plugin loaded in: {workspace}")


def register():
    """Register all hooks from this module."""
    register_hook(
        "my_plugin.session_start",
        HookType.SESSION_START,
        on_session_start,
        priority=0,
    )

Available Hook Types:

  • SESSIONSTART, SESSIONEND - Session lifecycle
  • TOOLPREEXECUTE, TOOLPOSTEXECUTE - Tool execution
  • FILEPRESAVE, FILEPOSTSAVE - File operations
  • GENERATIONPRE, GENERATIONPOST - LLM generation

Adding Commands

For custom /command handlers:

# src/gptme_my_plugin/commands/__init__.py
from gptme.commands import register_command, CommandContext
from gptme.message import Message


def my_command_handler(ctx: CommandContext):
    """Handle the /mycommand command."""
    args = ctx.full_args or "default"
    yield Message("system", f"Command executed with: {args}")


def register():
    register_command("mycommand", my_command_handler, aliases=["mc"])

Common Patterns

Optional Dependencies

For provider-specific features:

[project.optional-dependencies]
gemini = ["google-genai>=1.0.0"]
openai = ["openai>=1.0.0"]

Getting API Keys

def _get_api_key(env_var: str) -> str | None:
    """Get API key from gptme config first, then environment."""
    try:
        from gptme.config import get_config
        return get_config().get_env(env_var)
    except ImportError:
        import os
        return os.environ.get(env_var)

Fallback Imports

For standalone usage:

def _get_logs_dir():
    try:
        from gptme.dirs import get_logs_dir
        return get_logs_dir()
    except ImportError:
        from pathlib import Path
        return Path.home() / ".local" / "share" / "gptme" / "logs"

Testing with logs_dir Parameter

Make functions testable by adding optional parameters:

def my_stats(year: int | None = None, logs_dir: Path | None = None):
    if logs_dir is None:
        logs_dir = _get_logs_dir()
    # Use logs_dir...

Then in tests:

def test_my_stats(tmp_path):
    # Create test data in tmp_path
    result = my_stats(2025, logs_dir=tmp_path)
    assert result["year"] == 2025

Installation & Configuration

Configure plugins in gptme.toml at user-level (~/.config/gptme/config.toml) or project-level (gptme.toml in workspace root):

[plugins]
paths = ["~/.config/gptme/plugins", "/path/to/plugins"]
enabled = ["my_plugin"]  # Optional: limit which plugins load

See gptme Plugin Docs for full configuration details.

For Development

# Install in editable mode
uv pip install -e .

# Or in workspace
uv sync

Troubleshooting

Module Not Found in Tests

Problem: ModuleNotFoundError: No module named 'gptmemyplugin'

Solution: Ensure you're running tests from the workspace environment:

cd /path/to/gptme-contrib
uv run pytest plugins/my_plugin/tests/ -v

Import Errors from init.py

Problem: Complex imports in init.py cause import failures

Solution: Keep init.py minimal:

# Bad
from gptme.plugins import hookimpl, PluginMetadata  # May fail

# Good
__version__ = "0.1.0"

Environment Mismatch

Problem: uv installs to different env than pytest runs from

Solution: Use uv run to ensure consistent environment:

uv run pytest tests/ -v

Examples in gptme-contrib

  • wrapped: Analytics tool with tests
  • imagen: Multi-provider image generation
  • lsp: Language server integration
  • consortium: Multi-model consensus
  • example-hooks: Hook registration patterns

Related