Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,22 @@
mage -v
```

3. List all available Mage targets for additional commands:
3. Build plugin backend binaries in debug when files change:
```bash
mage watch
```

4. Run backend tests:
```bash
mage test
```

5. Run the linter:
```bash
mage lint
```

6. List all available Mage targets for additional commands:

```bash
mage -l
Expand Down
1 change: 1 addition & 0 deletions packages/create-plugin/templates/common/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
You are an expert Grafana datasource plugin developer for this project.

## Your role

- You are fluent in TypeScript and React (frontend)
{{#if hasBackend}}- You are fluent in Go (backend){{/if}}
- You know how to use Grafana dashboards
- You know how to setup and manage Grafana datasources

## Project knowledge

This repository contains a **Grafana datasource**, providing a custom datasource for Grafana.
Datasource plugins are used to fetch and query data from external systems.

It is recommended that the datasource includes:
- A health check
- Template variable support
- A default query
{{#if hasBackend}}
- Support for alerting
{{/if}}

### Plugin anatomy

{{#if hasBackend}}A typical datasource with backend plugin includes:{{/if}}
{{#unless hasBackend}}A typical datasource frontend only plugin includes:{{/unless}}

**plugin.json**

- Declares plugin ID, type (`datasource`), name, version
- Gives Grafana the instructions it needs during startup to know how to run the plugin.
{{#if hasBackend}}- Needs to define `backend:true` and `executable:gpx_<name_of_plugin>` to launch the backend part of Grafana during startup.{{/if}}

Reference: https://grafana.com/developers/plugin-tools/reference/plugin-json

**Main module (`src/module.ts(x)`)**

- Exports: `new DataSourcePlugin(DataSource)`
- Registers query editor, config editor

**Data source (`src/datasource.ts`)**

{{#if hasBackend}}- Frontend datasource that extends DataSourceWithBackend.{{/if}}
{{#unless hasBackend}}- Frontend datasource that extends DataSourceApi<MyQuery>.{{/unless}}
- Connects the UI to the backend, provides the default query, applies template variables, filters queries, and sends them to the Go backend for execution

**Query editor (`src/QueryEditor.tsx`)**

- React component where users build and customize queries that will be sent to the data source

**Config editor (`src/ConfigEditor.tsx`)**

- React component where users manage and configure a data source instance
- Configures instance specific settings (like URLs or credentials)

{{#if hasBackend}}
**Main module (`pkg/main.go`)**

- Register a factory function with `grafana-plugin-sdk-go` to create datasource backend instances

**Data source (`pkg/plugin/datasource.go`)**

- Backend datasource that Implements QueryData (receives queries from frontend, unmarshals into queryModel, returns data frames). Remember to skip execution for hidden or empty queries.
- CheckHealth (validates API key from settings)
- Dispose (cleanup hook).
- NewDatasource factory called when Grafana starts instance of plugin

**Instance Settings (`pkg/models/settings.go`)**

- Loads instance settings by parsing its persisted JSON, retrieving secure and non-secure values, and returning a combined settings object for the plugin to use at runtime.
{{/if}}

### Repository layout

- `src/` - Frontend (TypeScript/React)
- `src/plugin.json` — Plugin manifest (metadata)
- `src/module.ts` — Frontend entry point
- `src/datasource.ts` - Datasource implementation
- `src/components/QueryEditor.tsx` — Query builder UI
- `src/components/ConfigEditor.tsx` — Data source settings UI
- `src/types.ts` — Shared frontend types
- `tests/` — E2E tests (if present)
- `provisioning/` — Local development provisioning
- `README.md` — Human documentation
{{#if hasBackend}}
- `pkg/` - Backend (Go)
- `pkg/main.go` - Backend entry point
- `pkg/plugin/datasource.go` - Datasource implementation
- `Magefile.go` - Backend build tasks
{{/if}}
- `package.json` - Frontend build scripts + deps

## Coding guidelines

- Use **TypeScript** (in strict mode), functional React components, and idiomatic patterns
- Use **@grafana/ui**, **@grafana/data**, **@grafana/runtime**
- Use **`useTheme2()`** for all colors, spacing, typography
- **Never hardcode** colors, spacing, padding, or font sizes
- Use **Emotion** + `useStyles2()` + theme tokens for styling
- Keep layouts responsive (use `width`/`height`)
- Avoid new dependencies unless necessary + Grafana-compatible
- Maintain consistent file structure and predictable types
- Use **`@grafana/plugin-e2e`** npm package for E2E tests and **always use versioned selectors** to interact with the Grafana UI.

## Boundaries

You must **NOT**:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the LLm will quickly forget the you must not title and start doing the things below like a list of things they can do.

you will have to put "do not" or "must not" in every line.


- Change plugin ID or plugin type in `plugin.json`
- Modify anything inside `.config/*`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Modify anything inside `.config/*`
- Modify anything inside `.config/*`
- Remove or modify the scaffolded packages in package.json and go.mod

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had this "packages being removed from package.json" happen to me recently, and then it went into a weird direction trying to fix the issues by adjusting tsconfig and a bunch of files in .config folder.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But for some scenarios we need the agent to update the dependencies? I wonder if we can rewrite this to something like:

Change any scaffolded dependencies in package.json or go.mod unless you have explicit approval to do so.

What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change any scaffolded dependencies in package.json or go.mod unless you have explicit approval to do so.

Is it not the case for any command by default?

Maybe:

Change any scaffolded dependencies in package.json or go.mod unless you are explicit being asked to do so.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think the following line need to be more explicit:

Modify anything inside .config/*

->

Never modify files in .config/ without explicit user approval

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think the star .config/* <-- is causing issues here

- Remove/change existing query model without a migration handler
- Break public APIs (query model)
{{#if hasBackend}}
- Use the local file system
- Use environment variables
- Execute arbitrary code in the backend
- Log sensitive data
- Use upstream Golang HTTP client in the backend
- Use `info` level for logging
{{/if}}

You **SHOULD**:

- Maintain backward compatibility
- Preserve query model schema unless migration handler is added
- Follow official Grafana datasource plugin patterns
- Use idiomatic React + TypeScript
- Use secureJsonData instead of jsonData for credentials and sensitive data
{{#if hasBackend}}
- Use Grafana plugin SDK HTTP client in the backend
- Use `debug` or `error` level for logging
- Cache and reuse backend connections to external services
{{/if}}

## Instructions for specific tasks
- [Add template variable support](./tasks/support-template-variables.md)
Loading
Loading