エンジニアのためのメモ管理CLIツールnbの使い方
メモ管理に特化したCLIツール「nb」を紹介します。

nbとは
nbはローカルでメモやタスク管理ができるCLIです。あくまでも管理に特化したCLIです。編集は各々の愛しているテキストエディタでできます。
メモ管理難しすぎ問題
たとえば自力でメモを管理しようとすると次のような方法が考えられます。
- ファイル名を日本語タイトルにする(
プラグインの作り方.md) - ファイル名を英語タイトルにする(
how-to-plugin.md) - ファイル名を日時にする(
202501071032.md)
ファイル名をタイトルにすると、後からタイトルを変えたくなった時に少々面倒です。また、そもそもメモを取り始める時点ではタイトルが決まっていないこともしばしばあります。
その対策でファイル名を日時にすると、ファイルの中身が分かりづらいです。そしてファイルを開くときにファイル名の入力が面倒です。
他にも「タグを付けたい」「検索したい」「よく開くノートをスピーディーに開けるようにしたい」などさまざまな願望が生まれることでしょう。
nbならこれら問題を解決できます。
nbのしくみとメリット
nbでは、次のいずれかをタイトルとして扱います。
- ファイルの最初のh1
- フロントマターの
title - 上記のどちらでも無ければ本文1行目
# ここがタイトルになるここに素敵な本文を書いていく……---title: ここがタイトルになる---ここに素敵な本文を書いていく……今日から俺がタイトルに!?このしくみによって後から柔軟にタイトルを付けられます。より早くメモが始められますね。
これらのタイトルはノートの一覧や検索で表示されます。

画像の例ではノートの一覧を表示しています。先頭にある[1]のような番号が各ノートのIDです。
ファイル名とID
nbはファイル名が日時になっています。たとえば20241227173232.mdのような感じです。もちろん任意の名前を付けることもできます(例:idea.md)。
ただファイル名が日時だと入力が面倒です。そこで、nbではノートの一つひとつにIDが割り振られます。このしくみによってあらゆる操作のタイプ数が減ります。
たとえば、普通はvim 20250107113431.mdのようにファイル名を指定して開きます。
nbを使えばnb e 11のようにファイル名の代わりにIDを指定することで、あらかめ設定したテキストエディタで編集できます。
vim 20250107113431.md # 長い……nb e 11 # 短い!編集後にはシェルにタイトルが表示され、中身が分かりやすいです。

