Atlas / Skills / marcus / Create Plugin

Create PluginSAFE

skills/marcus/create-plugin

Use sidecar next to CLI agents for diffs, file trees, conversation history, and task management with td

Verdict
SAFE
Grade
B
Trust score
89 /100
Version
—
Hosts
1 documented
License
MIT
Stars
1,086
01

Overview

Use sidecar next to CLI agents for diffs, file trees, conversation history, and task management with td

Read from source at commit a69114b893d1OBSERVED · 2026-10-10
02

Host compatibility

What the documentation claims. We have not run a compatibility test.

HostStatusNotes
cursormentioned
03

What it tells the agent

The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.

---
name: create-plugin
description: >
  Create new sidecar plugins implementing the plugin.Plugin interface, rendering
  views with Bubble Tea, handling keyboard input via keymap contexts, and
  integrating with the app shell (footer hints, event bus, adapters). Use when
  creating a new plugin, modifying plugin architecture, or debugging plugin
  rendering/lifecycle issues. See references/ for sidebar list and fixed footer
  layout details.
---

# Create Plugin

**This skill is the embedded class: a Go package compiled into Sidecar with its own Bubble Tea UI.** If what you want is a tool's data in Sidecar — a searchable tab, rows that open into documents, panes beside a terminal — you almost certainly want a *protocol* plugin instead: an executable in any language answering five JSON methods, which Sidecar renders itself and which ships as a config entry rather than a Sidecar release. Read [docs/guides/active/creating-plugins.md](../../../docs/guides/active/creating-plugins.md) and stop here. Come back only when the screen itself is the point — a board, a queue, a layout the collection-and-document vocabulary cannot express — because everything below costs a release, a keymap pass, and a permanent place in the repository.

## Architecture Overview

- **Bubble Tea model**: `internal/app/model.go` owns the active plugin index, dispatches key events, renders plugin views.
- **Registry**: `internal/plugin/registry.go` stores plugins, handles lifecycle with panic protection, keeps an `unavailable` map when `Init` fails (silent degradation).
- **Plugin contract**: `internal/plugin/plugin.go` defines the interface every plugin must satisfy.
- **Context**: `internal/plugin/context.go` provides `WorkDir`, `ConfigDir`, `Adapters`, `EventBus`, `Logger`, `Epoch`, and `Keymap`.
- **Keymap**: `internal/keymap` maps keys to command IDs. Footer/help reads bindings by context using `Plugin.Commands()` + `Plugin.FocusContext()`.

## Plugin Interface

Every plugin must implement all of these methods:

```go
ID() string              // Stable kebab-case identifier
Name() string            // Short human label for headers/help
Icon() string            // Single-character glyph for tab strip
Init(ctx *Context) error // Lightweight setup; return error to degrade gracefully
Start() tea.Cmd          // Kick off async work (non-blocking)
Update(msg tea.Msg) (Plugin, tea.Cmd) // Pure state transition
View(width, height int) string        // Render within provided dimensions
IsFocused() bool         // Check focus state
SetFocused(bool)         // App calls this on tab switch
Commands() []plugin.Command           // Footer hints per context
FocusContext() string    // Current context name for keymap
Stop()                   // Idempotent cleanup
```

Optional: implement `Diagnostics() []plugin.Diagnostic` for the diagnostics overlay.

## Lifecycle Order

1. **Registration** (`cmd/sidecar/main.go`): `registry.Register(myplugin.New())`. No work here.
2. **Init**: Detect prerequisites (repos, adapters, env vars). Use `ctx.Logger` for warnings. Return error to degrade gracefully.
3. **Start**: Batch initial commands with `tea.Batch`. Never block.
4. **Update**: Pattern-match on custom `Msg` types and `tea.KeyMsg`. Keep I/O in commands, not directly in Update.
5. **View**: Render only; no side-effects. Honor `width/height`.
6. **Focus/Blur**: `SetFocused` called on tab switch. Pause expensive work when unfocused.
7. **Stop**: Close watchers, timers, channels. Guard with `sync.Once`/flags.

## Epoch Pattern (Stale Message Detection)

