Skip to content
Testing
Command

/create-api

You are creating a JavaScript API class for a Scopy plugin so it can be controlled from test automation scripts.

BOOST
From plugin
scopy
50213 skills13 commands1 MCP
Install
> /plugin marketplace add analogdevicesinc/scopy
> /plugin install scopy_dev_plugin@scopy-plugins

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/create-api

Context preview

What this command does when you run it.

You are creating a JavaScript API class for a Scopy plugin so it can be controlled from test automation scripts.

Command definition

create-api.md

/create-api — Generate JavaScript API class for a Scopy plugin

You are creating a JavaScript API class for a Scopy plugin so it can be controlled from test automation scripts.

**Plugin:** `$ARGUMENTS`

Step 0: Load context

Use the Read tool to check if a port state file exists:

  • Path: `tasks/$ARGUMENTS-port-state.md`
  • If the file does not exist, note "No state file — will discover from source files directly." and continue.

Step 1: Discovery

Locate the plugin's source files by checking these paths in priority order:

**If state file exists**, use it as the inventory: extract the plugin class name, namespace, tool list IDs, and section/attribute inventory.

**If no state file**, discover directly:

  • Use the Glob tool to find the plugin header: `scopy/packages/$ARGUMENTS/plugins/*/include/*/$ARGUMENTS*plugin.h`
  • Use the Glob tool to find the plugin source: `scopy/packages/$ARGUMENTS/plugins/*/src/$ARGUMENTS*plugin.cpp`
  • Read tool class files in the same directory
  • Read `manifest.json.cmakein` for device name and display name
  • Read CMakeLists.txt for library and export macro naming

**Also read the tool implementation** (`<plugin>.cpp` in `src/`) to catalogue every IIOWidget's conversion setup. For each widget, note:

  • `setDataToUIConversion` lambda → determines what the **getter** must do (e.g. ÷1e6 for Hz→MHz)
  • `setUItoDataConversion` lambda → determines what the **setter** must do (e.g. ×1e6 for MHz→Hz)
  • IIO attribute suffix patterns (e.g. hardwaregain returns "-10.000000 dB" — suffix must be stripped in getter)
  • Combo widget available-attribute name → extract valid enum string list for setter validation

Also check if an API already exists (use the Glob tool to search for `*_api.h` in the plugin's package dir). If found, switch to **Update Mode** (see below).

Update Mode (existing API)

When an API class already exists, do NOT stop. Instead:

1. **Read all existing API files** (header + source) and the plugin header/source. 2. **Run all A1–A7 checks** from the `api-quality-checks` skill against the existing code (same as `/validate-api`). 3. **Check for missing coverage**: Compare every IIOWidget discovered in Step 1 against the existing API methods. Flag any widgets that lack getter/setter pairs. 4. **Present a fix plan** listing:

  • Critical issues found (A1–A7 failures)
  • Missing getter/setter pairs for uncovered widgets
  • Conversion mismatches between tool lambdas and API methods

5. **AUTO-APPROVE and proceed** — apply all fixes to the existing API files:

  • Fix A2 issues (naming, lifecycle ordering, nullptr init)
  • Fix A3 issues (add null-checks to methods missing them)
  • Fix A7 issues (const QString& params, naming conventions)
  • Add missing getter/setter methods for uncovered widgets
  • Fix conversion logic mismatches

6. Continue to **Step 4: Validate** below to confirm all checks pass after fixes.

Do NOT regenerate the API from scratch — fix the existing code in place.

Step 2: Design — WAIT FOR APPROVAL

After reading the plugin header, source, and instrument classes, present:

1. **API pattern chosen** (Pattern A: tool-based, Pattern B: IIOWidgetGroup-based, or both) 2. **Complete method list** grouped by instrument/category:

  • `getTools()` always included
  • getter/setter pairs for each widget member
  • run-control methods
  • IIOWidget access methods (if applicable)

For each getter/setter pair, also document a **conversion row**: | Method | IIO unit | API unit | Getter conversion | Setter conversion | 3. **Missing Functionality Report** — things that CAN'T be exposed without base-class changes 4. **Files to create/modify**:

  • `<plugin>_api.h` (new)
  • `<plugin>_api.cpp` (new)
  • Plugin header (add friend + `m_api` member + `initApi()`)
  • Plugin source (add `initApi()` impl + call in `onConnect()` + delete in `onDisconnect()`)
  • CMakeLists.txt (only if it uses explicit file lists — check first)

**Wait for user approval before writing any code.**

Step 3: Implement

Follow the API patterns described in the `scopy-api-patterns` knowledge skill:

  • Use `friend class` for private member access (do NOT add public getters to instrument classes)
  • Null-check every instrument pointer
  • Call `initApi()` as the last line of `onConnect()` before `return true`
  • Delete `m_api` at the BEGINNING of `onDisconnect()` before any other cleanup
  • Set the JS object name with `setObjectName("pluginname")` — lowercase, short
  • Register with `ScopyJS::GetInstance()->registerApi(m_api)`
  • End the `.cpp` file with `#include "moc_<plugin>_api.cpp"`

IIOWidget Conversion Rules

`IIOWidget::writeAsync()` writes directly to the IIO data strategy — it does **NOT** apply `m_UItoDS`. Similarly, `read().first` returns the raw IIO value, not the UI-displayed value. Getters and setters MUST replicate the conversion logic from `setDataToUIConversion` / `setUItoDataConversion` lambdas found in the tool class.

**Frequency (Hz ↔ MHz):**

// Getter: divide raw Hz string by 1e6
QString getXxx() {
    QString raw = readFromWidget(key);
    if(raw.isEmpty()) return raw;
    return QString::number(raw.toDouble() / 1e6, 'f', 3);
}
// Setter: multiply MHz value by 1e6 before writing
void setXxx(const QString &val) {
    writeToWidget(key, QString::number(val.toDouble() * 1e6, 'f', 0));
}

**IIO unit suffix (e.g. " dB" appended by IIO driver to hardwaregain):**

// Getter: strip the trailing suffix before returning
QString getXxx() {
    QString raw = readFromWidget(key);
    int idx = raw.indexOf(" dB");
    if(idx != -1) raw = raw.left(idx).trimmed();
    return raw;
}
// Setter: write numeric string only (IIO accepts without suffix)
void setXxx(const QString &val) { writeToWidget(key, val); }

**dBFS ↔ linear scale (e.g. IIO stores 0.5 linear, UI shows 6 dBFS):**

#include <cmath>
// Getter: linear → dBFS (round to nearest integer)
QString getXxx() {
    QString raw = readFromWidget(key);
    if(raw.isEmpty())
Read more
Ships withscopy

Scopy is a software oscilloscope and signal analysis toolset.

Get the whole plugin

Other commands on scopy.