各ノートとIDの対応は、ノートの一覧や検索でも表示されます(後述)。
Git管理も楽々
実態はただのテキストファイルですのでGit管理も楽です。git add・commit・pushなどはnb側が自動でやってくれます。
インストール方法
nbはbashとGitを実行できる環境が必要です。bashは単純に実行ができればよいので、ログインシェルはZshやfishなどでも大丈夫です。
さまざまな環境でインストールできます。公式ドキュメントのInstallationを見て各OSに合った方法でインストールしましょう。
たとえばHomebrewが使える環境であれば次のコマンドでインストールします。
brew install xwmx/taps/nbセットアップ
nbを実行してウェルカム画面やヘルプが出れば完了です。
nb
テキストエディタの設定
nb set editorを実行し、ノートの編集で使うテキストエディタを設定します。
nb set editor nvimあるいは環境変数$EDITORを設定します。
ノートはどこに保存されるの?
デフォルトのノートの保存場所は~/.nb/home/です。このディレクトリがGitリポジトリになっています。
ディレクトリの変更方法やリポジトリを増やす方法は後で解説します。
ノートの基本操作
基本的な操作を紹介します。
ノートの作り方
次のいずれかのコマンドで、ノートを作成してテキストエディタで開きます。
nb add# ショートカットも用意されているnb anb +
nb aやnb +のようなショートカットも用意されており、タイプ数が減って入力が楽です。
画像のとおり、ファイル名はデフォルトだと日時になります。ファイル名を自分で決めたい場合、次のように実行します。
nb a example.mdテキストエディタを開かずにメモしたい場合、次のように文字列を渡します。
nb a "本文だけ"nb a "# タイトルだけ"公式ドキュメント:Adding
ノートの一覧表示
次のいずれかのコマンドで、ノートのリストを表示できます。
nb ls# 単純にnbだけでもリストが表示されるnb
ノートは最後に変更された順に並びます。ピン留め機能もあります(次の項目で解説)。
デフォルトだと15件まで表示されます。もっと表示させたい場合は--limit、全部表示させたいなら--allを使いましょう。
nb ls --limit 20nb ls --all--limitのデフォルト値を変えたい場合はnb set limit 20のように設定できます。
公式ドキュメント:Listing & Filtering
ピン留め
リストの上位にピン留めしたいノートがあれば、次のコマンドでピン留めしましょう。
# IDが1のノートをピン留めnb pin 1ピン留めが不要になったらunpinを実行します。
# IDが1のノートをピン留めから外すnb unpin 1公式ドキュメント:Pinning
ノートの編集
次のいずれかのコマンドで、ノートをテキストエディタで編集できます。
# IDが3のノートを開くnb edit 3# ショートカットも用意されているnb e 3ファイル名でも開けます。
nb e idea.mdnb e 20241227173232.md--contentを使えばテキストエディタを開かずに追記できます。
nb e 3 --content "追記できる"nb e 3 --c "短いオプションも用意されている"公式ドキュメント:Editing
ノートの検索
次のようにしてノートを検索できます。
nb search "テスト"# ショートカットも用意されているnb q "テスト"qはクエリのqで覚えやすいです。

AND検索・OR検索もできます。
# AND検索nb q "example" --and "demo"nb q "example" "demo"
# OR検索nb q "example" --or "sample"nb q "example|sample"正規表現も使えるようです。内部ではgit grepが使われていますが、rg、agなどにも対応しています。
公式ドキュメント:Search
ノートの削除
次のようなコマンドでノートを削除できます。
nb delete 3nb d 3nb d idea.md公式ドキュメント:Deleting
ノートの表示
nb e 5のようにテキストエディタで開けばノートを表示できますが、nb内でも表示用のコマンドがあります。
# nb内で開くnb show 5nb s 5# w3mで開くnb browse 5# ブラウザで開く(後述)nb browse 5 --gui筆者はすぐに編集したくなるため、nb eを使っています。
タスク機能
ノートの中にあるチェックボックスの一覧を表示するには、次のようなコマンドが使えます。
nb tasks 7 # タスク一覧nb tasks open 7 # 未完了のタスク一覧nb tasks closed 7 # 完了したタスク一覧# IDなしだとすべてのノートが対象nb tasksnb tasks opennb tasks closedタスクはインデント付きで表示されます。

