diff --git a/curses/pom.xml b/curses/pom.xml
new file mode 100644
index 000000000..117632d57
--- /dev/null
+++ b/curses/pom.xml
@@ -0,0 +1,67 @@
+
+
+
+
+ 4.0.0
+
+
+ org.jline
+ jline-parent
+ 3.27.0-SNAPSHOT
+
+
+ jline-curses
+ JLine Curses
+
+
+ org.jline.curses
+
+
+
+
+ org.jline
+ jline-terminal
+
+
+
+ org.jline
+ jline-reader
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+ true
+ ${java.release.version}
+
+ -Xlint:all,-options,-processing
+
+ true
+
+
+
+
+
+
+
diff --git a/curses/src/main/java/org/jline/curses/Component.java b/curses/src/main/java/org/jline/curses/Component.java
new file mode 100644
index 000000000..0a0a3f1ed
--- /dev/null
+++ b/curses/src/main/java/org/jline/curses/Component.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2002-2018, the original author(s).
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+package org.jline.curses;
+
+import java.util.EnumSet;
+
+import org.jline.terminal.MouseEvent;
+
+public interface Component {
+
+ Position getPosition();
+
+ void setPosition(Position position);
+
+ Position getScreenPosition();
+
+ boolean isIn(int x, int y);
+
+ Size getSize();
+
+ void setSize(Size size);
+
+ Container getParent();
+
+ Size getPreferredSize();
+
+ boolean isFocused();
+
+ boolean isEnabled();
+
+ void enable(boolean enabled);
+
+ void focus();
+
+ void draw(Screen screen);
+
+ EnumSet getBehaviors();
+
+ enum Behavior {
+ NoFocus,
+ FullScreen,
+ NoDecoration,
+ CloseButton,
+ ManualLayout,
+ Popup
+ }
+
+ void handleMouse(MouseEvent event);
+
+ void handleInput(String input);
+}
diff --git a/curses/src/main/java/org/jline/curses/Constraint.java b/curses/src/main/java/org/jline/curses/Constraint.java
new file mode 100644
index 000000000..220b60e17
--- /dev/null
+++ b/curses/src/main/java/org/jline/curses/Constraint.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2002-2018, the original author(s).
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+package org.jline.curses;
+
+public interface Constraint {}
diff --git a/curses/src/main/java/org/jline/curses/Container.java b/curses/src/main/java/org/jline/curses/Container.java
new file mode 100644
index 000000000..357e0a1eb
--- /dev/null
+++ b/curses/src/main/java/org/jline/curses/Container.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2002-2018, the original author(s).
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+package org.jline.curses;
+
+import java.util.Collection;
+
+public interface Container extends Component {
+
+ /**
+ * Returns a read-only collection of all contained components.
+ */
+ Collection getComponents();
+}
diff --git a/curses/src/main/java/org/jline/curses/Curses.java b/curses/src/main/java/org/jline/curses/Curses.java
new file mode 100644
index 000000000..90f4fdccd
--- /dev/null
+++ b/curses/src/main/java/org/jline/curses/Curses.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2002-2018, the original author(s).
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+package org.jline.curses;
+
+import java.util.*;
+import java.util.function.Supplier;
+
+import org.jline.curses.impl.*;
+import org.jline.terminal.Terminal;
+
+public class Curses {
+
+ public enum Border {
+ Single,
+ SingleBevel,
+ Double,
+ DoubleBevel
+ }
+
+ public enum Alignment {
+ Beginning,
+ Center,
+ End,
+ Fill;
+ }
+
+ public enum Location implements Constraint {
+ Center,
+ Top,
+ Bottom,
+ Left,
+ Right
+ }
+
+ public static class GridConstraint implements Constraint {}
+
+ public static GUI gui(Terminal terminal) {
+ return new GUIImpl(terminal);
+ }
+
+ public static WindowBuilder window() {
+ return new WindowBuilder();
+ }
+
+ public static Button button() {
+ return new Button();
+ }
+
+ public static TextArea textArea() {
+ return new TextArea();
+ }
+
+ public static ContainerBuilder border() {
+ return new ContainerBuilder<>(BorderPanel::new);
+ }
+
+ public static ContainerBuilder grid() {
+ return new ContainerBuilder<>(GridPanel::new);
+ }
+
+ public static MenuBuilder menu() {
+ return new MenuBuilder();
+ }
+
+ public static MenuBuilder menu(SubMenu... subMenus) {
+ MenuBuilder builder = new MenuBuilder();
+ builder.contents.addAll(Arrays.asList(subMenus));
+ return builder;
+ }
+
+ public static MenuBuilder menu(SubMenuBuilder... subMenus) {
+ MenuBuilder builder = new MenuBuilder();
+ for (SubMenuBuilder subMenu : subMenus) {
+ builder.contents.add(subMenu.build());
+ }
+ return builder;
+ }
+
+ public static SubMenuBuilder submenu() {
+ return new SubMenuBuilder();
+ }
+
+ public static Box box(String title, Border border, ComponentBuilder> component) {
+ return box(title, border, component.build());
+ }
+
+ public static Box box(String title, Border border, Component component) {
+ return new Box(title, border, component);
+ }
+
+ public interface ComponentBuilder {
+
+ C build();
+ }
+
+ public static class ContainerBuilder implements ComponentBuilder {
+
+ private final Map components = new LinkedHashMap<>();
+ private final Supplier supplier;
+
+ ContainerBuilder(Supplier supplier) {
+ this.supplier = supplier;
+ }
+
+ public ContainerBuilder add(Component component, C constraint) {
+ components.put(component, constraint);
+ return this;
+ }
+
+ public ContainerBuilder add(ComponentBuilder> component, C constraint) {
+ return add(component.build(), constraint);
+ }
+
+ public Container build() {
+ AbstractPanel container = supplier.get();
+ components.forEach(container::addComponent);
+ return container;
+ }
+ }
+
+ public static class SubMenuBuilder {
+ private String name;
+ private String key;
+ List