diff --git a/src/commandpanel.cpp b/src/commandpanel.cpp
--- a/src/commandpanel.cpp
+++ b/src/commandpanel.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2015 Hasan Yavuz Özderya
+  Copyright © 2016 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -17,11 +17,12 @@
   along with serialplot.  If not, see .
 */
 
+#include 
+#include 
+
 #include "commandpanel.h"
 #include "ui_commandpanel.h"
-
-#include 
-#include 
+#include "setting_defines.h"
 
 CommandPanel::CommandPanel(QSerialPort* port, QWidget *parent) :
     QWidget(parent),
@@ -46,15 +47,15 @@ CommandPanel::CommandPanel(QSerialPort* 
     _menu.addSeparator();
 
     command_name_counter = 0;
-    newCommand(); // add an empty slot by default
 }
 
 CommandPanel::~CommandPanel()
 {
+    commands.clear(); // UI will 'delete' actual objects
     delete ui;
 }
 
-void CommandPanel::newCommand()
+CommandWidget* CommandPanel::newCommand()
 {
     auto command = new CommandWidget();
     command_name_counter++;
@@ -64,6 +65,14 @@ void CommandPanel::newCommand()
     connect(command, &CommandWidget::sendCommand, this, &CommandPanel::sendCommand);
     connect(command, &CommandWidget::focusRequested, this, &CommandPanel::focusRequested);
     _menu.addAction(command->sendAction());
+
+    // add to command list and remove on destroy
+    commands << command;
+    connect(command, &QObject::destroyed, [this](QObject* obj)
+            {
+                commands.removeOne(static_cast(obj));
+            });
+    return command;
 }
 
 void CommandPanel::sendCommand(QByteArray command)
@@ -89,3 +98,66 @@ QAction* CommandPanel::newCommandAction(
 {
     return &_newCommandAction;
 }
+
+unsigned CommandPanel::numOfCommands()
+{
+    return commands.size();
+}
+
+void CommandPanel::saveSettings(QSettings* settings)
+{
+    settings->beginGroup(SettingGroup_Commands);
+    settings->beginWriteArray(SG_Commands_Command);
+    for (int i = 0; i < commands.size(); i ++)
+    {
+        settings->setArrayIndex(i);
+        auto command = commands[i];
+        settings->setValue(SG_Commands_Name, command->name());
+        settings->setValue(SG_Commands_Type, command->isASCIIMode() ? "ascii" : "hex");
+        settings->setValue(SG_Commands_Data, command->commandText());
+    }
+    settings->endArray();
+    settings->endGroup();
+}
+
+void CommandPanel::loadSettings(QSettings* settings)
+{
+    // clear all commands
+    while (commands.size())
+    {
+        auto command = commands.takeLast();
+        command->disconnect();
+        delete command;
+    }
+
+    // load commands
+    settings->beginGroup(SettingGroup_Commands);
+    unsigned size = settings->beginReadArray(SG_Commands_Command);
+
+    for (unsigned i = 0; i < size; i ++)
+    {
+        settings->setArrayIndex(i);
+        auto command = newCommand();
+
+        // load command name
+        QString name = settings->value(SG_Commands_Name, "").toString();
+        if (!name.isEmpty()) command->setName(name);
+
+        // Important: type should be set before command data for correct validation
+        QString type = settings->value(SG_Commands_Type, "").toString();
+        if (type == "ascii")
+        {
+            command->setASCIIMode(true);
+        }
+        else if (type == "hex")
+        {
+            command->setASCIIMode(false);
+        } // else unchanged
+
+        // load command data
+        command->setCommandText(settings->value(SG_Commands_Data, "").toString());
+    }
+
+    settings->endArray();
+    settings->endGroup();
+}
diff --git a/src/commandpanel.h b/src/commandpanel.h
--- a/src/commandpanel.h
+++ b/src/commandpanel.h
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2015 Hasan Yavuz Özderya
+  Copyright © 2016 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -23,8 +23,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 
 #include "commandwidget.h"
 
@@ -41,7 +43,14 @@ public:
     ~CommandPanel();
 
     QMenu* menu();
+    /// Action for creating a new command.
     QAction* newCommandAction();
+    /// Stores commands into a `QSettings`
+    void saveSettings(QSettings* settings);
+    /// Loads commands from a `QSettings`.
+    void loadSettings(QSettings* settings);
+    /// Number of commands
+    unsigned numOfCommands();
 
 signals:
     // emitted when user tries to send an empty command
@@ -52,11 +61,12 @@ private:
     QSerialPort* serialPort;
     QMenu _menu;
     QAction _newCommandAction;
+    QList commands;
 
     unsigned command_name_counter;
 
 private slots:
-    void newCommand();
+    CommandWidget* newCommand();
     void sendCommand(QByteArray command);
 };
 
