Index: java/GraphTest.java
===================================================================
--- java/GraphTest.java	(revision dc9ae96b7b1d2a5734bffb939fef13fa7461c582)
+++ java/GraphTest.java	(revision ad24705156d10e68c900c05fab3769ecd41aa766)
@@ -39,4 +39,6 @@
 		else if (f.getPath().endsWith(".zip"))
 		    ctxt.load_zip_file(f, errs);
+		else if (f.getPath().endsWith(".rt0"))
+		    ctxt.load_rt0_file(f, errs);
 		else
 		    System.out.println(f + " of unknown type");
@@ -62,4 +64,5 @@
 	String suf = ".der";
 	System.out.println("Result: " + ret.getSuccess());
+	System.out.println("Proof");
         for (Credential c : ret.getCredentials()) {
             System.out.println(c.simpleString(ctxt));
@@ -73,9 +76,17 @@
 	n = 0;
 	suf = ".pem";
+	System.out.println("Identities");
 	for (Identity i: ids) {
 	    System.out.println("ID: " + i);
 	    i.write(fn + n++ + suf);
 	}
-	ctxt.write_zip_file(new File("./testout.zip"), true, true);
+	try {
+	    ctxt.write_zip_file(new File("./testout.zip"), true, true);
+	}
+	catch (IOException ioe) {
+	    System.err.println("Could not write ZIP: " + ioe);
+	}
+	System.out.println("rt0 with keyids");
+	ctxt.write_rt0(new OutputStreamWriter(System.out), true);
     }
 }
Index: java/net/deterlab/abac/Context.java
===================================================================
--- java/net/deterlab/abac/Context.java	(revision dc9ae96b7b1d2a5734bffb939fef13fa7461c582)
+++ java/net/deterlab/abac/Context.java	(revision ad24705156d10e68c900c05fab3769ecd41aa766)
@@ -6,4 +6,5 @@
 import java.io.*;
 import java.util.*;
+import java.util.regex.*;
 import java.util.zip.*;
 import java.security.*;
@@ -275,7 +276,7 @@
         Collection<Credential> creds = new HashSet<Credential>();
 
-        // only return creds with a cert: all others are derived edges
+        // only non-derived edges
         for (Credential cred : g.getEdges())
-            if (cred.cert() != null)
+            if (!derived_edges.contains(cred))
                 creds.add(cred);
 
@@ -812,4 +813,48 @@
 
     /**
+     * Load from a simple rt0 text format.  A jabac extension.  The format is
+     * <br/>
+     * # comments<br/>
+     * role &lt;- role<br/>
+     * <br/>
+     *
+     * Spaces are not significant around the arrow and the tail can be as long
+     * as needed.
+     * @param f the File to load
+     * @param errors a Map of lines to errors
+     * @throws IOException if there is an error getting the file open
+     */
+    public void load_rt0_file(File f, Map<String, Exception> errors) 
+	    throws IOException {
+	Pattern comment = Pattern.compile("(^\\s*#|^\\s*$)");
+	Pattern rule = Pattern.compile("([\\w\\.]+)\\s*<-+\\s*([\\w\\.\\&]+)");
+	LineNumberReader r = new LineNumberReader(new FileReader(f));
+	String line = null;
+
+	while ((line = r.readLine()) != null) {
+	    Matcher cm = comment.matcher(line);
+	    Matcher rm = rule.matcher(line);
+
+	    if (cm.find()) continue;
+	    if (rm.find()) 
+		add_credential(new Credential(new Role(rm.group(1)), 
+			    new Role(rm.group(2))));
+	    else if (errors != null) 
+		errors.put("Line " + r.getLineNumber(), 
+			new RuntimeException("Unexpected format"));
+	}
+    }
+
+    /**
+     * Equivalent to load_rt0_file(d, null).
+     * @param f the File to load
+     * @throws IOException if there is an error getting the file open
+     */
+    public void load_rt0_file(File f) throws IOException {
+	load_rt0_file(f, null);
+    }
+	
+
+    /**
      * Write the certificates that make up the context as a zip file, with an
      * entry for each credential or identity.  The files are all zipped in a
@@ -853,4 +898,48 @@
 
     /**
+     * Write to a simple rt0 text format.  A jabac extension.
+     * The format is
+     * <br/>
+     * role &lt;- role<br/>
+     * <br/>
+     *
+     * @param w a Writer to print on
+     * @param useKeyIDs a boolean, true to print key IDs not mnemonics
+     */
+    public void write_rt0(Writer w, boolean useKeyIDs) {
+	PrintWriter pw = w instanceof PrintWriter ? 
+	    (PrintWriter) w : new PrintWriter(w);
+
+	for (Credential c: credentials()) 
+	    pw.println(useKeyIDs ? c.toString() : c.simpleString(this));
+	pw.flush();
+    }
+
+    /**
+     * Call write_rt0 on a FileWriter derived from f.
+     * @param f the File to write to
+     * @param useKeyIDs a boolean, true to print key IDs not mnemonics
+     * @throws IOException if there is a problem writing the file.
+     */
+    public void write_rt0(File f, boolean useKeyIDs) throws IOException {
+	write_rt0(new FileWriter(f), useKeyIDs);
+    }
+
+    /**
+     * Equivalent to write_rt0(w, false);
+     * @param w a Writer to print on
+     */
+    public void write_rt0(Writer w) { write_rt0(w, false); }
+
+    /**
+     * Equivalent to write_rt0(f, false);
+     * @param f the File to write to
+     * @throws IOException if there is a problem writing the file.
+     */
+    public void write_rt0(File f) throws IOException {
+	write_rt0(new FileWriter(f), false);
+    }
+
+    /**
      * Get to the SHA1 hash of the key.  Used by Roles and Identities to get a
      * key ID.
