diff --git a/deployment/macos/pack.py b/deployment/macos/pack.py
new file mode 100644
index 0000000000000000000000000000000000000000..d849446be5d0f2e01d2ff27bed4c958cf5e7d16d
--- /dev/null
+++ b/deployment/macos/pack.py
@@ -0,0 +1,357 @@
+"""
+deploy.py helps you package your code into a standalone application.
+
+for now, MacOS X and Linux are supported...
+"""
+import os
+import subprocess
+import shutil
+import sys
+import glob
+
+def _lib_name(component):
+  return 'lib%s.dylib' % component
+
+def _deps_for_lib(lib, pool, recursive=True):
+  if lib in pool:
+    return
+  otool=subprocess.Popen(['otool', '-L', lib], stdout=subprocess.PIPE)
+  output=otool.communicate()[0]
+  lines=output.split('\n')[1:]
+  for line in lines:
+    d=line.split(' ')[0].strip()
+    if len(d)>0:
+      if d==lib:
+        continue
+      if d not in pool:
+        if d.startswith('/System') or d.startswith('/usr/lib'):
+          continue
+        if recursive:
+          _deps_for_lib(d, pool)
+        pool.add(d)        
+  return
+
+def collect_deps(stage_dir, components, binaries, libexec_binaries,
+                 site_packages, site_packages_dir, libexec_path='openstructure'):
+  """
+  Collect the dependencies for the given components and returns a list of 
+  frameworks/libraries that the component depends on.
+  """
+  pool=set()
+  for component in components:
+    lib_name=os.path.abspath(os.path.join(stage_dir, 'lib', 
+                                          _lib_name(component)))  
+    if not os.path.exists(lib_name):
+      print 'WARNING:', lib_name, 'does not exist'
+    if lib_name not in pool:
+      _deps_for_lib(lib_name, pool)
+      pool.add(lib_name)    
+  for bin in binaries:  
+    bin_name=os.path.abspath(os.path.join(stage_dir, 'bin', 
+                                          bin))  
+    if not os.path.exists(bin_name):
+      print 'WARNING:', bin_name, 'does not exist'
+      continue
+    if bin_name not in pool:
+      _deps_for_lib(bin_name, pool)
+  for bin in libexec_binaries:
+    bin_name=os.path.abspath(os.path.join(stage_dir, 'libexec', libexec_path,
+                                          bin))
+    if not os.path.exists(bin_name):
+      print 'WARNING:', bin_name, 'does not exist'
+      continue
+    if bin_name not in pool:
+      _deps_for_lib(bin_name, pool)
+  for site_package in site_packages:
+    full_path=get_python_module_path(site_package)
+    print full_path
+    if not os.path.exists(full_path):
+      print 'WARNING:', site_package, 'does not exists'
+      continue
+    if os.path.isdir(full_path):
+      for so_file in glob.glob(os.path.join(full_path, '*.so')):
+        _deps_for_lib(so_file, pool)
+  return pool
+
+LIBEXEC_SCRIPTS=['ost_config']
+LIBEXEC_BINARIES=[]
+GUI_LIBEXEC_BINARIES=['gosty']
+BINARIES=['ldt', 'chemdict_tool', 'tmalign', 'tmscore']
+GUI_BINARIES=[]
+GUI_COMPONENTS=['gfx', 'gui', 'info']
+COMPONENTS=['mol', 'geom', 'conop', 'seq_alg', 'seq',
+            'img', 'img_alg', 'io', 'db', 'base']
+GUI_SCRIPTS=['dng']
+SCRIPTS=['ost']
+CHANGE_ID_RPATH='install_name_tool -id @rpath/%s %s'   
+CHANGE_ID='install_name_tool -id @rpath/%s %s'
+CHANGE_LOAD_CMD_RPATH='install_name_tool -change %s @rpath/%s %s'
+CHANGE_LOAD_CMD='install_name_tool -change %s @executable_path/%s %s'
+ADD_RPATH='install_name_tool -add_rpath %s %s 2> /dev/null'
+SITE_PACKAGES=[]
+GUI_SITE_PACKAGES=['sip.so', 'sipconfig.py', 'sipdistutils.py', 'PyQt4']
+REMOVE_HEADERS='rm -rf `find %s/lib -type d -name Headers`'
+REMOVE_CURRENT='rm -rf `find %s/lib -type d -name Current`'
+# collect libs of non-standard libraries/frameworks we depend on
+
+def copy_binaries(stage_dir, outdir, binary_names, scripts, bin_dir,
+                  append_bin=True):
+
+  exe_path=os.path.abspath(os.path.join(outdir, bin_dir))
+  for binary_name in binary_names:
+    if append_bin:
+      bin_name=os.path.join(stage_dir, bin_dir, binary_name)
+    else:
+      bin_name=os.path.join(stage_dir, binary_name)
+    if not os.path.exists(bin_name):
+      print 'WARNING:', binary_name, 'does not exist'
+      continue
+    dst_name=os.path.join(outdir, bin_dir, os.path.basename(bin_name))
+    shutil.copy(bin_name, dst_name)
+    update_load_commands(dst_name, True, exe_path)
+  for script in scripts:
+    shutil.copy(os.path.join(stage_dir, bin_dir, script),
+                os.path.join(outdir,bin_dir, script))
+
+def split_framework_components(abs_path):
+    """
+    Splits the path pointing to a dynamic library within a framework
+    
+    '/System/Frameworks/A.framework/Versions/4/A' =>
+    ['/System/Frameworks/A.framework', 'Versions/4/A']
+    """
+    parts=abs_path.split('/')
+    for i, s in enumerate(parts):
+      if s.endswith('.framework'):
+        lead=os.path.join('/', *parts[:i+1])
+        trail=os.path.join(*parts[i+1:])
+        return lead, trail
+
+def change_id(id, lib):
+  os.chmod(lib, 0666)
+  os.system(CHANGE_ID_RPATH % (id,lib))
+  os.chmod(lib, 0444)
+
+def update_load_commands(lib, exe, exe_path):
+  direct_deps=set()
+  _deps_for_lib(lib, direct_deps, recursive=False)
+  os.chmod(lib, 0666)
+  for direct_dep in direct_deps:
+    if direct_dep.endswith('.dylib'):
+      new_name=os.path.basename(direct_dep)
+      os.system(CHANGE_LOAD_CMD_RPATH % (direct_dep, new_name, lib))
+    else:
+      assert direct_dep.find('.framework/')>=0
+      framework_path, rel_path=split_framework_components(direct_dep)
+      framework_name=os.path.basename(framework_path)
+      new_name=os.path.join(framework_name, rel_path)
+      os.system(CHANGE_LOAD_CMD_RPATH % (direct_dep, new_name, lib))
+  if exe:
+    os.chmod(lib, 0555)
+  else:
+    os.chmod(lib, 0444)
+
+def copy_deps(dependencies, outdir):
+  exe_path=os.path.join(outdir, 'bin')
+  for dep in dependencies:
+    if dep.endswith('.dylib'):
+      dst_name=os.path.join(outdir, 'lib', os.path.basename(dep))
+      if not os.path.exists(dep):
+        continue
+      if os.path.exists(dst_name):
+        continue
+      shutil.copy(dep, dst_name)
+      change_id(os.path.basename(dep), dst_name)
+      update_load_commands(dst_name, False, exe_path)
+    else:
+      assert dep.find('.framework/')>=0
+      framework_path, rel_path=split_framework_components(dep)
+      framework_name=os.path.basename(framework_path)
+      dst_name=os.path.join(outdir, 'lib', framework_name)
+      shutil.copytree(framework_path, dst_name)
+      change_id(os.path.join(dst_name, rel_path),
+                os.path.join(dst_name, rel_path))
+      os.unlink(os.path.join(dst_name, os.path.splitext(framework_name)[0]))
+      update_load_commands(os.path.join(dst_name, rel_path), False, 
+                           exe_path)
+
+def update_pymod_shared_objects(lib_path, path, files):
+  exe_path=os.path.abspath(os.path.join(lib_path, '../bin'))
+  for f in files:
+    if not os.path.exists(os.path.join(path, f)):
+      continue
+    base, ext=os.path.splitext(f)
+    if  ext=='.so':
+      path_to_lib_path=os.path.relpath(lib_path, path)
+      abs_name=os.path.join(path, f)
+      os.system(ADD_RPATH % (path_to_lib_path, abs_name))
+      update_load_commands(abs_name, False, exe_path)
+    elif ext in ('.pyc', '.pyo'):
+      os.unlink(os.path.join(path, f))
+
+def merge_tree(src, dst):
+  """
+  Similar to shutil.copytree, but does not complain when the destination
+  directory already exists.
+  """
+  names = os.listdir(src)
+  if not os.path.exists(dst):
+    os.makedirs(dst)
+  errors = []
+  for name in names:
+    srcname = os.path.join(src, name)
+    dstname = os.path.join(dst, name)
+    try:
+        if os.path.islink(srcname):
+            linkto = os.readlink(srcname)
+            os.symlink(linkto, dstname)
+        elif os.path.isdir(srcname):
+            merge_tree(srcname, dstname)
+        else:
+            shutil.copy2(srcname, dstname)
+    except (IOError, os.error), why:
+        errors.append((srcname, dstname, str(why)))
+    except shutil.Error, err:
+        errors.extend(err.args[0])
+  try:
+      shutil.copystat(src, dst)
+  except OSError, why:
+      if WindowsError is not None and isinstance(why, WindowsError):
+          # Copying file access times may fail on Windows
+          pass
+      else:
+          errors.extend((src, dst, str(why)))
+  if errors:
+      raise shutil.Error, errors
+
+def get_site_package_dir():
+  """
+  Get site-package directory of this python installation. This assumes 
+  that ost was linked against the same version of Python (which is a very
+  reasonable thing to do, as this script is most likely run with ost).
+  """
+  for p in sys.path:
+    pattern='/site-packages'
+    index=p.find(pattern)
+    if index>=0:
+      return p[:index+len(pattern)]
+  raise RuntimeError("Couldn't determine site-packages location")
+
+def get_python_module_path(module):
+  for path in sys.path:
+    full_path=os.path.join(path, module)
+    if os.path.exists(full_path):
+      return full_path
+  return None
+  
+  
+def get_python_home():
+  """
+  Derive Python home by looking at the location of the os module
+  """
+  return os.path.dirname(sys.modules['os'].__file__)
+
+
+class Package(object):
+  def __init__(self, name, root_dir, binaries=[], scripts=[], 
+               modules=[], libraries=[], libexec_dir=None, libexec_scripts=[]):
+    self.root_dir=root_dir
+    self.name=name
+    self.binaries=binaries
+    self.scripts=scripts
+    self.libraries=libraries
+    self.libexec_dir=libexec_dir
+    self.libexec_scripts=libexec_scripts
+    self.pymod_dir=os.path.join('lib', 'python%d.%d' % sys.version_info[0:2],
+                                'site-packages')
+    self.modules=modules
+    self.libexec_binaries=[]
+    self.site_packages=[]
+    self.site_packages_dir=''
+  def status(self, message):
+    print '%s: %s' % (self.name, message)
+
+  def _prepare_output_dir(self, output_dir):
+    """
+    Prepares the output directory structure, including lib, bin and an optional
+    libexec directory.
+    """
+    #if os.path.exists(output_dir):
+    #  shutil.rmtree(output_dir)
+    if not os.path.exists(output_dir):
+      os.makedirs(output_dir)
+    if not os.path.exists(os.path.join(output_dir, 'bin')):
+      os.makedirs(os.path.join(output_dir, 'bin'))
+    if not os.path.exists(os.path.join(output_dir, 'lib')):
+      os.makedirs(os.path.join(output_dir, 'lib'))
+    if self.libexec_dir:
+      out_exec_dir=os.path.join(output_dir, 'libexec', self.libexec_dir)
+      if not os.path.exists(out_exec_dir):
+        print 'making...', out_exec_dir
+        os.makedirs(out_exec_dir)
+  def _copy_site_packages(self, output_dir):
+    for sp in SITE_PACKAGES:
+      src=get_python_module_path(sp)
+      if os.path.isdir(src):
+        merge_tree(src, os.path.joini(output_dir, self.pymod_dir, sp))
+      else:
+        shutil.copy(src, os.path.join(output_dir, self.pymod_dir, sp))
+    print 'updating link commands of python shared objects'
+    os.path.walk(os.path.join(output_dir, 'lib'), 
+                 update_pymod_shared_objects, 
+                 os.path.join(output_dir, 'lib'))
+
+  def ship(self, output_dir):
+    self._prepare_output_dir(output_dir)
+    if os.path.exists(os.path.join(self.root_dir, 'share')):
+      self.status('copying shared data files')
+      merge_tree(os.path.join(self.root_dir, 'share'), 
+                 os.path.join(output_dir, 'share'))
+    self.status('collecting dependencies')
+    deps=collect_deps(self.root_dir, self.libraries, self.binaries, 
+                      self.libexec_binaries, self.site_packages, 
+                      self.site_packages_dir)
+    # when running in non-gui mode, we are most likely missing the boost
+    # python library. Let's add it to the list of dependencies by
+    # inspecting "_ost_base.so".
+    pymod_dir='lib/python%d.%d/site-packages' % sys.version_info[0:2]
+    _deps_for_lib(os.path.join(self.root_dir, pymod_dir, 'ost/_ost_base.so'),
+                  deps, recursive=False)
+    self.status('copying dependencies')
+    copy_deps(deps, output_dir)
+    if self.libexec_dir:
+      self.status('copying libexec binaries')
+      copy_binaries(self.root_dir, output_dir, self.libexec_binaries, 
+                    self.libexec_scripts,
+                    os.path.join('libexec', self.libexec_dir))
+    self.status('copying binaries')
+    copy_binaries(self.root_dir, output_dir, self.binaries, 
+                self.scripts, 'bin')
+    self.status('copying pymod')
+    merge_tree(os.path.join(self.root_dir,self.pymod_dir), 
+               os.path.join(output_dir, self.pymod_dir))
+    self._copy_site_packages(output_dir)
+
+class OpenStructure(Package):
+  def __init__(self, stage_dir, minimal=True):
+    libs=['ost_mol', 'ost_geom', 'ost_conop', 'ost_seq_alg',
+          'ost_io', 'ost_db', 'ost_base', 'ost_seq', 'ost_mol_alg']
+    super(OpenStructure, self).__init__('OpenStructure', stage_dir, 
+                                        binaries=['ldt', 'chemdict_tool'],
+                                        libexec_scripts=['ost_config'],
+                                        scripts=['ost'],
+                                        libraries=libs,
+                                        libexec_dir='openstructure')
+
+class Qmean(Package):
+  def __init__(self, stage_dir):
+    super(Qmean, self).__init__('Qmean', stage_dir,
+                                scripts=['qmean'],
+                                libexec_scripts=['qmean_script.py'],
+                                libexec_dir='qmean',
+                                libraries=['qmean'])
+ost=OpenStructure('../../stage')
+qmean=Qmean('../../../../../qmean/stage')
+ost.ship('qmean')
+qmean.ship('qmean')
+