diff --git a/src/commandwidget.cpp b/src/commandwidget.cpp
--- a/src/commandwidget.cpp
+++ b/src/commandwidget.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2015 Hasan Yavuz Özderya
+  Copyright © 2016 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -101,6 +101,11 @@ bool CommandWidget::isASCIIMode()
     return ui->pbASCII->isChecked();
 }
 
+void CommandWidget::setASCIIMode(bool enabled)
+{
+    ui->pbASCII->setChecked(enabled);
+}
+
 void CommandWidget::setName(QString name)
 {
     ui->leName->setText(name);
@@ -120,3 +125,14 @@ QAction* CommandWidget::sendAction()
 {
     return &_sendAction;
 }
+
+QString CommandWidget::commandText()
+{
+    return ui->leCommand->text();
+}
+
+void CommandWidget::setCommandText(QString str)
+{
+    ui->leCommand->selectAll();
+    ui->leCommand->insert(str);
+}
diff --git a/src/commandwidget.h b/src/commandwidget.h
--- a/src/commandwidget.h
+++ b/src/commandwidget.h
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2015 Hasan Yavuz Özderya
+  Copyright © 2016 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -39,26 +39,36 @@ public:
     void setName(QString name);
     QString name();
     void setFocusToEdit();
+    /// An action that triggers sending of command.
     QAction* sendAction();
+    /// true: ascii mode, false hex mode
+    bool isASCIIMode();
+    /// true: ascii mode, false hex mode
+    void setASCIIMode(bool ascii);
+        /// Returns the command data as text
+    QString commandText();
+    /// Set command data as text. Text is validated according to current mode.
+    void setCommandText(QString str);
 
 signals:
-    void deleteRequested(CommandWidget* thisWidget); // emitted when delete button is clicked
+    /// emitted when delete button is clicked
+    void deleteRequested(CommandWidget* thisWidget);
 
-    // emitted when send button is clicked
-    //
-    // in case of hex mode, command text should be a hexadecimal
-    // string containing hexadecimal characters only (not even spaces)
+    /**
+     * Emitted when send button is clicked.
+     *
+     * In case of hex mode, command text should be a hexadecimal
+     * string containing hexadecimal characters only (not even spaces)
+     */
     void sendCommand(QByteArray command);
 
-    // emitted when user tries to send an empty command
+    /// emitted when user tries to send an empty command
     void focusRequested();
 
 private:
     Ui::CommandWidget *ui;
     QAction _sendAction;
 
-    bool isASCIIMode(); // true: ascii mode, false hex mode
-
 private slots:
     void onDeleteClicked();
     void onSendClicked();
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -201,6 +201,12 @@ MainWindow::MainWindow(QWidget *parent) 
     // load default settings
     QSettings settings("serialplot", "serialplot");
     loadAllSettings(&settings);
+
+    // ensure command panel has 1 command if none loaded
+    if (!commandPanel.numOfCommands())
+    {
+        commandPanel.newCommandAction()->trigger();
+    }
 }
 
 MainWindow::~MainWindow()
@@ -434,6 +440,7 @@ void MainWindow::saveAllSettings(QSettin
     dataFormatPanel.saveSettings(settings);
     channelMan.saveSettings(settings);
     plotControlPanel.saveSettings(settings);
+    commandPanel.saveSettings(settings);
 }
 
 void MainWindow::loadAllSettings(QSettings* settings)
@@ -443,6 +450,7 @@ void MainWindow::loadAllSettings(QSettin
     dataFormatPanel.loadSettings(settings);
     channelMan.loadSettings(settings);
     plotControlPanel.loadSettings(settings);
+    commandPanel.loadSettings(settings);
 }
 
 void MainWindow::saveMWSettings(QSettings* settings)
diff --git a/src/setting_defines.h b/src/setting_defines.h
--- a/src/setting_defines.h
+++ b/src/setting_defines.h
@@ -76,4 +76,10 @@ const char SG_Plot_AutoScale[] = "autoSc
 const char SG_Plot_YMax[] = "yMax";
 const char SG_Plot_YMin[] = "yMin";
 
+// command setting keys
+const char SG_Commands_Command[] = "command";
+const char SG_Commands_Name[] = "name";
+const char SG_Commands_Type[] = "type";
+const char SG_Commands_Data[] = "data";
+
 #endif // SETTING_DEFINES_H