Agent skill

JS Cpp Protocol

by notepadqq in notepadqq/notepadqq

Reference for the communication protocol between the JavaScript editor (CodeMirror or Monaco) and the C++/Qt UI layer via QWebChannel.

GPL-3.0Auto-check passedDevelopment

Install JS Cpp Protocol

skills CLI
$ npx skills add notepadqq/notepadqq --skill js-cpp-protocol -a claude-code

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

GitHub CLI
$ gh skill install notepadqq/notepadqq js-cpp-protocol --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/notepadqq/notepadqq.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/js-cpp-protocol .claude/skills/js-cpp-protocol && 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
js-cpp-protocol
GitHub stars
2.3k
Token cost
~3.2k tokens
SKILL.md length
1,093 words
Files
1
Skills in repo
2
Repo updated
First seen
Licence
GPL-3.0

At a glance

Reference for the communication protocol between the JavaScript editor (CodeMirror or Monaco) and the C++/Qt UI layer via QWebChannel.

  • Works in 3 steps: C++ (editor.cpp:47-70): Creates a… → JS (index.html:7 / index_monaco.html:7):… → JS (UiDriver.js:8-26): On…
  • Implementing new editor features
  • SKILL.md covers Overview, Architecture, Key Files and Communication Mechanism, plus 8 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

JS Cpp Protocol is an agent skill from notepadqq/notepadqq. Reference for the communication protocol between the JavaScript editor (CodeMirror or Monaco) and the C++/Qt UI layer via QWebChannel. Use when implementing new editor features, adding messages to the bridge, debugging JS/C++ communication, or understanding how editor commands flow between layers.

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

It sits in Development. It works with C++, JavaScript, Linux and macOS. The repository describes itself as: A simple, general-purpose editor for Linux and MacOS. The licence is GPL-3.0.

When your agent uses it

  • Implementing new editor features
  • Adding messages to the bridge
  • Debugging JS/C++ communication
  • Understanding how editor commands flow between layers

Example prompts

  • “/js-cpp-protocol”

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. C++ (editor.cpp:47-70): Creates a JsToCppProxy QObject (registered as "cpp_ui_driver"), creates a QWebChannel, sets it on the WebEngine…
  2. JS (index.html:7 / index_monaco.html:7): Includes (Qt's built-in WebChannel JS library).
  3. JS (UiDriver.js:8-26): On DOMContentLoaded, creates new QWebChannel(qt.webChannelTransport, callback), obtains cpp_ui_driver =…

What it can do on your machine

Read from SKILL.md and the folder at commit 37652c5. 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 and cpp).

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

  • Network

    No URLs in SKILL.md.

    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

JS Cpp Protocol loads about 3.2k tokens when it runs. Until then it costs about 79 tokens; SKILL.md has 1,093 words of instructions outside code blocks.

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

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 notepadqq/notepadqq at commit 37652c5, republished under its GPL-3.0 licence (© notepadqq). 1,093 words, ~3,247 tokens.