[8 4]のような行頭の番号はタスク操作用のセレクタです。たとえばnb do 8 4を実行するとそのチェックボックスにチェックが付きます。つまりテキストエディタを開かずに編集できます。
nb do 8 4
逆にチェックを外すにはnb undo 8 4のように実行します。
nb undo 8 4公式ドキュメント:Tasks
TODOノート
nb todoという別の機能もあります。nb todoはノートそのものを1つのタスクとして扱います。
nb todo add "シークレット任務" --due "2025-01-11"
ファイル名は20250107150223.todo.mdのような形式で、中身は次のようになります。
# [ ] シークレット任務
## Due
2025-01-11TODOが完了したらnb do 6、未完了に戻すならnb undo 6のように実行します。
TODOノートの一覧を表示するにはnb todosを実行します。
nb todos # TOODノートの一覧nb todos open # 未完了のTODOノート一覧nb todos closed # 完了したTODOノート一覧筆者はtasks(チェックボックス)の方で事足りているため、TODOノートの方はまだ使いこなせていません。嘘です。この記事を書くときに初めて知りました。
サブタスク・詳細の入力などもできるようです。
公式ドキュメント:Todos
タグ機能
本文中に#タグのようにハッシュタグに続けて文字を書くと、タグとして認識されます。
タグは検索で便利です。
nb --tags タグ1nb q --tags タグ1 # ヒット箇所も表示
公式ドキュメント:Tagging
画像の扱い
生きていればメモと一緒に画像を管理したいときがやってきます。
nb importで任意のファイルを管理下に加えられます。
nb import ~/Downloads/foo.pngnb import https://raw.githubusercontent.com/xwmx/nb/master/docs/images/nb.pngimportしたファイルにもIDが割り振られます。
nb openを使えばGUIのアプリケーションで開けます。
nb open 18# ファイル名でもOKnb open foo.pngブラウザでプレビュー
先ほど少し紹介したのですが、nb browseにオプション--guiを加えるとブラウザでプレビューできます。
nb browse 4 --gui# オプションが前でもOKnb browse --gui 4
画像が表示できるほか、ノートのリンクを書いていればリンク化され、押せば遷移できます。
ブックマーク(Markdown化)
筆者は使っていませんが、指定したサイトをMarkdownファイル化してくれるブックマークという機能もあります。
気になる人は次のコマンドを実行してみましょう。
nb https://example.com公式ドキュメント:Bookmarks
ファイル名の変更
ファイル名はnb moveで変更できます。
nb move bar.md buz.md# IDでも指定できるnb move 2 "new-filename" # new-filename.mdになる# ショートカットがあるnb mv bar.md buz.md# エイリアスもあるnb rename bar.md buz.mdここでもう一度一覧を見てみる
nb lsではMarkdownファイル以外も表示されます。

画像・ブックマーク・TODOなどはアイコン付きで表示されます。
GitHubで管理する方法
git add・commit・pushなどはnbが自動でやってくれます。
リモートリポジトリを設定するには次のようなコマンドを叩きます。
nb remote set git@github.com:example/example.git「別のPCでも同じリポジトリを使ってメモしたい」というときも同じコマンドが使えます。

画像の例では別のPCで同期済みのリポジトリをセットしています。
git pushは自動ですが、git pullは自動ではありません。次のコマンドで同期させましょう。
nb syncリポジトリやディレクトリを分ける方法
「仕事用」「プライベート用」など複数のリポジトリに分けて管理したい場合、「ノートブック」を作ってあげます。
前述の~/.nb/home/はhomeという名前のノートブックです。
次のようにしてノートブックを追加できます。
nb notebooks add exampleノートブックの切り替え方法
新しく作ったノートブックのノートを扱うには3つの切り替え方法があります。
ディレクトリを移動することで切り替える
ノートブックのディレクトリに移動することで切り替えます。
nb add # homeのnotebookにノートが追加されるcd ~/.nb/example/nb add # exampleのnotebookにノートが追加されるprefixで都度切り替える
次のようにコマンド名・ID・ファイル名の前にnotebook名をつけてあげます。どのディレクトリにいても大丈夫です。
nb example:addnb example:e 12nb e example:12nb example:todos.md deleteuseコマンドで切り替える
nb use exampleを実行する方法です。どのディレクトリにいても大丈夫です。
nb add # homeのnotebookにノートが追加されるnb use examplenb add # exampleのnotebookにノートが追加されるhome以外のノートブックをクローンする
home以外のノートブックをGitHubからクローンして作成したい場合、次のように実行します。
nb notebooks add example git@github.com:example/example.git main~/.nb以外に保存したい
そもそも~/.nb以外に保存したい場合はnb set nb_dirで設定します。
カスタマイズ
筆者のカスタマイズ例を紹介します。
すぐに入力できるZshのキーバインド
最新の15件を表示後、コマンドラインにnb eが入力されるキーバインドを設定しています。
function nbe() { nb ls zle reset-prompt BUFFER="nb e " zle end-of-line}
zle -N nbebindkey "^X^X" nbeCTRL+Xを2回入力すると発動します。
ちなみにfzfを使った検索も考えたのですが、全文取得・ID取得などに時間がかかって効率的ではなかったため止めました。
上記のキーバインドで表示されなければnb qを使って検索、というフローに落ち着いています。
よく開くノートへのエイリアス
よく開くノートはエイリアスを設定しています。
alias idea='nb e idea.md'Neovimでのカスタマイズ
nbを導入するにあたってNeovimでカスタマイズしたところを紹介します。
bufferlineでノートタイトルを表示
bufferline.nvimで通常だとファイル名が表示されますが、nbのリポジトリであればノートタイトルを表示するように変更しました。

