pywry-orientation
When to reach for PyWry MCP tools (native webview rendering, Plotly, TradingView, AgGrid, chat) instead of writing Flask/Streamlit/Dash/Electron code. Use at…
**CRITICAL**: This is a **native desktop application** using PyWry/WRY (Rust WebView). This is **NOT** a browser. This is **NOT** Jupyter. This is **NOT** an iframe.
$ npx -y skills add deeleeramone/PyWry --skill native --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/nativeContext preview
The summary Claude sees to decide when to auto-load this skill.
**CRITICAL**: This is a **native desktop application** using PyWry/WRY (Rust WebView). This is **NOT** a browser. This is **NOT** Jupyter. This is **NOT** an iframe.
> **CRITICAL**: This is a **native desktop application** using PyWry/WRY (Rust WebView). > This is **NOT** a browser. This is **NOT** Jupyter. This is **NOT** an iframe.
You're creating widgets for a **native desktop window** powered by:
The widget runs in a **standalone system window** with:
❌ **NOT a web browser** - No DevTools (unless explicitly enabled), no extensions, no URL bar ❌ **NOT Jupyter** - No cell output area, no kernel, no notebook context ❌ **NOT an iframe** - No parent page, no sandboxing, no cross-origin restrictions
┌───────────────────────────────────────────────────────────┐
│ Native Window │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Title Bar (OS-native) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ │ │
│ │ WebView (WRY/Tauri) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Your Widget Content │ │ │
│ │ │ (HTML/CSS/JS via PyWry API) │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────┘
↕ Python ↔ Rust ↔ OS integration# You have the entire window - use it
content = Div(
content="<h1>Dashboard</h1>",
component_id="main",
style="height: 100vh; width: 100vw; padding: 20px;",
)# Top toolbar for primary navigation
create_widget(
html=content.build_html(),
toolbars=[{
"position": "top",
"items": [
{"type": "button", "label": "File", "event": "menu:file"},
{"type": "button", "label": "Edit", "event": "menu:edit"},
{"type": "button", "label": "View", "event": "menu:view"},
]
}]
)# Let OS dark/light mode control the theme update_theme(widget_id, theme="system")
**CRITICAL**: Buttons work automatically when events follow `elementId:action` pattern.
# Counter widget - buttons update content automatically
create_widget(
html='<div id="counter" style="font-size:48px;text-align:center">0</div>',
toolbars=[{
"position": "top",
"items": [
{"type": "button", "label": "+1", "event": "counter:increment"},
{"type": "button", "label": "-1", "event": "counter:decrement"},
{"type": "button", "label": "Reset", "event": "counter:reset"}
]
}]
)The magic: `event="counter:increment"` automatically: 1. Finds element with `id="counter"` 2. Increments its text content by 1 3. Updates the display
Supported actions:
# Detect window close
events = get_events(widget_id, clear=True)
for e in events:
if e["event_type"] == "pywry:disconnect":
# User closed the window - cleanup
cleanup_resources()| Component | Why | |-----------|-----| | `TabGroup` | Multi-view navigation (like app tabs) | | `SecretInput` | Secure API key storage | | `Marquee` | Live data tickers (full width available) | | `Plotly` | Full interactive charts (zoom, pan, export) |
from pywry import PyWry
from pywry.toolbar import Button, Div, TabGroup, Toolbar
app = PyWry()
# Create main content area
content = Div(
content="""
<h1 style="margin: 0;">Financial Dashboard</h1>
<p>Real-time market data</p>
""",
component_id="dashboard",
style="padding: 24px; height: calc(100vh - 100px);",
)
# Create window with toolbars
widget = app.show(
html=content.build_html(),
title="Market Dashboard",
height=800,
toolbars=[
Toolbar(
position="top",
items=[
Button(label="Refresh", event="action:refresh", variant="primary"),
Button(label="Settings", event="action:settings", variant="ghost"),
]
)
]
)
# Event loop
while True:
events = widget.get_events(clear=True)
for e in events:
if e["event_type"] == "pywry:disconnect":
exit()
elif e["event_type"] == "action:refresh":
# Refresh data...
pass# Triggers native OS save dialog
download(widget_id,
url="data:text/csv;base64,...",
filename="export.csv")# Ope
PyWry is a cross-platform app factory, rendering engine and UI toolkit for Python that produces native desktop, web, and notebook experiences from a single API.
Repo: deeleeramone/PyWry
When to reach for PyWry MCP tools (native webview rendering, Plotly, TradingView, AgGrid, chat) instead of writing Flask/Streamlit/Dash/Electron code. Use at…
Add OAuth2 authentication to PyWry apps — Google, GitHub, Microsoft, or any OIDC provider.
Autonomous PyWry application building using LLM sampling, elicitation, and progress reporting.
How an agent operates inside a PyWry chat widget — reading user messages, attachments, @-context, tool-call result cards, edit/resend, settings changes.
**STOP. THIS IS THE AUTHORITATIVE REFERENCE FOR ALL COMPONENTS.** **YOU MUST USE THE EXACT EVENT SIGNATURES DOCUMENTED HERE.** **THERE ARE NO EXCEPTIONS. NO…