Agent skill

Coot Inline Graphs

by pemsley in pemsley/coot

Create interactive inline Chart.js graphs directly in the chat from live Coot data.

GPL-3.0Auto-check passed

Install Coot Inline Graphs

skills CLI
$ npx skills add pemsley/coot --skill coot-inline-graphs -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install pemsley/coot coot-inline-graphs --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/pemsley/coot.git skills-src && mkdir -p .claude/skills && cp -r skills-src/mcp/docs/skills/inline-graphs .claude/skills/coot-inline-graphs && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
coot-inline-graphs
GitHub stars
168
Token cost
~2.8k tokens
SKILL.md length
470 words
Files
1
Skills in repo
11
Repo updated
First seen
Licence
GPL-3.0

At a glance

Create interactive inline Chart.js graphs directly in the chat from live Coot data.

  • Works in 3 steps: Fetch per-residue data from Coot → Fetch secondary structure → Render the widget
  • The user asks to plot
  • SKILL.md covers Core workflow, Step 1 — Fetch per-residue…, Step 2 — Fetch secondary… and Step 3 — Render the widget, plus 9 more sections
  • Reaches cdnjs.cloudflare.com

What it does

Coot Inline Graphs is an agent skill from pemsley/coot. Create interactive inline Chart.js graphs directly in the chat from live Coot data. Use this skill whenever the user asks to plot, graph, chart, or visualise any per-residue data from Coot — B-factors, density correlations, Ramachandran probabilities, rotamer scores, or any other per-residue metric. Also use when the user asks to overlay secondary structure on a graph, or to compare metrics across chains. Prefer this approach over any file-based graphing (e.g. Pygal) — it is faster, interactive, and renders…

Its SKILL.md is about 2.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It works with Chart.js. The repository describes itself as: Software for macromolecular model-building. The licence is GPL-3.0.

When your agent uses it

  • The user asks to plot
  • Visualise any per-residue data from Coot — B-factors
  • Density correlations
  • Ramachandran probabilities

Example prompts

  • “/coot-inline-graphs”

Requirements

  • Python 3

Workflow steps

3 steps, taken from the step headings in SKILL.md.

  1. Fetch per-residue data from Coot
  2. Fetch secondary structure
  3. Render the widget

What it can do on your machine

Read from SKILL.md and the folder at commit 6e3c026. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are javascript, html and python).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • cdnjs.cloudflare.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Coot Inline Graphs loads about 2.8k tokens when it runs. Until then it costs about 140 tokens; SKILL.md has 470 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~140
When it runs · the whole SKILL.md, loaded when a task matches
~2.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from pemsley/coot at commit 6e3c026, republished under its GPL-3.0 licence (© pemsley). 470 words, ~2,781 tokens.