Download SKILL.mdSave it as .claude/skills/js-cpp-protocol/SKILL.md (or your agent's skills folder).
name
js-cpp-protocol
description
Reference for the communication protocol between the JavaScript editor (CodeMirror or Monaco) and the C++/Qt UI layer via QWebChannel. Use when implementing new editor features, adding messages to the bridge, debugging JS/C++ communication, or understanding how editor commands flow between layers.

JS Editor / C++ UI Communication Protocol

Overview

Notepadqq's editor uses Qt WebEngine (QWebEngineView) with Qt WebChannel (QWebChannel) for bi-directional communication between the native C++ UI and the JavaScript editor engine (either CodeMirror or Monaco). The C++ side is unaware of which engine is running — both engines implement the identical message protocol.

Architecture

┌───────────────────────────┐          QWebChannel           ┌──────────────────────────┐
│        C++ / Qt           │  ◄─────────────────────────►   │   JavaScript Editor      │
│                           │                                │                          │
│  Editor (editor.cpp)      │  signal: messageReceivedByJs   │  UiDriver.js             │
│    ├─ JsToCppProxy (QObject)│  ──────────────────────────►  │    ├─ QWebChannel bridge │
│    └─ CustomQWebView      │  ◄──────────────────────────  │    └─ messageReceived()   │
│                           │  slot: receiveMessage()        │                          │
│  EditorTabWidget          │                                │  app.js / app_monaco.js  │
│  MainWindow               │                                │    └─ event handlers     │
└───────────────────────────┘                                └──────────────────────────┘

Key Files

SideFileRole
JSsrc/editor/classes/UiDriver.jsCore bridge: QWebChannel setup, sendMessage(), registerEventHandler(), messageReceived() dispatcher
JSsrc/editor/app.jsCodeMirror implementation: registers handlers for all C_CMD_* / C_FUN_* messages
JSsrc/editor/app_monaco.jsMonaco implementation: registers handlers for all C_CMD_* / C_FUN_* messages
JSsrc/editor/index.htmlCodeMirror HTML entry point
JSsrc/editor/index_monaco.htmlMonaco HTML entry point
C++src/ui/EditorNS/editor.cppCreates QWebChannel, sends messages, receives replies, manages async callbacks
C++src/ui/include/EditorNS/editor.hDeclares JsToCppProxy, Editor, AsyncReply
C++src/ui/EditorNS/customqwebview.cppQWebEngineView subclass: event handling, drag-drop, context menu

Communication Mechanism

Setup
  1. C++ (editor.cpp:47-70): Creates a JsToCppProxy QObject (registered as "cpp_ui_driver"), creates a QWebChannel, sets it on the WebEngine page, and registers the proxy: channel->registerObject("cpp_ui_driver", m_jsToCppProxy).

  2. JS (index.html:7 / index_monaco.html:7): Includes <script src="qrc:///qtwebchannel/qwebchannel.js"></script> (Qt's built-in WebChannel JS library).

  3. JS (UiDriver.js:8-26): On DOMContentLoaded, creates new QWebChannel(qt.webChannelTransport, callback), obtains cpp_ui_driver = channel.objects.cpp_ui_driver, and connects to the messageReceivedByJs signal.

C++ → JS (Commands and Function Calls)

Two modes exist:

Synchronous (legacy/deprecated): sendMessage(msg, data)

  • editor.cpp:374-382: Emits messageReceivedByJs signal, which Qt WebChannel delivers to JS.
  • JS receives it via cpp_ui_driver.messageReceivedByJs.connect(...) and processes it immediately.

Asynchronous (preferred): asyncSendMessageWithResultP(msg, data)

  • editor.cpp:389-430: Generates a unique message ID, wraps the message in [ASYNC_REQUEST] prefix + [ID=N] suffix.
  • JS receives it, dispatches to registered handlers, then sends back [ASYNC_REPLY] with the same ID.
  • C++ resolves the QtPromise::QPromise<QVariant> on receipt.

Message format for async:

C++ sends:  [ASYNC_REQUEST]C_CMD_GET_VALUE[ID=42]
JS replies: [ASYNC_REPLY]C_CMD_GET_VALUE[ID=42]
JS → C++ (Events)

JS calls UiDriver.sendMessage("J_EVT_*", data) which invokes cpp_ui_driver.receiveMessage(msg, data) (UiDriver.js:36).

C++ receives it in JsToCppProxy::receiveMessage() (editor.h:44), which emits messageReceived signal → Editor::on_proxyMessageReceived() (editor.cpp:143).

Message Naming Convention

PrefixDirectionSemantics
C_CMD_*C++ → JSFire-and-forget command (no return value expected)
C_FUN_*C++ → JSFunction call (return value expected via async reply)
J_EVT_*JS → C++Event notification (no return value)

Complete Message Reference

C_CMD_* — Commands (C++ → JS, no return value)
MessageDataDescription
C_CMD_SET_VALUEQStringSet full editor text content
C_CMD_MARK_CLEANnoneMark document as clean (no unsaved changes)
C_CMD_MARK_DIRTYnoneMark document as dirty (unsaved changes)
C_CMD_SET_LANGUAGElanguage MIME stringSet syntax highlighting language
C_CMD_SET_INDENTATION_MODE{useTabs: bool, size: int}Set tab/space indentation
C_CMD_SET_SELECTIONS_TEXT{text: string[], select: "after"|"before"|"selected"}Replace selected text
C_CMD_SET_SELECTION[fromLine, fromCol, toLine, toCol]Set selection range
C_CMD_SET_CURSOR[line, col]Set cursor position
C_CMD_SET_RTLnoneSet text direction to RTL
C_CMD_SET_LTRnoneSet text direction to LTR
C_CMD_SET_SCROLL_POS[left, top]Set scroll position
C_CMD_SELECT_ALLnoneSelect entire document
C_CMD_UNDOnoneUndo last change
C_CMD_REDOnoneRedo last undone change
C_CMD_CLEAR_HISTORYnoneClear undo history
C_CMD_SET_LINE_WRAPboolToggle line wrapping
C_CMD_SHOW_END_OF_LINEboolShow/hide end-of-line characters
C_CMD_SHOW_WHITESPACEboolShow/hide whitespace characters
C_CMD_SET_TABS_VISIBLEboolShow/hide tab characters
C_CMD_SET_THEME{name: string, path: string}Apply editor theme
C_CMD_SET_FONT{family: string, size: int, lineHeight: double}Set editor font
C_CMD_SET_LINE_NUMBERS_VISIBLEboolShow/hide line numbers
C_CMD_SET_OVERWRITEboolToggle overwrite mode
C_CMD_SET_SMART_INDENTboolToggle smart indent
C_CMD_SET_FOCUSnoneFocus the editor
C_CMD_BLURnoneBlur the editor
C_CMD_DISPLAY_PRINT_STYLEnoneSwitch to print-friendly CSS
C_CMD_DISPLAY_NORMAL_STYLEnoneSwitch back to normal CSS
C_CMD_DUPLICATE_LINEnoneDuplicate current line
C_CMD_MOVE_LINE_UPnoneMove current line up
C_CMD_MOVE_LINE_DOWNnoneMove current line down
C_CMD_TRANSPOSE_LINEnoneTranspose with previous line
C_CMD_DELETE_LINEnoneDelete current line
C_CMD_TRIM_LEADING_TRAILING_SPACEnoneTrim leading and trailing whitespace
C_CMD_TRIM_TRAILING_SPACEnoneTrim only trailing whitespace
C_CMD_TRIM_LEADING_SPACEnoneTrim only leading whitespace
C_CMD_ENABLE_MATHboolEnable/disable LaTeX math rendering
C_CMD_TAB_TO_SPACEnoneConvert tabs to spaces
C_CMD_SPACE_TO_TAB_ALLnoneConvert all spaces to tabs
C_CMD_SPACE_TO_TAB_LEADINGnoneConvert leading spaces to tabs
C_CMD_EOL_TO_SPACEnoneReplace line endings with spaces
C_CMD_GET_DOCUMENT_INFOnoneRequest document info (replied via J_EVT_DOCUMENT_INFO)
C_FUN_* — Function Calls (C++ → JS, return value via async reply)
MessageDataReturn Type
C_FUN_IS_CLEANnonebool
C_FUN_GET_HISTORY_GENERATIONnoneint
C_FUN_GET_VALUEnoneQString
C_FUN_GET_INDENTATION_MODEnone{useTabs: bool, size: int}
C_FUN_GET_SELECTIONS_TEXTnoneQStringList
C_FUN_GET_SELECTIONSnone[{anchor: {line, col}, head: {line, col}}]
C_FUN_GET_TEXT_LENGTHnoneint
C_FUN_GET_LINE_COUNTnoneint
C_FUN_GET_CURSORnone[line, col]
C_FUN_GET_SCROLL_POSnone[left, top]
C_FUN_SEARCH[regex: string, modifiers: string, forward: bool]bool (found or not)
C_FUN_REPLACE[regex, modifiers, forward, replacement, searchMode]bool
C_FUN_REPLACE_ALL[regex, modifiers, replacement, searchMode]int (count)
C_FUN_SEARCH_SELECT_ALL[regex, modifiers]int (count)
C_FUN_GET_LANGUAGESnonearray of {name, mime, mode, ext}
C_FUN_DETECT_INDENTATION_MODEnone{found: bool, useTabs: bool, size: int}
C_FUN_GET_CURRENT_WORDnoneQString
C_FUN_IS_MATH_ENABLEDnonebool
Show full SKILL.md (389 more words)Show less
J_EVT_* — Events (JS → C++, no return value)
MessageDataWhen Sent
J_EVT_READYnoneEditor initialization complete
J_EVT_CONTENT_CHANGEDnoneDocument content changes (throttled ~50ms)
J_EVT_CLEAN_CHANGEDboolClean/dirty state changes
J_EVT_CURSOR_ACTIVITY{cursor: {...}, selections: [...], content: {...}}Cursor/selection changes (throttled ~50ms)
J_EVT_DOCUMENT_INFO{cursor, selections, content}Reply to C_CMD_GET_DOCUMENT_INFO
J_EVT_GOT_FOCUSnoneEditor receives focus

Handler Registration Pattern (JS)

Handlers are registered in app.js or app_monaco.js:

javascript
UiDriver.registerEventHandler("C_CMD_SET_VALUE", function(msg, data, prevReturn) {
    editor.setValue(data);
});

Multiple handlers can be registered for the same message. They are called in registration order; each handler receives the previous handler's return value as prevReturn.

Async Flow in Detail

  1. C++ generates a unique ID (messageIdentifier counter, editor.cpp:387).
  2. C++ creates a promise and stores an AsyncReply{id, message, value, callback} in the asyncReplies list (editor.cpp:407-412).
  3. C++ sends [ASYNC_REQUEST]C_FUN_GET_CURSOR[ID=42] via messageReceivedByJs signal (editor.cpp:414-418).
  4. JS receives in UiDriver.messageReceived() (UiDriver.js:52-75), parses the real message and ID via regex /^\[ASYNC_REQUEST\](.*)\[ID=(\d+)\]$/, dispatches to handler(s), then sends back [ASYNC_REPLY]C_FUN_GET_CURSOR[ID=42] with the return value.
  5. C++ receives in Editor::on_proxyMessageReceived() (editor.cpp:148-176), parses the ID via regex \\[ID=(\\d+)\\]$, looks up the matching AsyncReply, resolves the promise and/or calls the callback, then emits asyncReplyReceived.

C++ API for Sending Messages

cpp
// Legacy synchronous (deprecated — blocks event loop)
void sendMessage(const QString msg, const QVariant data);

// Modern async with QtPromise (preferred)
QtPromise::QPromise<QVariant> asyncSendMessageWithResultP(const QString msg, const QVariant data);

// Legacy future-based (deprecated — spins event loop in while())
std::shared_future<QVariant> asyncSendMessageWithResult(
    const QString msg, const QVariant data,
    std::function<void(QVariant)> callback = nullptr);

Adding a New Message

  1. Choose the prefix: C_CMD_* if no return value, C_FUN_* if a return value is needed, J_EVT_* for JS-initiated notifications.
  2. JS side: Register a handler via UiDriver.registerEventHandler("C_CMD_YOUR_MSG", handler) in both app.js and app_monaco.js.
  3. C++ side: Call asyncSendMessageWithResultP("C_FUN_YOUR_MSG", data) (or the legacy API) from editor.cpp or a higher-level wrapper method in editor.h.
  4. Handle the reply: If async, .then() on the returned promise or connect to asyncReplyReceived signal.
  5. JS→C++ events: Just call UiDriver.sendMessage("J_EVT_YOUR_MSG", data) from JS and handle the parsed message in Editor::on_proxyMessageReceived().

Dual Editor Engine

Notepadqq ships two editor engines:

  • CodeMirror (default): index.html + app.js
  • Monaco (VS Code's editor): index_monaco.html + app_monaco.js

Both implement the identical message protocol. The C++ side selects the engine via Editor::useMonaco() (editor.cpp:33). Any new message must be implemented in both app.js and app_monaco.js.

Key Architecture Notes

  • QWebChannel serialises all values as QVariant (C++) ↔ plain JS values (JSON-compatible types).
  • JS-to-C++ messages use a callback parameter function(ret) {} even when the return value is unused — the QWebChannel bridge requires this for the method call to work.
  • The UiDriver maintains a msgQueue for messages sent before the WebChannel is ready; they are flushed once QWebChannel initialises.
  • C++ messages sent before the editor fires J_EVT_READY are queued and delivered once editorReady signal fires (editor.cpp:419-426).

© notepadqq, 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 .agents/skills/js-cpp-protocol of notepadqq/notepadqq.

Open the folder on GitHubat commit 37652c5

Compare with similar skills

JS Cpp Protocol 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.

JS Cpp Protocol compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
JS Cpp Protocol this skillnotepadqq/notepadqq2.3k—~3.2kAutomated safety check: PassGPL-3.0
Bump LibdatadogDataDog/dd-trace-dotnet573—~1.7kAutomated safety check: PassApache-2.0
Debug CIweb-infra-dev/rslint460—~2.8kAutomated safety check: PassMIT
Releasing Blancbnfy/blanc105—~2.9kAutomated safety check: NotesMIT
Subspace Buildsdallison/subspace104—~990Automated safety check: PassApache-2.0
Gui Testlibnativeapi/nativeapi157—~3.5kAutomated safety check: PassMIT

Similar skills

  • Bump Libdatadog

    DataDog/dd-trace-dotnet

    Official

    Update/bump the libdatadog native library version in dd-trace-dotnet.

    573 GitHub stars~1.7k tokensUpdated today
    DevelopmentAuto-check passed
  • Debug CI

    web-infra-dev/rslint

    Reproduce Linux CI failures locally using Docker when the same tests pass on the host, especially Go platform differences and VS Code extension tests requiring xvfb.

    460 GitHub stars~2.8k tokensUpdated today
    DevelopmentAuto-check passed
  • Releasing Blanc

    bnfy/blanc

    Full runbook for cutting a Blanc desktop release — scripts/release.sh mechanics and its required BLANCRELEASE env vars, macOS notarization via 1Password, the Touch ID provisioning profile and…

    105 GitHub stars~2.9k tokensUpdated today
    DevOps & CloudAuto-check: notes
  • Subspace Builds

    dallison/subspace

    Build and test Subspace across supported platforms and build systems.

    104 GitHub stars~990 tokensUpdated yesterday
    Backend & APIsAuto-check passed
  • Gui Test

    libnativeapi/nativeapi

    End-to-end test a desktop app (Flutter desktop apps and plain native executables such as C++ examples) by launching the real app, driving it with guarded synthetic mouse input — eased moves, clicks…

    157 GitHub stars~3.5k tokensUpdated today
    MobileAuto-check passed
  • Build Northstar

    nordstjernen-web/northstar-browser

    Configure, compile, and smoke-test a Meson-based C or C++ desktop browser on Linux, macOS, or Windows, and diagnose dependency, compiler, linker, runtime-library, build-directory, or…

    112 GitHub stars~1.3k tokensUpdated yesterday
    Testing & QAAuto-check passed

More from notepadqq/notepadqq

  • Release

    notepadqq/notepadqq

    Release a new Notepadqq version. An agent skill from notepadqq/notepadqq.

    2.3k GitHub stars~2k tokensUpdated 2 days ago
    Auto-check passed

Categories

Questions about JS Cpp Protocol

What does JS Cpp Protocol do?

Reference for the communication protocol between the JavaScript editor (CodeMirror or Monaco) and the C++/Qt UI layer via QWebChannel. JS Cpp Protocol is an agent skill from notepadqq/notepadqq. Reference for the communication protocol between the JavaScript editor (CodeMirror or Monaco) and the C++/Qt UI layer via QWebChannel.

When should I use JS Cpp Protocol?

JS Cpp Protocol fits situations like: implementing new editor features; adding messages to the bridge; debugging JS/C++ communication; understanding how editor commands flow between layers.

How do I install JS Cpp Protocol in Claude Code?

Run `npx skills add notepadqq/notepadqq --skill js-cpp-protocol -a claude-code`. Or copy the skill folder (.agents/skills/js-cpp-protocol in notepadqq/notepadqq) into .claude/skills/js-cpp-protocol in your project. Claude Code loads it when a task matches its description.

How do I install JS Cpp Protocol in Codex?

Run `npx skills add notepadqq/notepadqq --skill js-cpp-protocol -a codex`. Or copy the skill folder (.agents/skills/js-cpp-protocol in notepadqq/notepadqq) into .agents/skills/js-cpp-protocol in your project. Codex loads it when a task matches its description.

Can I use JS Cpp Protocol 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 notepadqq/notepadqq --skill js-cpp-protocol -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/js-cpp-protocol, .gemini/skills/js-cpp-protocol, .github/skills/js-cpp-protocol and .opencode/skills/js-cpp-protocol in your project.

What does JS Cpp Protocol need to run?

SKILL.md names no scripts, command-line tools or credentials: JS Cpp Protocol is instructions for the agent only.

Does JS Cpp Protocol access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is JS Cpp Protocol 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 JS Cpp Protocol use?

JS Cpp Protocol 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 JS Cpp Protocol use?

About 3.2k tokens (SKILL.md is roughly 13k 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 JS Cpp Protocol?

Skills that share tags, products or a category with JS Cpp Protocol: Bump Libdatadog (DataDog/dd-trace-dotnet, 573 stars), Debug CI (web-infra-dev/rslint, 460 stars), Releasing Blanc (bnfy/blanc, 105 stars) and Subspace Builds (dallison/subspace, 104 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains JS Cpp Protocol?

notepadqq (a GitHub organization) maintains it in notepadqq/notepadqq, which has 2,332 GitHub stars. The repository holds 2 skills in this directory. The repository was last updated on October 5, 2026.

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