Index: /trunk/cli/dune
===================================================================
--- /trunk/cli/dune	(revision 30)
+++ /trunk/cli/dune	(revision 31)
@@ -2,4 +2,5 @@
  (name txt)
  (public_name txt)
- (modules txt authors convert conversion edit file index last listing new topics html atom gemini publish pull read recent)
+ (modules txt authors convert conversion edit file index last listing
+ 	new topics html atom gemini peers publish pull read recent)
  (libraries text_parse.converter text_parse.parsers logarion msgpck curl str cmdliner))
Index: /trunk/cli/peers.ml
===================================================================
--- /trunk/cli/peers.ml	(revision 31)
+++ /trunk/cli/peers.ml	(revision 31)
@@ -0,0 +1,37 @@
+let print_peers_of_peer p =
+	let open Logarion.Header_pack in
+	match Msgpck.to_list p.peers with [] -> ()
+	| ps -> print_endline @@
+		List.fold_left (fun a x -> Printf.sprintf "%s %s" a (Msgpck.to_string x)) "peers: " ps
+
+type filter_t = { authors: Logarion.Person.Set.t; topics: Logarion.String_set.t }
+
+let print_peer () peer =
+	let open Logarion.Peers in
+	Printf.printf "%s" peer.path;
+	List.iter (Printf.printf "\t%s\n") peer.locations
+
+let remove_repo id =
+	let repopath = Filename.concat Logarion.Peers.text_dir id in
+	match Sys.is_directory repopath with
+	| false -> Printf.eprintf "No repository %s in %s" id Logarion.Peers.text_dir
+	| true ->
+		let cmd = Printf.sprintf "rm -r %s" repopath in
+		Printf.printf "Run: %s ? (y/N) %!" cmd;
+		match input_char stdin with
+		|'y'-> if Sys.command cmd = 0 then print_endline "Removed" else prerr_endline "Failed"
+		| _ -> ()
+
+let peers = function
+	| Some id -> remove_repo id
+	| None ->
+		Printf.printf "Peers in %s\n" Logarion.Peers.text_dir;
+		Logarion.Peers.fold print_peer ()
+
+open Cmdliner
+let term =
+	let remove = Arg.(value & opt (some string) None & info ["remove"]
+		~docv:"repository ID" ~doc:"remove repository texts & from future pulling") in
+	Term.(const peers $ remove),
+		Term.info "peers" ~doc:"list current peers" ~man:[ `S "DESCRIPTION";
+			`P "Lists current peers and associated information"]
Index: /trunk/cli/pull.ml
===================================================================
--- /trunk/cli/pull.ml	(revision 30)
+++ /trunk/cli/pull.ml	(revision 31)
@@ -87,6 +87,6 @@
 		then pull_text url dir id
 
+(*TODO: integrate in lib*)
 let validate_id_length s = String.length s <= 32
-
 let validate_id_chars s = try
 	String.iter (function 'a'..'z'|'A'..'Z'|'0'..'9'-> () | _ -> raise (Invalid_argument "")) s;
@@ -95,5 +95,5 @@
 
 let pull_index url authors_opt topics_opt =
-	let index_url = url ^ "/index.pck" in
+	let index_url = Filename.concat url "index.pck" in
 	match curl_pull index_url with
 	| Error s -> prerr_endline s; false
@@ -128,5 +128,9 @@
 	let pull got_one peer_url = if got_one then got_one else
 		(pull_index peer_url auths topics) in
-	Logarion.Peers.fold pull false;
+	let fold_locations init peer =
+		ignore @@ List.fold_left pull init peer.Logarion.Peers.locations;
+		false
+	in
+	ignore @@ Logarion.Peers.fold fold_locations false;
 	Curl.global_cleanup ()
 
Index: /trunk/cli/txt.ml
===================================================================
--- /trunk/cli/txt.ml	(revision 30)
+++ /trunk/cli/txt.ml	(revision 31)
@@ -16,4 +16,5 @@
 	Listing.term;
 	New.term;
+	Peers.term;
 	Publish.term;
 	Pull.term;
Index: /trunk/lib/peers.ml
===================================================================
--- /trunk/lib/peers.ml	(revision 30)
+++ /trunk/lib/peers.ml	(revision 31)
@@ -1,15 +1,21 @@
 let text_dir = Filename.concat (File_store.txtdir ()) "peers"
 
+type t = { path: string; locations: string list }
+
 let fold fn init = match Sys.readdir text_dir with
-	| exception (Sys_error msg) -> prerr_endline msg
+	| exception (Sys_error msg) -> prerr_endline msg; init
 	| dirs ->
-		let read_pack path =
-			let pack_path = Filename.(concat text_dir @@ concat path "index.pck") in
-			match Sys.file_exists pack_path with false -> () | true ->
-				match Header_pack.of_string (File_store.to_string pack_path) with
-				| Error s -> Printf.eprintf "%s %s\n" s pack_path
-				| Ok p -> ignore @@ List.fold_left fn init Header_pack.(p.info.locations)
+		let read_pack init path =
+			let fullpath = Filename.concat text_dir path in
+			if Sys.is_directory fullpath then begin
+			let pack_path = Filename.concat fullpath "index.pck" in
+			match Sys.file_exists pack_path with
+			| false -> Printf.eprintf "Missing index.pck for %s\n" path; init
+			| true -> match Header_pack.of_string (File_store.to_string pack_path) with
+				| Error s -> Printf.eprintf "%s %s\n" s pack_path; init
+				| Ok p -> fn init { path; locations = Header_pack.(p.info.locations) }
+			end else init
 		in
-		Array.iter read_pack dirs
+		Array.fold_left read_pack init dirs
 
 let scheme url =