When switching projects/worktrees, async operations may deliver stale data. Use the epoch pattern:

### Step 1: Add Epoch to message type
```go
type MyDataLoadedMsg struct {
    Epoch uint64
    Data  string
    Err   error
}
func (m MyDataLoadedMsg) GetEpoch() uint64 { return m.Epoch }
```

### Step 2: Capture epoch in command creators
```go
func (p *Plugin) loadData() tea.Cmd {
    epoch := p.ctx.Epoch // Capture synchronously before closure
    return func() tea.Msg {
        data, err := fetchData()
        return MyDataLoadedMsg{Epoch: epoch, Data: data, Err: err}
    }
}
```

### Step 3: Check staleness in Update
```go
case MyDataLoadedMsg:
    if plugin.IsStale(p.ctx, msg) {
        return p, nil // Discard stale message
    }
    p.data = msg.Data
```

Apply this to any async message that fetches data from filesystem/external sources or updates project-specific state.

## Keymap, Contexts, and Commands

- Define **contexts** mirroring your view modes (e.g., `git-status`, `git-diff`). Return the active one from `FocusContext()`.
- Expose **commands** with matching contexts via `Commands()`. These power footer hints and help overlay.
- Add default **bindings** in `internal/keymap/bindings.go`.
- Keep command IDs stable (verbs preferred: `open-file`, `toggle-diff-mode`).

### Command structure
```go
plugin.Command{
    ID:       "stage-file",
    Name:     "Stage",           // Keep 1-2 words max
    Category: plugin.CategoryGit,
    Priority: 10,                // Lower = higher priority; 0 treated as 99
    Context:  "git-status",
}
```

Categories: `CategoryNavigation`, `CategoryActions`, `CategoryView`, `CategorySearch`, `CategoryEdit`, `CategoryGit`, `CategorySystem`

### Context naming convention
- `plugin-name` for main view
- `plugin-name-detail` for detail/preview
- `plugin-name-modal` for modals
- `plugin-name-search` for search modes

### Dynamic binding registration
```go
func (p *Plugin) Init(ctx *plugin.Context) error {
    if ctx.Keymap != nil {
        ctx.Keymap.RegisterPluginBinding("g g", "go-to-top", "my-context")
    }
    return nil
}
```

## Event Bus (Cross-Plugin Communication)

- Subscribe: `ch := ctx.EventBus.Subscribe("topic")` in `Start()`, forward messages into `Update`.
- Publish: `ctx.EventBus.Publish("topic", event.NewEvent(event.TypeRefreshNeeded, "topic", payload))`.
- Best-effort, buffered (size 16), drops when full. Design listeners to be resilient
04

Trust audit

SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.

LayerWhat it checksResult
L0Provenance & inventoryWARN
L1Static analysis of the codeNA
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
none-observed
Shell
none-observed
Dependencies
pinned
Secrets in source
none-found

Findings (2)

MEDIUMInventory / provenance · inv.symlink · CWE-1104
.codex/skills
.codex/skills
Why it matters. link not followed
LOWInventory / provenance · inv.symlink · CWE-1104
GEMINI.md
GEMINI.md
Why it matters. link not followed

Gates applied: no_behavioural_pass.

Audited 2026-10-10 · audit v0.4.1 · source sha a69114b893d1full audit observations/trust-audit/skill/marcus__create-plugin.json · Report an issue / request a re-scan
05

Audit history

Every audit this skill has had.

DateSourceVerdictGradeScoreChange
2026-10-10a69114b893d1SAFEB89first audit
06

Questions

What does the Create Plugin skill do?

Use sidecar next to CLI agents for diffs, file trees, conversation history, and task management with td

Is Create Plugin safe to install?

The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.

What can Create Plugin access on my machine?

The audit observed no filesystem, network or shell use at all in its source.

Which assistants does Create Plugin work with?

Its documentation mentions cursor. That is what the text claims, not a compatibility test we ran.

How current is this page?

The grade is for one exact copy of the source (a69114b893d1), read on 2026-10-10. The repository is watched, and a new audit runs when it changes — this is the first audit.

Advertisement