Download SKILL.mdSave it as .claude/skills/coot-inline-graphs/SKILL.md (or your agent's skills folder).
name
coot-inline-graphs
description
Create interactive inline Chart.js graphs directly in the chat from live Coot data. Use this skill whenever the user asks to plot, graph, chart, or visualise any per-residue data from Coot — B-factors, density correlations, Ramachandran probabilities, rotamer scores, or any other per-residue metric. Also use when the user asks to overlay secondary structure on a graph, or to compare metrics across chains. Prefer this approach over any file-based graphing (e.g. Pygal) — it is faster, interactive, and renders inline in the conversation.

Coot Inline Graphs

Inline graphs render Chart.js directly in the chat via the visualize:show_widget tool. Coot supplies the data via Python; the widget renders it with no file I/O, no external viewer, and full interactivity.

Core workflow

  1. Get data from Coot — fetch per-residue metrics using the Python API
  2. Get secondary structure — call add_header_secondary_structure_info() then get_header_secondary_structure_info() if overlays are wanted
  3. Render the widget — embed data as JS literals in the Chart.js HTML

Always call visualize:read_me (modules: ["interactive", "chart"]) before the first visualize:show_widget call in a session.


Step 1 — Fetch per-residue data from Coot

B-factors
python
def get_bfactor_data(imol, chain_id):
    min_res = coot.min_resno_in_chain(imol, chain_id)
    max_res = coot.max_resno_in_chain(imol, chain_id)
    results = []
    for resno in range(min_res, max_res + 1):
        atoms = coot.residue_info_py(imol, chain_id, resno, "")
        if atoms:
            resname = coot.residue_name_py(imol, chain_id, resno, "")
            bfactors = [a[1][1] for a in atoms if isinstance(a[1][1], float)]
            mean_b = round(sum(bfactors) / len(bfactors), 2) if bfactors else 0
            results.append({"resno": resno, "resname": resname, "mean_b": mean_b})
    return results
Density correlation
python
def get_correlation_data(imol, chain_id, imol_map):
    stats = coot.map_to_model_correlation_stats_per_residue_range_py(
        imol, chain_id, imol_map, 1, 0)
    results = []
    for entry in stats[0]:
        residue_spec = entry[0]   # [chain_id, resno, ins_code]
        corr_data    = entry[1]   # [n_points, correlation]
        resno = residue_spec[1]
        correlation = corr_data[1]
        resname = coot.residue_name_py(imol, chain_id, resno, "")
        results.append({
            "resno": resno,
            "resname": resname,
            "correlation": round(correlation, 4) if correlation == correlation else None
        })
    return results
Ramachandran probabilities
python
def get_rama_data(imol, chain_id):
    rama = coot.all_molecule_ramachandran_score_py(imol)
    results = []
    for entry in rama[5]:
        if entry == -1:
            continue
        phi_psi, res_spec, score, res_names = entry
        if res_spec[0] != chain_id:
            continue
        results.append({
            "resno": res_spec[1],
            "resname": res_names[1],
            "phi": round(phi_psi[0], 1),
            "psi": round(phi_psi[1], 1),
            "rama_prob": round(score, 4)
        })
    return results

Step 2 — Fetch secondary structure

Always try get_header_secondary_structure_info() first. If it returns {} or False, call add_header_secondary_structure_info() to compute it from geometry, then call get_header_secondary_structure_info() again.

python
def get_secondary_structure(imol, chain_id):
    ss = coot.get_header_secondary_structure_info(imol)
    if not isinstance(ss, dict) or (not ss.get('helices') and not ss.get('strands')):
        coot.add_header_secondary_structure_info(imol)
        ss = coot.get_header_secondary_structure_info(imol)
    if not isinstance(ss, dict):
        return {'helices': [], 'strands': []}
    helices = [h for h in (ss.get('helices') or []) if h['initChainID'] == chain_id]
    strands = [s for s in (ss.get('strands') or []) if s['initChainID'] == chain_id]
    return {'helices': helices, 'strands': strands}

Important: add_header_secondary_structure_info() will crash Coot if called on a molecule that already has secondary structure records populated and then get_header_secondary_structure_info() is called — only call it when the initial query returns empty. (Bug reported; fix applied to c-interface-build.cc:2876.)


Step 3 — Render the widget

Chart.js setup

Load via CDN. Always use the UMD build:

html
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js"></script>

For secondary structure annotation overlays, also load:

html
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/3.0.1/chartjs-plugin-annotation.min.js"></script>
Data embedding

Embed Coot data as a JS literal directly in the widget HTML. Do not use fetch() or external URLs — the data comes from Coot at render time and is baked in.

javascript
const data = [
  {"resno": 1, "resname": "ASP", "mean_b": 34.95},
  // ... all residues
];
Canvas sizing

Always wrap <canvas> in a <div> with explicit height:

html
<div style="position: relative; width: 100%; height: 300px;">
  <canvas id="chart"></canvas>
</div>

Set responsive: true, maintainAspectRatio: false in Chart.js options. Never set height directly on the <canvas> element.


Secondary structure overlay

Box annotations sit at the top of the chart as a strip. The box height is computed dynamically so the α/β glyph sits vertically centred:

javascript
const boxHeightUnits = Math.round(22 * yAxisMax / 280);
const boxYMax = yAxisMax;
const boxYMin = yAxisMax - boxHeightUnits;

Build a resnoToIndex lookup first (maps residue number → bar index):

javascript
const resnoToIndex = {};
data.forEach((d, i) => { resnoToIndex[d.resno] = i; });
Show full SKILL.md (188 more words)Show less
Annotation spec
javascript
// Helix — purple, semi-opaque, white-ish glyph text
{
  type: 'box',
  xMin: resnoToIndex[h.initSeqNum] - 0.5,
  xMax: resnoToIndex[h.endSeqNum]  + 0.5,
  yMin: boxYMin,
  yMax: boxYMax,
  backgroundColor: 'rgba(175,169,236,0.45)',
  borderColor:     'rgba(127,119,221,0.8)',
  borderWidth: 1,
  label: {
    display: true,
    content: 'α',
    position: { x: 'center', y: 'center' },
    font:  { size: 13, weight: '500' },
    color: 'rgba(255,255,255,0.85)'
  }
}

// Strand — amber, semi-opaque, white-ish glyph text
{
  type: 'box',
  xMin: resnoToIndex[s.initSeqNum] - 0.5,
  xMax: resnoToIndex[s.endSeqNum]  + 0.5,
  yMin: boxYMin,
  yMax: boxYMax,
  backgroundColor: 'rgba(239,159,39,0.35)',
  borderColor:     'rgba(186,117,23,0.7)',
  borderWidth: 1,
  label: {
    display: true,
    content: 'β',
    position: { x: 'center', y: 'center' },
    font:  { size: 13, weight: '500' },
    color: 'rgba(255,255,255,0.85)'
  }
}

Threshold colouring

Colour bars relative to a threshold to highlight problem residues:

javascript
// Correlation — low is bad
backgroundColor: data.map(d => d.correlation < thresh ? '#378ADD' : '#5DCAA5')

// B-factor — high is bad
backgroundColor: data.map(d => d.mean_b > thresh ? '#378ADD' : '#5DCAA5')

// Ramachandran — low probability is bad
backgroundColor: data.map(d => d.rama_prob < thresh ? '#E24B4A' : '#5DCAA5')

Provide a range slider to let the user adjust threshold interactively. When switching between metrics, update the slider range accordingly:

  • Correlation: min=0, max=1, step=0.01, default=0.7
  • B-factor: min=0, max=bMax, step=1, default=20
  • Ramachandran: min=0, max=1, step=0.01, default=0.02

Click-to-navigate

Wire bar clicks to sendPrompt() so the user can jump to a residue in Coot:

javascript
onClick: (e, els) => {
  if (els.length) {
    const d = data[els[0].index];
    sendPrompt('Navigate to residue ' + d.resno + ' ' + d.resname +
               ' in chain ' + chainId + ' of the tutorial model');
  }
}

Axis labels and ticks

javascript
scales: {
  x: {
    grid: { display: false },
    ticks: {
      color: '#888780',
      font: { size: 9 },
      maxRotation: 90,
      autoSkip: true,
      maxTicksLimit: 30
    }
  },
  y: {
    min: 0,
    max: yAxisMax,
    grid: { color: 'rgba(136,135,128,0.15)' },
    ticks: {
      color: '#888780',
      font: { size: 11 },
      callback: v => v + ' Ų'   // or '.toFixed(2)' for correlations
    }
  }
}

Stat cards

Show summary metrics above the chart using the metric card pattern:

html
<div style="background: var(--color-background-secondary);
            border-radius: var(--border-radius-md);
            padding: 10px 12px;">
  <div style="font-size: 11px; color: var(--color-text-secondary);">Mean B</div>
  <div style="font-size: 17px; font-weight: 500; color: var(--color-text-primary);"
       id="s-meanb">—</div>
</div>

Use a 4-column grid: residue count, mean metric, count above/below threshold, max or min value as appropriate.


Legend

Always provide a manual legend below the chart — do not use Chart.js default:

html
<div style="display: flex; gap: 16px; margin-top: 8px;
            font-size: 12px; color: var(--color-text-secondary); flex-wrap: wrap;">
  <span style="display:flex;align-items:center;gap:4px;">
    <span style="width:10px;height:10px;border-radius:2px;background:#5DCAA5;"></span>
    Below threshold
  </span>
  <span style="display:flex;align-items:center;gap:4px;">
    <span style="width:10px;height:10px;border-radius:2px;background:#378ADD;"></span>
    Above threshold
  </span>
  <span style="display:flex;align-items:center;gap:4px;">
    <span style="width:10px;height:10px;border-radius:2px;
                 background:rgba(175,169,236,0.45);border:1px solid #7F77DD;"></span>
    Helix
  </span>
  <span style="display:flex;align-items:center;gap:4px;">
    <span style="width:10px;height:10px;border-radius:2px;
                 background:rgba(239,159,39,0.35);border:1px solid #BA7517;"></span>
    Strand
  </span>
</div>

Tooltips

Include both the primary metric and secondary metric in tooltips:

javascript
tooltip: {
  callbacks: {
    title: items => items[0].label,
    label: item => 'Mean B: ' + data[item.dataIndex].mean_b.toFixed(1) + ' Ų',
    afterLabel: item => {
      const r = data[item.dataIndex].resno;
      if (helices.some(h => r >= h.initSeqNum && r <= h.endSeqNum)) return 'α-helix';
      if (strands.some(s => r >= s.initSeqNum && r <= s.endSeqNum)) return 'β-strand';
      return 'loop/coil';
    }
  }
}

Number formatting

All numbers reaching the screen must be rounded:

  • B-factors: .toFixed(1) + ' Ų'
  • Correlations: .toFixed(3)
  • Ramachandran probabilities: .toFixed(4)
  • Axis tick integers: Math.round()

Why not Pygal?

Pygal requires file I/O, a separate viewer, and a display context. It produces black images in headless environments and is slow. Chart.js in the browser has none of these problems and adds interactivity for free. Do not use Pygal.

© pemsley, GPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in mcp/docs/skills/inline-graphs of pemsley/coot.

Open the folder on GitHubat commit 6e3c026

Compare with similar skills

Coot Inline Graphs next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Coot Inline Graphs compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Coot Inline Graphs this skillpemsley/coot168—~2.8kAutomated safety check: PassGPL-3.0
Brand and Design Toolkitnextlevelbuilder/ui-ux-pro-max-skill134k1 repos~3.5kAutomated safety check: PassMIT
Lieflat Chartslarashero3-dotcom/lieflat-charts6k1 repos~4.5kAutomated safety check: PassCC-BY-NC-4.0
DesignOhh-889/skyroc7959 repos~3.1kAutomated safety check: PassMIT
Web Designcountbot-ai/CountBot782—~1kAutomated safety check: PassMIT
Tufte Data Vizcaylent/tufte-data-viz223—~3.5kAutomated safety check: PassMIT

Similar skills

  • Brand and Design Toolkit

    nextlevelbuilder/ui-ux-pro-max-skill

    Bundles design tasks behind one skill: brand identity, tokens, UI styling, logos, corporate identity mockups, slides, banners, icons and social images.

    134k GitHub starsUsed in 1 repo~3.5k tokens
    Media & CreativeAuto-check passed
  • Lieflat Charts

    larashero3-dotcom/lieflat-charts

    Generates single-file HTML charts and full-page reports from real gallery templates, using a grayscale base with optional color presets.

    6k GitHub starsUsed in 1 repo~4.5k tokens
    Data & AnalyticsAuto-check passed
  • Design

    Ohh-889/skyroc

    Comprehensive design skill: brand identity, design tokens, UI styling, logo generation (55 styles, Gemini AI), corporate identity program (50 deliverables, CIP mockups), HTML presentations…

    795 GitHub starsUsed in 9 repos~3.1k tokens
    Frontend & DesignAuto-check passed
  • Web Design

    countbot-ai/CountBot

    网页设计与部署。生成精美的单页 HTML 网页(报告、落地页、数据可视化等),支持一键部署到 Cloudflare Pages。使用 Tailwind CSS + Chart.js + Font Awesome 技术栈。当用户要求制作网页、生成报告页面、创建落地页、数据可视化展示、部署网页到线上时使用。

    782 GitHub stars~1k tokensUpdated 3 days ago
    Frontend & DesignAuto-check passed
  • Tufte Data Viz

    caylent/tufte-data-viz

    A skill your agent uses when creating, reviewing, or styling charts, graphs, dashboards, sparklines, or any data visualization.

    223 GitHub stars~3.5k tokensUpdated 7 mo ago
    Data & AnalyticsAuto-check passed
  • Visualize

    Classic298/open-webui-plugins

    Render rich interactive visuals — SVG diagrams, HTML widgets, Chart.js charts, and interactive explainers — directly inline in chat using visualize().

    577 GitHub stars~10k tokensUpdated 2 days ago
    DevelopmentAuto-check passed

More from pemsley/coot

All 11 skills in this repo
  • Coot Rdkit

    pemsley/coot

    RDKit molecular manipulation and visualization within Coot's Python environment.

    168 GitHub stars~981 tokensUpdated today
    Auto-check passed
  • Coot Refinement

    pemsley/coot

    Best practices for protein structure refinement and validation in Coot.

    168 GitHub stars~2k tokensUpdated today
    Auto-check passed
  • Coot Essential API

    pemsley/coot

    API documentation to be loaded at startup - when starting a Coot session, immediately call getfunctiondescriptions() with the functions listed in this skill.

    168 GitHub stars~4.5k tokensUpdated today
    Auto-check passed
  • Coot Figure Making

    pemsley/coot

    Best practices for creating publication-quality molecular graphics figures in Coot using user-defined colors, ribbons, and molecular representations

    168 GitHub stars~7.3k tokensUpdated today
    Auto-check passed
  • Best Practices for Model-Building Tools and Refinement. An agent skill from pemsley/coot.

    168 GitHub stars~13k tokensUpdated today
    Auto-check passed
  • Coot Validation

    pemsley/coot

    Comprehensive structure validation combining model-to-map analysis and unmodeled density detection

    168 GitHub stars~6.2k tokensUpdated today
    Auto-check passed

Works with

Questions about Coot Inline Graphs

What does Coot Inline Graphs do?

Create interactive inline Chart.js graphs directly in the chat from live Coot data. Coot Inline Graphs is an agent skill from pemsley/coot.js graphs directly in the chat from live Coot data.

When should I use Coot Inline Graphs?

Coot Inline Graphs fits situations like: the user asks to plot; visualise any per-residue data from Coot — B-factors; density correlations; ramachandran probabilities.

How do I install Coot Inline Graphs in Claude Code?

Run `npx skills add pemsley/coot --skill coot-inline-graphs -a claude-code`. Or copy the skill folder (mcp/docs/skills/inline-graphs in pemsley/coot) into .claude/skills/coot-inline-graphs in your project. Claude Code loads it when a task matches its description.

How do I install Coot Inline Graphs in Codex?

Run `npx skills add pemsley/coot --skill coot-inline-graphs -a codex`. Or copy the skill folder (mcp/docs/skills/inline-graphs in pemsley/coot) into .agents/skills/coot-inline-graphs in your project. Codex loads it when a task matches its description.

Can I use Coot Inline Graphs in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add pemsley/coot --skill coot-inline-graphs -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/coot-inline-graphs, .gemini/skills/coot-inline-graphs, .github/skills/coot-inline-graphs and .opencode/skills/coot-inline-graphs in your project.

What does Coot Inline Graphs need to run?

SKILL.md names no scripts, command-line tools or credentials: Coot Inline Graphs is instructions for the agent only. Our summary lists: Python 3.

Does Coot Inline Graphs access the network?

SKILL.md names 1 domain. In commands or code: cdnjs.cloudflare.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is Coot Inline Graphs safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Coot Inline Graphs use?

Coot Inline Graphs is published under the GPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Coot Inline Graphs use?

About 2.8k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Coot Inline Graphs?

Skills that share tags, products or a category with Coot Inline Graphs: Brand and Design Toolkit (nextlevelbuilder/ui-ux-pro-max-skill, 134k stars), Lieflat Charts (larashero3-dotcom/lieflat-charts, 6k stars), Design (Ohh-889/skyroc, 795 stars) and Web Design (countbot-ai/CountBot, 782 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Coot Inline Graphs?

pemsley (a GitHub user) maintains it in pemsley/coot, which has 168 GitHub stars. The repository holds 11 skills in this directory. The repository was last updated on October 7, 2026.

Source: pemsley/coot on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.