diff --git a/pkgs/anoia/example-output/addresses/1/attribute b/pkgs/anoia/example-output/addresses/1/attribute
new file mode 100644
index 00000000..b54f8c3c
--- /dev/null
+++ b/pkgs/anoia/example-output/addresses/1/attribute
@@ -0,0 +1 @@
+a11
diff --git a/pkgs/anoia/example-output/addresses/3/attribute b/pkgs/anoia/example-output/addresses/3/attribute
new file mode 100644
index 00000000..711c1a16
--- /dev/null
+++ b/pkgs/anoia/example-output/addresses/3/attribute
@@ -0,0 +1 @@
+a33
diff --git a/pkgs/anoia/example-output/addresses/5/attribute b/pkgs/anoia/example-output/addresses/5/attribute
new file mode 100644
index 00000000..80923457
--- /dev/null
+++ b/pkgs/anoia/example-output/addresses/5/attribute
@@ -0,0 +1 @@
+a55
diff --git a/pkgs/anoia/example-output/addresses/6/attribute b/pkgs/anoia/example-output/addresses/6/attribute
new file mode 100644
index 00000000..91395989
--- /dev/null
+++ b/pkgs/anoia/example-output/addresses/6/attribute
@@ -0,0 +1 @@
+a66
diff --git a/pkgs/anoia/example-output/colours/black b/pkgs/anoia/example-output/colours/black
new file mode 100644
index 00000000..c4949eb9
--- /dev/null
+++ b/pkgs/anoia/example-output/colours/black
@@ -0,0 +1 @@
+000000
diff --git a/pkgs/anoia/example-output/colours/blue b/pkgs/anoia/example-output/colours/blue
new file mode 100644
index 00000000..df785ee4
--- /dev/null
+++ b/pkgs/anoia/example-output/colours/blue
@@ -0,0 +1 @@
+0000ff
diff --git a/pkgs/anoia/example-output/colours/green b/pkgs/anoia/example-output/colours/green
new file mode 100644
index 00000000..9f07fb62
--- /dev/null
+++ b/pkgs/anoia/example-output/colours/green
@@ -0,0 +1 @@
+00ff00
diff --git a/pkgs/anoia/example-output/colours/red b/pkgs/anoia/example-output/colours/red
new file mode 100644
index 00000000..db6f1d8e
--- /dev/null
+++ b/pkgs/anoia/example-output/colours/red
@@ -0,0 +1 @@
+ff0000
diff --git a/pkgs/anoia/example-output/name b/pkgs/anoia/example-output/name
new file mode 100644
index 00000000..dbf1b394
--- /dev/null
+++ b/pkgs/anoia/example-output/name
@@ -0,0 +1 @@
+eth1
diff --git a/pkgs/anoia/fs.fnl b/pkgs/anoia/fs.fnl
index f0213494..1e3aa03a 100644
--- a/pkgs/anoia/fs.fnl
+++ b/pkgs/anoia/fs.fnl
@@ -29,4 +29,8 @@
     (error (.. "can't remove " pathname " of kind \"" unknown.mode "\""))))
 
 
-{ : mktree : rmtree }
+{
+ : mktree
+ : rmtree
+ : directory?
+ }
diff --git a/pkgs/anoia/svc.fnl b/pkgs/anoia/svc.fnl
index 002583cc..468434ee 100644
--- a/pkgs/anoia/svc.fnl
+++ b/pkgs/anoia/svc.fnl
@@ -1,5 +1,7 @@
 (local inotify (require :inotify))
 (local { : file-exists? } (require :anoia))
+(local { : directory? } (require :anoia.fs))
+(local lfs (require :lfs))
 
 (fn read-line [name]
   (with-open [f (assert (io.open name :r) (.. "can't open file " name))]
@@ -17,14 +19,30 @@
                      inotify.IN_CLOSE_WRITE)
     handle))
 
+(fn read-value [pathname]
+  (case (lfs.symlinkattributes pathname)
+    nil nil
+    {:mode "directory"}
+    (collect [f (lfs.dir pathname)]
+      (when (not (or (= f ".") (= f "..")))
+        (values f (read-value ( .. pathname "/" f)))))
+    {:mode "file"}
+    (read-line pathname)
+    {:mode "link"}
+    (read-line pathname)
+    unknown
+    (error (.. "can't read " pathname " of kind \"" unknown.mode "\""))))
+
+
 (fn open [directory]
   (let [watcher (watch-fsevents directory)
         has-file? (fn [filename] (file-exists? (.. directory "/" filename)))]
     {
-     :wait (fn [] (watcher:read))
+     :wait #(watcher:read)
      :ready? (fn [self]
                (and (has-file? "state") (not (has-file? ".lock"))))
-     :output (fn [_ filename] (read-line (.. directory "/" filename)))
+     :output (fn [_ filename]
+               (read-value (.. directory "/" filename)))
      :close #(watcher:close)
      }))
 
diff --git a/pkgs/anoia/test-svc.fnl b/pkgs/anoia/test-svc.fnl
new file mode 100644
index 00000000..89830eec
--- /dev/null
+++ b/pkgs/anoia/test-svc.fnl
@@ -0,0 +1,17 @@
+(local svc (require :anoia.svc))
+(local { : view } (require :fennel))
+
+(local ex (svc.open "./example-output"))
+
+(assert (= (ex:output "name") "eth1"))
+
+(assert (=
+         (table.concat (ex:output "colours"))
+         (table.concat { :red "ff0000" :green "00ff00" :blu "0000ff" :black "000000" })))
+
+(assert (=
+         (table.concat (ex:output "addresses"))
+         (table.concat {:1 {:attribute "a11"}
+                        :3 {:attribute "a33"}
+                        :5 {:attribute "a55"}
+                        :6 {:attribute "a66"}})))