AoAH Day 14: Debugging a Karakeep CLI against the live service / Dec 2025
With the
To start with, I use Karakeep across all my devices to bookmark things, and I'd like to be able to programmatically search through tags, for example by taking all outbound links from the blogs that I read and autosynching them with my remote service. Karakeep on the server side does some cool things like screenshot links and create local webarchives.
Unfortunately, Karakeep doesn't publish an OCaml interface. Fortunately, my new bestie Claude helped me build ocaml-karakeep without much input from me!
Approach
With a ton of pre-Christmas organising to do this weekend, I didn't have a lot of spare time. So I thought I'd use everything I've learnt so far and try to one-shot this as bravely/foolishly as possible. I setup a repo with:
- Access to all the previous libraries, including the jsonfeed to act as an 'exemplar' for using jsont, as well as requests.
- Cloned the karakeep source code which has the details of the API somewhere in the Node source. It uses something called tRPC that I'm not familiar with.
- I took a ZFS snapshot of my karakeep deployment, and gave my agent a live API key to access my node. Yes, this is the 'take the seatbelt off' moment.
And then I prompted the agent to build jsont specifications derived from the Karakeep source, and then hook this up to Requests, and then iterate using my live key to debug failures until the API spec was right.
Results
This almost worked first time! While the testcases generated worked, I also got the agent to generate a karakeep CLI command. I'd made sure that, as with

Since I didn't have time to do a full coverage test of the API, I asked the agent to exercise the functionality and do live debugging. This is where the jsont codec was incredibly useful, since it provided all the right hints to the agent to take action. Good error messages aren't just for humans any more!
A typical error, for example was:
> main.exe bookmarks summarize wqa1sc1z42xcxfwwrsxeggbl
main.exe: [ERROR] Karakeep error: JSON error: Missing members in bookmark object:
content
createdAt
id
File "-", line 1, characters 0-615:
The agent had enough data from that error message to figure things out and make the jsont codec more permissive with option types.

The library also made good use of the stateful HTTP interface from Requests, for example by modifying all the default requests to use the API key:
let create ~sw ~env ~base_url ~api_key =
let session = Requests.create ~sw env in
let session =
Requests.set_auth session (Requests.Auth.bearer ~token:api_key)
in
{ session; base_url }
The karakeep.proto subpackage has all the dedicated jsont decoders, which take care of conversion to-and-from OCaml types. I found these quite readable:
(** Type of content a bookmark can have *)
type bookmark_content_type =
| Link (** A URL to a webpage *)
| Text (** Plain text content *)
| Asset (** An attached asset (image, PDF, etc.) *)
| Unknown (** Unknown content type *)
val bookmark_content_type_jsont : bookmark_content_type Jsont.t
Reflections
The new agent trick I learnt today is the power of debugging against live services. The jsont descriptions derived from the Karakeep source code provided just enough information in error messages that the agent could fix them by trying to run the command against my live service. Luckily, nothing got deleted this time, but in the future projects like Shelter will be ever more important.
Anyway, I now have a karakeep binary and library that's working great for my search needs. Back to bookmarking Christmas presents I needed to have obtained yesterday!
