Gpui Action
Build keyboard-driven UI interactions with declarative actions in GPUI
✨ The solution you've been looking for
Action definitions and keyboard shortcuts in GPUI. Use when implementing actions, keyboard shortcuts, or key bindings.
See It In Action
Interactive preview & real-world examples
AI Conversation Simulator
See how users interact with this skill
User Prompt
I need to add keyboard shortcuts to my GPUI editor component. I want cmd-s for save, arrow keys for navigation, and cmd-q to quit.
Skill Processing
Analyzing request...
Agent Response
Complete action definitions with keyboard bindings and event handlers for a functional editor interface
Quick Start (3 Steps)
Get up and running in minutes
Install
claude-code skill install gpui-action
claude-code skill install gpui-actionConfig
First Trigger
@gpui-action helpCommands
| Command | Description | Required Args |
|---|---|---|
| @gpui-action create-editor-keyboard-shortcuts | Implement standard editor actions like save, quit, and navigation with keyboard shortcuts | None |
| @gpui-action context-aware-key-bindings | Set up different keyboard behaviors for different UI contexts like modals vs main editor | None |
| @gpui-action parameterized-actions | Create actions that accept parameters for dynamic behavior like digit input or text insertion | None |
Typical Use Cases
Create Editor Keyboard Shortcuts
Implement standard editor actions like save, quit, and navigation with keyboard shortcuts
Context-Aware Key Bindings
Set up different keyboard behaviors for different UI contexts like modals vs main editor
Parameterized Actions
Create actions that accept parameters for dynamic behavior like digit input or text insertion
Overview
Overview
Actions provide declarative keyboard-driven UI interactions in GPUI.
Key Concepts:
- Define actions with
actions!macro or#[derive(Action)] - Bind keys with
cx.bind_keys() - Handle with
.on_action()on elements - Context-aware via
key_context()
Quick Start
Simple Actions
1use gpui::actions;
2
3actions!(editor, [MoveUp, MoveDown, Save, Quit]);
4
5const CONTEXT: &str = "Editor";
6
7pub fn init(cx: &mut App) {
8 cx.bind_keys([
9 KeyBinding::new("up", MoveUp, Some(CONTEXT)),
10 KeyBinding::new("down", MoveDown, Some(CONTEXT)),
11 KeyBinding::new("cmd-s", Save, Some(CONTEXT)),
12 KeyBinding::new("cmd-q", Quit, Some(CONTEXT)),
13 ]);
14}
15
16impl Render for Editor {
17 fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
18 div()
19 .key_context(CONTEXT)
20 .on_action(cx.listener(Self::move_up))
21 .on_action(cx.listener(Self::move_down))
22 .on_action(cx.listener(Self::save))
23 }
24}
25
26impl Editor {
27 fn move_up(&mut self, _: &MoveUp, cx: &mut Context<Self>) {
28 // Handle move up
29 cx.notify();
30 }
31
32 fn move_down(&mut self, _: &MoveDown, cx: &mut Context<Self>) {
33 cx.notify();
34 }
35
36 fn save(&mut self, _: &Save, cx: &mut Context<Self>) {
37 // Save logic
38 cx.notify();
39 }
40}
Actions with Parameters
1#[derive(Clone, PartialEq, Action, Deserialize)]
2#[action(namespace = editor)]
3pub struct InsertText {
4 pub text: String,
5}
6
7#[derive(Action, Clone, PartialEq, Eq, Deserialize)]
8#[action(namespace = editor, no_json)]
9pub struct Digit(pub u8);
10
11cx.bind_keys([
12 KeyBinding::new("0", Digit(0), Some(CONTEXT)),
13 KeyBinding::new("1", Digit(1), Some(CONTEXT)),
14 // ...
15]);
16
17impl Editor {
18 fn on_digit(&mut self, action: &Digit, cx: &mut Context<Self>) {
19 self.insert_digit(action.0, cx);
20 }
21}
Key Formats
1// Modifiers
2"cmd-s" // Command (macOS) / Ctrl (Windows/Linux)
3"ctrl-c" // Control
4"alt-f" // Alt
5"shift-tab" // Shift
6"cmd-ctrl-f" // Multiple modifiers
7
8// Keys
9"a-z", "0-9" // Letters and numbers
10"f1-f12" // Function keys
11"up", "down", "left", "right"
12"enter", "escape", "space", "tab"
13"backspace", "delete"
14"-", "=", "[", "]", etc. // Special characters
Action Naming
Prefer verb-noun pattern:
1actions!([
2 OpenFile, // ✅ Good
3 CloseWindow, // ✅ Good
4 ToggleSidebar, // ✅ Good
5 Save, // ✅ Good (common exception)
6]);
Context-Aware Bindings
1const EDITOR_CONTEXT: &str = "Editor";
2const MODAL_CONTEXT: &str = "Modal";
3
4// Same key, different contexts
5cx.bind_keys([
6 KeyBinding::new("escape", CloseModal, Some(MODAL_CONTEXT)),
7 KeyBinding::new("escape", ClearSelection, Some(EDITOR_CONTEXT)),
8]);
9
10// Set context on element
11div()
12 .key_context(EDITOR_CONTEXT)
13 .child(editor_content)
Best Practices
✅ Use Contexts
1// ✅ Good: Context-aware
2div()
3 .key_context("MyComponent")
4 .on_action(cx.listener(Self::handle))
✅ Name Actions Clearly
1// ✅ Good: Clear intent
2actions!([
3 SaveDocument,
4 CloseTab,
5 TogglePreview,
6]);
✅ Handle with Listeners
1// ✅ Good: Proper handler naming
2impl MyComponent {
3 fn on_action_save(&mut self, _: &Save, cx: &mut Context<Self>) {
4 // Handle save
5 cx.notify();
6 }
7}
8
9div().on_action(cx.listener(Self::on_action_save))
Reference Documentation
- Complete Guide: See reference.md
- Action definition, keybinding, dispatch
- Focus-based routing, best practices
- Performance, accessibility
What Users Are Saying
Real feedback from the community
Environment Matrix
Dependencies
Framework Support
Context Window
Security & Privacy
Information
- Author
- longbridge
- Updated
- 2026-01-30
- Category
- ide-plugins
Related Skills
Gpui Action
Action definitions and keyboard shortcuts in GPUI. Use when implementing actions, keyboard …
View Details →Gpui Context
Context management in GPUI including App, Window, and AsyncApp. Use when working with contexts, …
View Details →Gpui Context
Context management in GPUI including App, Window, and AsyncApp. Use when working with contexts, …
View Details →