OCaml CLI and library to the Karakeep bookmarking app

promote metadata

+184 -58
+1 -1
.ocamlformat
··· 1 - version=0.27.0 1 + version=0.28.1
+53
.tangled/workflows/build.yml
··· 1 + when: 2 + - event: ["push", "pull_request"] 3 + branch: ["main"] 4 + 5 + engine: nixery 6 + 7 + dependencies: 8 + nixpkgs: 9 + - shell 10 + - stdenv 11 + - findutils 12 + - binutils 13 + - libunwind 14 + - ncurses 15 + - opam 16 + - git 17 + - gawk 18 + - gnupatch 19 + - gnum4 20 + - gnumake 21 + - gnutar 22 + - gnused 23 + - gnugrep 24 + - diffutils 25 + - gzip 26 + - bzip2 27 + - gcc 28 + - ocaml 29 + - pkg-config 30 + 31 + steps: 32 + - name: opam 33 + command: | 34 + opam init --disable-sandboxing -a -y 35 + - name: repo 36 + command: | 37 + opam repo add aoah https://tangled.org/anil.recoil.org/aoah-opam-repo.git 38 + - name: switch 39 + command: | 40 + opam install . --confirm-level=unsafe-yes --deps-only 41 + - name: build 42 + command: | 43 + opam exec -- dune build -p karakeep 44 + - name: switch-test 45 + command: | 46 + opam install . --confirm-level=unsafe-yes --deps-only --with-test 47 + - name: test 48 + command: | 49 + opam exec -- dune runtest --verbose 50 + - name: doc 51 + command: | 52 + opam install -y odoc 53 + opam exec -- dune build @doc
+15
LICENSE.md
··· 1 + ISC License 2 + 3 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org> 4 + 5 + Permission to use, copy, modify, and distribute this software for any 6 + purpose with or without fee is hereby granted, provided that the above 7 + copyright notice and this permission notice appear in all copies. 8 + 9 + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+56 -36
README.md
··· 1 1 # OCaml Karakeep API Client 2 2 3 - This library provides OCaml bindings to the Karakeep API for bookmark management. 3 + An OCaml client library for the [Karakeep](https://karakeep.app) bookmark service API. 4 + Built on [Eio](https://github.com/ocaml-multicore/eio) for structured concurrency with 5 + a type-safe interface using [jsont](https://erratique.ch/software/jsont) for JSON encoding/decoding. 4 6 5 7 ## Features 6 8 7 - - Fetch bookmarks from Karakeep instances with pagination 8 - - Retrieve detailed bookmark information 9 - - Create new bookmarks 10 - - Access and download bookmark assets 11 - - Filter bookmarks by tags 9 + - Full API coverage for bookmarks, tags, lists, highlights, and user operations 10 + - Automatic pagination support 11 + - Type-safe JSON encoding/decoding with jsont 12 + - Built on Eio for structured concurrency 13 + - Cmdliner integration for CLI tools 12 14 13 15 ## Installation 14 - 15 - To install the library, you can use opam: 16 16 17 17 ```bash 18 18 opam install karakeep ··· 21 21 Or pin the development version: 22 22 23 23 ```bash 24 - opam pin add karakeep.dev git+https://github.com/yourusername/ocaml-karakeep.git 24 + opam pin add karakeep.dev git+https://tangled.org/@anil.recoil.org/ocaml-karakeep.git 25 25 ``` 26 26 27 27 ## Configuration 28 28 29 - The library requires an API key for authentication. You can obtain an API key from your Karakeep instance. 29 + The library requires an API key for authentication. You can obtain an API key from your Karakeep instance settings. 30 30 31 31 ## Usage Example 32 32 33 33 ```ocaml 34 - open Lwt.Infix 35 - open Karakeep 34 + let () = 35 + Eio_main.run @@ fun env -> 36 + Eio.Switch.run @@ fun sw -> 36 37 37 - (* Setup the Karakeep client *) 38 - let api_key = "your_api_key" 39 - let base_url = "https://hoard.recoil.org" 38 + (* Create the client *) 39 + let client = 40 + Karakeep.create ~sw ~env 41 + ~base_url:"https://hoard.recoil.org" 42 + ~api_key:"your_api_key" 43 + in 40 44 41 - (* Fetch recent bookmarks *) 42 - let fetch_recent_bookmarks () = 43 - fetch_bookmarks ~api_key ~limit:10 base_url >>= fun response -> 44 - 45 - (* Process bookmarks *) 45 + (* Fetch recent bookmarks *) 46 + let result = Karakeep.fetch_bookmarks client ~limit:10 () in 46 47 List.iter (fun bookmark -> 47 - let title = match bookmark.title with 48 - | Some t -> t 49 - | None -> "(No title)" 50 - in 51 - Printf.printf "- %s\n URL: %s\n\n" title bookmark.url 52 - ) response.data; 53 - 54 - Lwt.return_unit 48 + let title = Karakeep.bookmark_title bookmark in 49 + Printf.printf "- %s\n" title 50 + ) result.bookmarks; 51 + 52 + (* Fetch all bookmarks (handles pagination automatically) *) 53 + let all_bookmarks = Karakeep.fetch_all_bookmarks client () in 54 + Printf.printf "Total bookmarks: %d\n" (List.length all_bookmarks); 55 + 56 + (* Create a new bookmark *) 57 + let _new_bookmark = 58 + Karakeep.create_bookmark client 59 + ~url:"https://ocaml.org" 60 + ~title:"OCaml Programming Language" 61 + ~tags:["programming"; "ocaml"] 62 + () 63 + in 55 64 56 - (* Run the function *) 57 - let () = Lwt_main.run (fetch_recent_bookmarks ()) 65 + (* Search bookmarks *) 66 + let search_results = Karakeep.search_bookmarks client ~query:"ocaml" () in 67 + Printf.printf "Found %d results\n" (List.length search_results.bookmarks) 68 + ``` 69 + 70 + ## Error Handling 71 + 72 + All operations may raise `Eio.Io` exceptions with a `Karakeep.E` error payload: 73 + 74 + ```ocaml 75 + try 76 + let bookmarks = Karakeep.fetch_bookmarks client () in 77 + (* ... *) 78 + with 79 + | Eio.Io (Karakeep.E err, _) -> 80 + Printf.eprintf "Karakeep error: %s\n" (Karakeep.error_to_string err) 58 81 ``` 59 82 60 83 ## Documentation 61 84 62 - See the [documentation](doc/index.md) for more detailed usage instructions and API reference. 85 + - [API Documentation](doc/index.md) 86 + - Online documentation is generated with `dune build @doc` 63 87 64 88 ## License 65 89 66 - This library is licensed under the ISC license. 67 - 68 - ## Contact 69 - 70 - For issues and questions, please create an issue on the GitHub repository. 90 + ISC License. See [LICENSE.md](LICENSE.md) for details.
+5
dune
··· 1 + ; Root dune file 2 + 3 + ; Ignore directories that shouldn't be processed by dune 4 + 5 + (data_only_dirs karakeep-src third_party)
+2 -1
dune-project
··· 1 - (lang dune 3.17) 1 + (lang dune 3.18) 2 2 (name karakeep) 3 3 4 4 (license ISC) ··· 8 8 (bug_reports "https://tangled.org/@anil.recoil.org/ocaml-karakeep/issues") 9 9 10 10 (generate_opam_files true) 11 + (maintenance_intent "(latest)") 11 12 12 13 (package 13 14 (name karakeep)
+2 -1
karakeep.opam
··· 12 12 homepage: "https://tangled.org/@anil.recoil.org/ocaml-karakeep" 13 13 bug-reports: "https://tangled.org/@anil.recoil.org/ocaml-karakeep/issues" 14 14 depends: [ 15 - "dune" {>= "3.17"} 15 + "dune" {>= "3.18"} 16 16 "ocaml" {>= "5.2.0"} 17 17 "requests" {>= "0.0.1"} 18 18 "eio" {>= "1.2"} ··· 40 40 "@doc" {with-doc} 41 41 ] 42 42 ] 43 + x-maintenance-intent: ["(latest)"]
+5
lib/cmd/karakeep_cmd.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 open Cmdliner 2 7 3 8 type config = {
+5
lib/cmd/karakeep_cmd.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Karakeep CLI support library 2 7 3 8 This module provides cmdliner terms and utilities for building command-line
+5
lib/karakeep.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Karakeep API client implementation *) 2 7 3 8 include Karakeep_proto
+5
lib/karakeep.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Karakeep API client 2 7 3 8 This module provides a client for interacting with the Karakeep bookmark
+5
lib/proto/karakeep_proto.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Karakeep API protocol types and JSON codecs *) 2 7 3 8 (** {1 Helper Codecs} *)
+5
lib/proto/karakeep_proto.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Karakeep API protocol types and JSON codecs 2 7 3 8 This module provides type definitions and jsont codecs for the Karakeep
-19
run_tests.sh
··· 1 - #!/bin/bash 2 - set -e 3 - 4 - echo "Building project..." 5 - opam exec -- dune build --display=quiet 6 - 7 - echo -e "\n=== Running fetch bookmarks test ===\n" 8 - opam exec -- dune exec test/test.exe 9 - 10 - echo -e "\n=== Running create bookmark test ===\n" 11 - opam exec -- dune exec test/create_test.exe 12 - 13 - echo -e "\n=== Running asset test ===\n" 14 - opam exec -- dune exec test/asset_test.exe 15 - 16 - echo -e "\n=== Running search bookmarks test ===\n" 17 - opam exec -- dune exec test/search_test.exe 18 - 19 - echo -e "\nAll tests passed!"
+5
test/asset_test.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 open Karakeep 2 7 3 8 let () =
+5
test/create_test.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 open Karakeep 2 7 3 8 let () =
+5
test/search_test.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 open Karakeep 2 7 3 8 let print_bookmark bookmark =
+5
test/test.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 open Karakeep 2 7 3 8 let print_bookmark bookmark =