やっていることは単純で、「最初の行がh1ならその内容を表示」としています。
require("bufferline").setup({ options = { name_formatter = function(buf) if buf.path:match("%.nb/home/.*.md") then local file = io.open(buf.path, "r") if not file then return end local first_line = file:read("*l") file:close() local heading = first_line:match("^#%s+(.+)")
if heading then return heading end end end, },})見出し付きwikilinkの挿入とジャンプ
[[test.md##この見出しにジャンプしたい|タイトル]]のような見出し付きwikilinkを扱えるようにキーマップを設定しました。
詳しくは別の記事「Neovimで見出し付きwikilinkのジャンプとリンク生成」に書いています。
全文検索後にwikilinkの挿入
telescope.nvimでLive Grep後、選択したノートへのwikilinkを挿入するキーマップです。
前述の「見出し付きwikilink」の設定をした後はこのキーマップを使っていませんが一応。
設定例(クリックで開きます)
local function insert_text_at_cursor(text) local row, col = unpack(vim.api.nvim_win_get_cursor(0)) local current_line = vim.api.nvim_get_current_line() local new_line = current_line:sub(1, col) .. text .. current_line:sub(col + 1) vim.api.nvim_set_current_line(new_line) vim.api.nvim_win_set_cursor(0, { row, col + #text })end
vim.keymap.set("n", "<Leader>fw", function() require("telescope.builtin").live_grep({ file_ignore_patterns = { ".index", ".pindex", ".git" }, attach_mappings = function(prompt_bufnr, map) map("i", "<CR>", function() local picker = action_state.get_current_picker(prompt_bufnr) if picker.manager:num_results() == 0 then actions.close(prompt_bufnr) do return end end local num_selections = #picker:get_multi_selection() if not num_selections or num_selections <= 1 then actions.add_selection(prompt_bufnr) end
actions.close(prompt_bufnr)
for _, entry in ipairs(picker:get_multi_selection()) do local filename
if entry.filename then filename = entry.filename elseif not entry.bufnr then local value = entry.value if not value then return end if type(value) == "table" then value = entry.display end
local sections = vim.split(value, ":") filename = sections[1] end if filename:match("%.md$") then local file = io.open(filename, "r")
if not file then return end local first_line = file:read("*l") file:close() -- Markdownの見出し(# 見出し)のパターンにマッチするかチェック local heading = first_line:match("^#%s+(.+)")
if heading then local wikilink = "[[" .. filename .. "|" .. heading .. "]]" insert_text_at_cursor(wikilink) end end end end) return true end, })end, { desc = "grepしてwikilinkで書く(nb用)" })Markdownを見やすくする
render-markdown.nvimを導入してMarkdownを見やすくしました。
詳しくは別の記事「render-markdown.nvimの使い方とカスタマイズ例」に書いています。
紹介しきれなかったもの
nb lsのカラーテーマの設定、アイコンの変更、プラグインの導入など紹介しきれていない機能があります。各コマンドにも紹介していないオプションが大量にあります。
公式ドキュメントが充実していますので困ったら見てみましょう。
Web検索するとき
nbだとググラビリティが低いため、次のように検索ワードを足すことをおすすめします。
- nb cli
- xwmx/nb
- nb memo tool
- nb note taking
以上、nbの紹介でした。
タイプ数が短くなるように工夫されていてめちゃくちゃ便利です。任意のテキストエディタで編集できるためすぐに手に馴染みました。
Zettelkastenとして扱えるところもうれしいポイントです。