diff --git a/IPython/config/application.py b/IPython/config/application.py
new file mode 100644
index 0000000..c35bc41
--- /dev/null
+++ b/IPython/config/application.py
@@ -0,0 +1,108 @@
+# encoding: utf-8
+"""
+A base class for a configurable application.
+
+Authors:
+
+* Brian Granger
+"""
+
+#-----------------------------------------------------------------------------
+#  Copyright (C) 2008-2011  The IPython Development Team
+#
+#  Distributed under the terms of the BSD License.  The full license is in
+#  the file COPYING, distributed as part of this software.
+#-----------------------------------------------------------------------------
+
+#-----------------------------------------------------------------------------
+# Imports
+#-----------------------------------------------------------------------------
+
+from copy import deepcopy
+import sys
+
+from IPython.config.configurable import Configurable
+from IPython.utils.traitlets import (
+    Unicode, List
+)
+from IPython.config.loader import (
+    KeyValueConfigLoader, PyFileConfigLoader
+)
+
+#-----------------------------------------------------------------------------
+# Application class
+#-----------------------------------------------------------------------------
+
+
+class Application(Configurable):
+
+    # The name of the application, will usually match the name of the command
+    # line application
+    app_name = Unicode(u'application')
+
+    # The description of the application that is printed at the beginning
+    # of the help.
+    description = Unicode(u'This is an application.')
+
+    # A sequence of Configurable subclasses whose config=True attributes will
+    # be exposed at the command line (shortnames and help).
+    classes = List([])
+
+    # The version string of this application.
+    version = Unicode(u'0.0')
+
+    def __init__(self, **kwargs):
+        Configurable.__init__(self, **kwargs)
+        # Add my class to self.classes so my attributes appear in command line
+        # options.
+        self.classes.insert(0, self.__class__)
+
+    def print_help(self):
+        """Print the help for each Configurable class in self.classes."""
+        for cls in self.classes:
+            cls.class_print_help()
+            print
+
+    def print_description(self):
+        """Print the application description."""
+        print self.description
+        print
+
+    def print_version(self):
+        """Print the version string."""
+        print self.version
+
+    def update_config(self, config):
+        # Save a copy of the current config.
+        newconfig = deepcopy(self.config)
+        # Merge the new config into the current one.
+        newconfig._merge(config)
+        # Save the combined config as self.config, which triggers the traits
+        # events.
+        self.config = config
+
+    def parse_command_line(self, argv=None):
+        """Parse the command line arguments."""
+        if argv is None:
+            argv = sys.argv[1:]
+
+        if '-h' in argv or '--h' in argv:
+            self.print_description()
+            self.print_help()
+            sys.exit(1)
+
+        if '--version' in argv:
+            self.print_version()
+            sys.exit(1)
+
+        loader = KeyValueConfigLoader(argv=argv, classes=self.classes)
+        config = loader.load_config()
+        self.update_config(config)
+
+    def load_config_file(self, filename, path=None):
+        """Load a .py based config file by filename and path."""
+        # TODO: this raises IOError if filename does not exist.
+        loader = PyFileConfigLoader(filename, path=path)
+        config = loader.load_config()
+        self.update_config(config)
+
diff --git a/IPython/config/configurable.py b/IPython/config/configurable.py
index 12abd1c..7d04db1 100755
--- a/IPython/config/configurable.py
+++ b/IPython/config/configurable.py
@@ -22,9 +22,7 @@ Authors:
 
 from copy import deepcopy
 import datetime
-from weakref import WeakValueDictionary
 
-from IPython.utils.importstring import import_item
 from loader import Config
 from IPython.utils.traitlets import HasTraits, Instance
 from IPython.utils.text import indent
@@ -152,13 +150,18 @@ class Configurable(HasTraits):
 
     @classmethod
     def class_get_help(cls):
+        """Get the help string for this class in ReST format."""
         cls_traits = cls.class_traits(config=True)
         final_help = []
-        final_help.append('%s options' % cls.__name__)
-        final_help.append(len(final_help[0])*'-')
+        final_help.append(u'%s options' % cls.__name__)
+        final_help.append(len(final_help[0])*u'-')
         for k, v in cls_traits.items():
             help = v.get_metadata('help')
-            final_help.append(k + " : " + v.__class__.__name__)
+            shortname = v.get_metadata('shortname')
+            header = "%s.%s : %s" % (cls.__name__, k, v.__class__.__name__)
+            if shortname is not None:
+                header += " (shortname=" + shortname + ")"
+            final_help.append(header)
             if help is not None:
                 final_help.append(indent(help))
         return '\n'.join(final_help)
diff --git a/docs/examples/core/appconfig.py b/docs/examples/core/appconfig.py
index 28644ce..7c8954f 100644
--- a/docs/examples/core/appconfig.py
+++ b/docs/examples/core/appconfig.py
@@ -1,10 +1,10 @@
 import sys
 
 from IPython.config.configurable import Configurable
+from IPython.config.application import Application
 from IPython.utils.traitlets import (
     Bool, Unicode, Int, Float, List
 )
-from IPython.config.loader import KeyValueConfigLoader
 
 class Foo(Configurable):
 
@@ -18,35 +18,19 @@ class Bar(Configurable):
     enabled = Bool(True, config=True, shortname="bar-enabled", help="Enable bar.")
 
 
-class MyApp(Configurable):
+class MyApp(Application):
 
-    app_name = Unicode(u'myapp', config=True, shortname="myapp", help="The app name.")
+    app_name = Unicode(u'myapp')
     running = Bool(False, config=True, shortname="running", help="Is the app running?")
     classes = List([Bar, Foo])
-
-    def __init__(self, **kwargs):
-        Configurable.__init__(self, **kwargs)
-        self.classes.insert(0, self.__class__)
-
-    def print_help(self):
-        for cls in self.classes:
-            cls.class_print_help()
-            print
-
-    def parse_command_line(self, argv=None):
-        if argv is None:
-            argv = sys.argv[1:]
-        if '-h' in argv or '--h' in argv:
-            self.print_help()
-            sys.exit(1)
-        loader = KeyValueConfigLoader(argv=argv, classes=self.classes)
-        config = loader.load_config()
-        self.config = config
+    config_file = Unicode(u'', config=True, shortname="config-file", help="Load this config file")
 
 
 def main():
     app = MyApp()
     app.parse_command_line()
+    if app.config_file:
+        app.load_config_file(app.config_file)
     print "app.config:"
     print app.config