diff --git a/library/bootstrap/boot-stage1.factor b/library/bootstrap/boot-stage1.factor
index 0d63de9b1a..98d4d6eabe 100644
--- a/library/bootstrap/boot-stage1.factor
+++ b/library/bootstrap/boot-stage1.factor
@@ -186,6 +186,7 @@ vectors words ;
"/library/ui/panes.factor"
"/library/ui/books.factor"
"/library/ui/outliner.factor"
+ "/library/ui/commands.factor"
"/library/ui/presentations.factor"
"/library/ui/listener.factor"
"/library/ui/ui.factor"
diff --git a/library/ui/commands.factor b/library/ui/commands.factor
new file mode 100644
index 0000000000..8966700271
--- /dev/null
+++ b/library/ui/commands.factor
@@ -0,0 +1,55 @@
+IN: gadgets-presentations
+USING: compiler gadgets gadgets-buttons gadgets-menus
+gadgets-panes generic hashtables inference inspector jedit
+kernel lists namespaces parser prettyprint sequences words ;
+
+SYMBOL: commands
+
+V{ } clone commands global set-hash
+
+: forget-command ( name -- )
+ commands [ [ second = not ] subset-with ] change ;
+
+: define-command ( class name quot -- )
+ over forget-command 3array commands get push ;
+
+: applicable ( object -- seq )
+ commands get [ first call ] subset-with ;
+
+: command-quot ( presented quot -- quot )
+ [ \ drop , curry , [ pane get pane-call ] % ] [ ] make ;
+
+TUPLE: command-button object ;
+
+: command-menu ( command-button -- )
+ command-button-object dup applicable
+ [ [ third command-quot ] keep second swons ] map-with
+