Joplin-butler: my WIP command line interface for WebClipper API

Hey guys, I'm one of the friendly /r/joplinapp mods (hugelung). I've spent the last 3 days creating a brand new cli tool for Joplin in Go. It doesn't cover the whole API yet, but the foundation is pretty solid, and I figured I'd start talking about it + see what advice y'all have for me

The motivation is that while Joplin provides a really cool terminal application, this application is usually out of date with the Joplin Desktop/Mobile apps (i.e. using an older database format), and requires a full sync in order to use. This is a pretty bad experience when you just want to automate a few things using a terminal script — causing a bunch of waiting for sync to happen + using twice as much data on your computer

Meanwhile, Joplin provides a "data api" which is a REST server running on localhost. This is how the Joplin Webclipper communicates with the active Joplin Desktop session, and this API is super cool. You can do almost everything that is possible in plugins / full sync, and everything feels realtime. You make a note, and it's instantly in your Desktop app. As a bonus, this library can be used in Go programs instead of via the command line

Some of what the tool is currently capable of:

  • Authenticate to Joplin desktop using a popup message that the desktop app makes. No hassling with API keys
  • Configuration (and api keys) are automatically saved to ~/.joplin-butler/config.json
  • Rough implementation of search for objects + handling the data pagination automatically
  • joplin-butler get allows you to inspect all Joplin objects, like tags, resources, notes, folders
  • joplin-butler create allows you to make most of these objects, but mostly just notes with title/body
  • joplin-butler delete allows you to delete objects

A small example:

Create a note with title and markdown body:

> joplin-butler create note "My CLI Joplin Dream" -body "Begins today :D"

ID: 50fe5cf5dc6f4070a11c869cd4ec0138
Title: My CLI Joplin dream
ParentID: 1d4c4899bc7d4df4ad45cd575ac30043
CreatedTime: 1681088397617
UpdatedTime: 1681088397617
Source: joplin-desktop
Begins today :D

Delete a note:

> joplin-butler delete note/50fe5cf5dc6f4070a11c869cd4ec0138

Successfully deleted notes/50fe5cf5dc6f4070a11c869cd4ec0138

There's a fair bit remaining to do:

  • Attaching/removing objects to other objects, like a tag to a note, or a resource to a note
  • Allowing customization of which metadata is retrieved and displayed
  • Editing object data selectively using the PUT api

CLI design mentality:

  • Implemented similar to the verbs used by kubectl for controlling kubernetes resources
  • Fully generic concepts about manipulating database objects, preferring "create note " rather than "mknote" like Joplin terminal does it
  • Structured data outputs so you can easily use unix tools to manipulate the data
  • I can ultimately support the verbs that Joplin terminal does later, just for the convenience of being able to use the same ones, but I consider this low priority

Joplin Butler Update:

Do stuff like this:

> joplin-butler create resource ~/Downloads/Big\ airship/NE/still/still\ only0003.png

ID: b8a8f3b5249943ca95aa0571bd905766
Title: still only0003.png
CreatedTime: 1681174988187
UpdatedTime: 1681174988187
UserCreatedTime: 1681174988187
UserUpdatedTime: 1681174988187
Size: 1068527
IsShared: 0

> joplin-butler get folders

269afae798c445fda34a2817cb0a96ea AE Misc
4216484946714902922c15b075d39e28 Frequent
dc80329d7b694117850e21556d59ddc7 Huge Lung
029466b3d52f4cf2bf3aaab11ade8e40 Ideas
a95cab228a9d4f118d4ad2c0a1b1adc5 Travel

> joplin-butler create note 'My CLI Joplin Dream' \
    -body 'Begins today :D\n\n ![airship](:/b8a8f3b5249943ca95aa0571bd905766)' \
    -parent '269afae798c445fda34a2817cb0a96ea'

ID: acd2cc52a6444e42a163fcefe94464d7
Title: My CLI Joplin Dream
ParentID: 1d4c4899bc7d4df4ad45cd575ac30043
CreatedTime: 1681175174105
UpdatedTime: 1681175174105
Source: joplin-desktop
Begins today :D


The above code created the following note in Joplin Desktop instantly:


Thanks for releasing this project.

I'm new to Go programming language. I checked out your Github project but wasn't sure how to get the joplin-butler command. So for those wondering:

From the project folder, type:

$ export GO111MODULE=on      # Important, otherwise the joplin-butler command will throw errors!
$ go build

Run it:

$ ./joplin-butler get folders

Yeah, thanks, good point! — and please let me know if you have some workflows or features that you'd be interested in taking on. There's still a fair bit that's missing, like assigning tags and being able to refer to folders / tags by name instead of their hash. I'm also interested in the idea of doing a JoplinFS filesystem on the basis of this lib, which would enable you to interact with Joplin as if it's just files on a disk