diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2024, Henning Thielemann
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * The names of contributors may not be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,8 @@
+#!/usr/bin/env runghc
+
+> module Main where
+
+> import Distribution.Simple
+
+> main :: IO ()
+> main = defaultMain
diff --git a/portmidi-utility.cabal b/portmidi-utility.cabal
new file mode 100644
--- /dev/null
+++ b/portmidi-utility.cabal
@@ -0,0 +1,32 @@
+Cabal-Version: 2.2
+Name:          portmidi-utility
+Version:       0.0
+Maintainer:    Henning Thielemann <alsa@henning-thielemann.de>
+Author:        Henning Thielemann <alsa@henning-thielemann.de>
+Category:      Sound
+License:       BSD-3-Clause
+License-File:  LICENSE
+Stability:     Experimental
+Build-Type:    Simple
+Synopsis:      PortMidi utilities
+Description:
+  Currently provides a command-line tool
+  that lists all MIDI devices accessible by @PortMidi@.
+
+Source-Repository head
+  type:     darcs
+  location: http://hub.darcs.net/thielema/portmidi-utility/
+
+Source-Repository this
+  type:     darcs
+  tag:      0.0
+  location: http://hub.darcs.net/thielema/portmidi-utility/
+
+Executable portmidi-list-devices
+  Main-Is: ListDevices.hs
+  Hs-Source-Dirs: src
+  GHC-Options: -Wall
+  Default-Language: Haskell98
+  Build-Depends:
+    PortMidi >=0.2 && <0.3,
+    base >=4 && <5
diff --git a/src/ListDevices.hs b/src/ListDevices.hs
new file mode 100644
--- /dev/null
+++ b/src/ListDevices.hs
@@ -0,0 +1,30 @@
+module Main where
+
+import qualified Sound.PortMidi as PM
+import qualified Data.List as List
+import Data.Foldable (for_)
+
+import Control.Exception (bracket_)
+
+import Text.Printf (printf)
+
+
+pmio :: IO (Either PM.PMError a) -> IO ()
+pmio act =
+   either (fail . show) (const $ return ()) =<< act
+
+main :: IO ()
+main =
+   bracket_ (pmio PM.initialize) (pmio PM.terminate) $ do
+
+   numDev <- PM.countDevices
+   for_ (take numDev [0..]) $ \devId -> do
+      info <- PM.getDeviceInfo devId
+      let flags =
+            ("input", PM.input) :
+            ("output", PM.output) :
+            ("opened", PM.opened) :
+            []
+      printf "%3d. %s: %s - %s\n" devId (PM.interface info) (PM.name info) $
+         List.intercalate ", " $
+         map fst $ filter (\(_,access) -> access info) flags
