Loam is free and open source for macOS. Your notes stay plain Markdown files on your disk. Download for macOS.[Download for macOS.]
All pages

Plugins

Build your first plugin

.md

Create, build, test and enable a small plugin with the loam command line, then run its command.

This page builds a plugin called word-count. It adds one command, word-count.hello, and uses the four loam plugin commands you need for every plugin: new, build, test and enable. The output blocks are what loam printed for this plugin. The examples use --vault ~/Notes; you can leave it out when you run from inside the vault.

Before you start

  • Swift 6.2 on your PATH. Xcode or the Command Line Tools provide it, and Loam builds plugins with it.
  • The loam command on your PATH. The install command links it into ~/.local/bin. Otherwise, Settings > Developers in the app puts it on your PATH.
  • A network connection for the first build. It downloads the SDK's dependencies, such as swift-markdown and Yams, from GitHub.

Create, build and test

  1. Create the package: loam --vault ~/Notes plugin new word-count.
  2. Open .loam/plugins/word-count/Sources/WordCount/WordCountPlugin.swift. The command is already there. Change its text if you want.
  3. Build it: loam --vault ~/Notes plugin build word-count. Wait for "ok" : true. The first build takes a few minutes.
  4. Test it: loam --vault ~/Notes plugin test word-count. Wait for "ok" : true.

plugin new writes this package, relative to your vault:

.loam/plugins/word-count/
  plugin.json
  Package.swift
  Sources/WordCount/WordCountPlugin.swift
  Tests/WordCountTests/WordCountPluginTests.swift
  README.md
  .gitignore

It prints the new id and its folder:

{
  "id" : "word-count",
  "path" : "/Users/you/Notes/.loam/plugins/word-count"
}

The generated command is in WordCountPlugin.swift. Its summary is what agents read:

Sources/WordCount/WordCountPlugin.swift

public func activate(context: PluginContext) throws {
    let vault = context.vault
    try context.registerCommand(Command(
        id: "word-count.hello",
        title: "Word Count: say hello",
        summary: "Says hello and how many notes the vault has. No arguments; optional: name."
    ) { arguments in
        let notes = try vault.markdownPaths().count
        return "Hello \(arguments["name"] ?? "from Word Count"). Notes in this vault: \(notes)."
    })
}

Build prints ok and the library it compiled. Its log holds the Swift build output, shortened here:

{
  "id" : "word-count",
  "library" : "/Users/you/Notes/.loam/cache/plugins/word-count/libWordCountPlugin.dylib",
  "log" : "<the Swift build output>",
  "ok" : true
}

Enable and run it

  1. Check the permissions. The template sets "permissions": ["vault.read"] in plugin.json, because this command reads your notes. Keep it unless you remove the command.
  2. Enable the plugin: loam --vault ~/Notes plugin enable word-count.
  3. Run the command: loam --vault ~/Notes word-count.hello name=Ada.

plugin enable prints what started:

{
  "activated" : [
    "word-count"
  ],
  "active" : true,
  "enabled" : "word-count"
}

The command prints one line. The count is 0 in this example because the test vault is empty:

Hello Ada. Notes in this vault: 0.

Next steps

Read Anatomy of a plugin for each file in the package, then Plugin commands to add more. Before you share the plugin, read Share and install plugins.

For AI agents: loam guide plugins has these steps with the rules that loam plugin build checks.