Mami: cross-tool document converter

I created this tool and tried to support obsidian, just wanted to make a statement here!


Mami is a conversion tool that can connect different markdown-based frameworks and tools, and can convert the data of one tool to another tool, which is very helpful for cross-application migration and multi-platform release, currently known joplin/obsidian/hexo/hugo/raw, plans to support docsify/vuepress.

Some practical use cases are to export a portion of obsidian notes as a note or wiki instead of manually copying to a specific location. And directly use the existing framework, you can publish it to github pages and other places for online access.



  • you need to install nodejs 18

Step 1: Create a new project

The following uses pnpm as the package manager, but you can replace it with npm

Create a hexo project

pnpx hexo init obsidian2hexo-demo && cd mami-starter

Step 2: Install mami

Add @mami/cli and typescript as development dependencies of the project

pnpm i -D @mami/cli typescript

Add some scripts to package.json

  "scripts": {
    "gen": "mami"

Create your config file mami.config.ts

import { defineConfig } from '@mami/cli'

export default defineConfig({
  input: [],
  output: [],

then run

$ pnpm run gen

> [email protected] gen
> mami


Well, nothing happens because you have no input or output plugin defined. Continue to the next step.

Step 3: Install the required plugins

Install the required plug-ins to connect the required tools. Here we use joplin => obsidian as an example

pnpm i -D @mami/plugin-obsidian @mami/plugin-hexo

Modify your config file mami.config.ts

import { defineConfig } from '@mami/cli'
import * as obsidian from '@mami/plugin-obsidian'
import * as hexo from '@mami/plugin-hexo'
import path from 'path'

export default defineConfig({
  input: [obsidian.input({ root: path.resolve(__dirname, './obsidian-source') })],
  output: [hexo.output({ root: __dirname })],

Step 4: Perform the conversion

Then you can rerun the following command

pnpm run gen

Now you will see the converted obsidian file in _source/post and source/resources

Then, start the hexo local server

pnpm hexo server

you got a website



API Documentation

Roughly speaking, plugins are divided into input and output plugins. The input plugin will return an AsyncGenerator, while the output plugin will return an AsyncGenerator will consume it in the handle hook function.


Intermediate format

  "id": "0e2510c9272449dbafe3e0f3fba12d74",
  "title": "Welcome to Joplin!",
  "content": "content body",
  "createAt": 1666288266591,
  "updateAt": 1666288266591,
  "path": ["Welcome! (Desktop)"],
  "tags": [
      "id": "04dfa5cf19e4435f9f3f09a73a7edfb2",
      "title": "blog"
  "resources": [
      "id": "63b83e548b7b4adfae18544b7038b0bc",
      "title": "AllClients.png",
      "raw": "<nodejs buffer>"

Writing plugins involves some markdown ast operations. For example, you may need to convert links in markdown. It is recommended to use mdast to handle it.


PS: The origin of the name mami is [Mami Tomoe] in Puella Magi Madoka Magica (Mami Tomoe - Wikipedia), her magic is a ribbon that can connect various things , and can even form a musket (:

The website, online examples and api documentation are online, and a visual client is currently being developed, which may eventually be packaged as a binary application using electron

vitepress/vuepress support

1 Like


1 Like