スレッドを書くローカル執筆アプリ / A local writing app for Bluesky threads
re SPEC.md
21 kB · 255 lines
Markdown
at main

Re: 仕様 #

発案:Nighthaven(@moja.blue) 初版:2026-09-14 この文書は CC BY 4.0 で提供する。写したり手を加えたりするときは、発案者の名前とこの文書の場所を示すこと。 英語版は SPEC.en.md。内容が合わないときは、この日本語版を正とする。


1. 何のためのものか #

Re: は、SNS を使わずにスレッドを書くための執筆用アプリである。300字までの投稿を、直前の投稿に返す形で後ろへ継ぎ足していく。書いたスレッドは、そのまま Bluesky にスレッドとして投稿できる。

発想のもとには「返しモデル」がある。文章の最小単位は「返し」であり、書き手は直前の文、あるいは頭の中の「欠け」に返しつづけることで文章を前へ進める、という見方である。SNS のスレッドで書くと考えが進みやすいのは、次の二つの条件がそろうからである。

  • 一つの投稿が短く、境目がはっきりしている
  • 直前の投稿にしか返せない

Re: はこの二つを、SNS の外に取り出したものである。

静かにひとりで書き連ねるだけでは、書く気が続きにくい。そこで Re: には出口として Bluesky への投稿を付けてある。書いたものを出せる先があることが、書きつづける理由になる。

2. 名前 #

名前は Re: とする。返信の印であり、このアプリの最小単位である「返し」と一致する。Re: の後ろには返す相手が要る。その相手は、直前の投稿か、頭の中の欠けである。

macOS ではファイル名の「:」がターミナルで「/」に見えるため、ファイル名やフォルダ名ではコロンを除いて Re と書く。

3. 書く単位 #

項目 決まり 理由
投稿の上限 書記素で300字。超えると投稿できない。直すときも同じ Bluesky と同じ上限にする
目安 150字を超えると字数の表示の色が変わる 作者の Bluesky のスレッド投稿461件では、150字を超えると4件に3件が空行で段落に分かれていた。空行で区切った塊は中央値43字・1文だった
並べ替え・途中への挿入 入れない 直前にしか返せないことが、スレッドで書く利点だからである。ツェッテルカステンは途中への挿入を認めるが、Re: は逆を試す
投稿のキー ⌘Enter。日本語の変換中は反応しない
スレッドの名前 最初に付けない。最初の投稿で、作った日時の名前(2026-09-14_1530)が付く。あとから画面左上の名前を押して変える 題名や問いを先に決めると、返しの向きが先に決まってしまう

4. 画面 #

4.1 書く画面 #

書く画面は1列である。本文は14.5px、1行は40字で折る。40字は、書いた量を行数で見るための幅である。

入力欄の上端は、スレッドの長さによらず画面の高さの6割に置く。スレッドは入力欄の上へ下から積むので、直前の投稿はいつも入力欄のすぐ上にある。長くなれば、入力欄より上の段の中でスクロールする。

  • 入力欄の位置が毎回同じであること、直前の投稿が入力欄のすぐ上にあること、スレッドの頭が一覧の頭と同じ高さにあることの3つは、スレッドの長さが変わるので同時には満たせない。書いているあいだずっと続く直前の投稿との距離を取り、一覧の頭にそろえるのはあきらめた
  • 入力欄を最下部に固定すると、短いスレッドで直前の投稿と入力欄が離れる。入力欄を末尾に並べて全体を送ると、送るたびに入力欄が上下する

返す先の2件、つまり二つ前の投稿と直前の投稿だけを濃い字にし、それより前は淡くする。返しの向きは、点が二つないと決まらない。直前の投稿だけでは、それに何を返すかしか見えない。二つ前の投稿もあれば、直前の投稿がどちらへ返したかが見え、次に話を進めるのか、向きを変えるのかを選べる。

帯の「全体」か ⌘E で、横に俯瞰の列を開く。俯瞰の列は13.5pxで、画面の幅に流し56字で止める。40字の幅で読むと、41〜44字の投稿の最後に1〜3字だけの行ができて読みにくいからである。画面の幅が860px以下のときは、俯瞰の列だけを出す。

本文の列は、番号のラベルがはみ出す分の余白を左右の両方に取り、一覧と同じ中心に置く。

書く画面の帯は、左に「← 一覧」と名前、右へ 見え方(全体)→ 中身(主張・キーワード)→ 新しく作る(新規作成)→ 外へ出す(印刷・紙切れへ送る・鍵・Bluesky)の順に並べる。紙切れの帯と同じ並びである。

4.2 番号 #

投稿の末尾に、Bluesky と同じ丸いラベルで番号(3/12)を付ける。番号はファイルに書かず、画面で数える。投稿を足すと分母が変わるからである。ラベルは行の外の余白へはみ出してよい。ラベルに押されて本文が次の行へ折れないようにするためである。

4.3 直す #

投稿を押すと、その投稿が入力欄の位置で直す欄になる。俯瞰の列から押しても同じである。直すためのモードは置かない。前の投稿は上の段に、後ろの投稿は下の段に並ぶ。直した投稿に返していた次の投稿が、宙に浮かないようにするためである。直す欄の「消す」で、その投稿を消す。公開した投稿は押しても直す欄にならない。文字を選んだだけのときと、リンクを押したときも入らない。

4.4 一覧 #

一覧は1列で、中身は出さない。書く画面に同じ全体が出るからである。一覧は更新の新しい順に並べる。アプリを開くと、いつも一覧から始まる。

  • 一覧は1件1行で、日付(今日・きのう・9月14日)の見出しで区切る。行には主張・件数・印だけを出し、名前と最終更新日時はマウスを載せると出る
  • 絞り込みのボタンは置かない。投稿済みと鍵は行の印で見分け、探すのは検索(4.5)とキーワードの索引(4.8)で行う
  • 一覧の行を1回押すと書く画面に入る。開いていたスレッドなら、書きかけの入力や直している途中の状態ごと戻る。最後に開いたスレッドの行の左端に「→」を出す
  • 書きかけの入力はスレッドごとに保存する。別のスレッドへ移っても消えない。まだ投稿していない新しいスレッドの書きかけには、「新規作成」で戻る
  • Bluesky に投稿したスレッドには青い点、鍵をかけたスレッドには鍵の印を、日時の横に付ける
  • 一覧の行の右端のゴミ箱の印でスレッドを片づける。消さずに piles/ へ移すので、あとから戻せる。印は淡い色で常に出し、行を押す動きと重ならないよう行のボタンの外に置く。押すと確認を出す
  • 書く画面には、ゴミ箱も白紙に戻すも置かない。スレッドの URL は1件目の投稿そのもので、投稿済みの分は消せないからである。書き直すなら新規作成で始める

4.8 キーワードと主張 #

一覧を読めるようにするために、スレッドごとにキーワードと主張の一行を持つ。どちらも書き終わってから決まるものなので、自動で出した下書きを直して使う。名前を先に付けないのと同じ理由で、先に決めない。

項目 決まり
キーワード 4つまで。ほかのスレッドと比べて、そのスレッドだけに多い語を2つ自動で出す。書く画面の帯から直せる
索引 ペインの下端に固定し、一覧の列の中央にそろえる。一覧の本数で上下に動くと、目で探し直すことになるからである。2本以上のキーワードを件数の多い順に7つまで出す。件数は数字ではなく地の濃さで示す。押すとそのキーワードで絞り込む。残りは「ほか」で開き、「たたむ」で戻す
主張 一行。本文の文を採点して自動で出し、候補を3つ示す。書く画面の帯から直せる。1行に入らないときは0.75倍まで字を小さくして収め、それでも入らなければ末尾を切る
保存 見出しと鍵の下に <!-- re:keywords … --> と <!-- re:claim … --> の行を置く

主張の採点は次の順で見る。「AがBを〜する」の他動詞で終わる一文と、「〜は」で題目を立てた文を上に置く。指示語で始まる文、数字の並ぶ文、列挙、「〜と思う」のような思考述語で終わる文は下げる。

主張の形にならないスレッドは日記型とみなし、最初の一文を淡い字で出す。論証しているスレッドの主張は濃い字で出すので、一覧で両者を見分けられる。

4.5 検索 #

一覧の帯の検索欄で、すべてのスレッドを探す。⌘F で検索欄に移る。

  • 投稿の本文と画像の ALT を探し、当たった投稿を1件ずつ新しい順に出す。スレッドの名前に当たったときはスレッドを出す
  • 空白で区切った語は、全部を含む投稿だけを出す
  • 全角と半角、英字の大文字と小文字は区別しない。ひらがなとカタカナは区別する
  • 「片づけたものも」にチェックを入れると piles/ も探す。既定では探さない
  • 結果の行を押すと書く画面に入り、当たった投稿へ移って色を付ける。片づけたスレッドは開けない
  • 日本語の変換中は探さず、確定したときに探す。Esc で検索欄を空にし、一覧に戻る

4.6 スレッドへのリンク #

本文に日時の名前(2026-09-15_2303)を書くと、そのスレッドへのリンクになる。matters/ にある名前だけをリンクにする。

  • 押すとそのスレッドの書く画面に入る。書いていた入力はスレッドごとに保存してあるので、戻れば残っている
  • Bluesky に投稿するときは、名前の文字はそのまま残し、相手のスレッドの第一投稿へのリンクを付ける(8.3)。相手がまだ投稿されていなければ付けない

4.7 印刷 #

書く画面の帯の「印刷」で、スレッドを A4 に印刷する。

項目 決まり 理由
紙面 A4、10pt、1行48字前後×50行。1ページに2,000字ほど
番号 各投稿の頭に 3/22 を出す 紙では、どこからどこまでが1件かを先に見たい
段落 1件を1段落にまとめる。句点で終わる行はそのままつなぎ、それ以外の行は全角の空白をはさむ 画面の空行のまま刷ると短い行ばかりになり、1ページに1,000字ほどしか入らない
画像 ALT を添えて小さく載せる
見出し スレッド名・件数・印刷した日。ページの下にページ番号

4.9 紙切れへ送る #

書く画面の帯の「紙切れへ送る」で、スレッドを紙切れの下書きにし、紙切れの書く画面で開く。スレッドを材料に、長い文章へ仕上げるための入り口である。

  • 1投稿を1段落にする。投稿の中の段落はそのまま残す
  • 画像は移さない。ALT を「> 画像:…」の行にして、材料に残す
  • 手で直した主張があれば題にする。自動の下書きは使わない
  • 下書きのフロントマターに re: <スレッド名> を書いてつながりを残す。2回目からは「紙切れで開く」になり、新しく作らない。紙切れで直した文を上書きしないためである
  • 紙切れの下書きの置き場(KAMIKIRE_MATTERS)と書く画面の URL(KAMIKIRE_URL)は .env に書く。書いていなければボタンを出さない

5. 保存 #

スレッドは1本ずつ Markdown ファイルに保存する。投稿・直す・削除のたびに書き込み、書き出しのボタンは持たない。

matters/
└── 2026-09-14_1530/
    ├── 2026-09-14_1530.md
    └── images/
        └── 20260914-153012-a1b2c3_2000x1500.jpg
# 2026-09-14_1530

<!-- re:lock -->

<!-- 2026-09-14 15:30:12 -->
一件目の本文。

![画像の説明](images/20260914-153012-a1b2c3_2000x1500.jpg)

<!-- 2026-09-14 15:31:40 at://did:plc:…/app.bsky.feed.post/… bafy… -->
Bluesky に投稿した二件目の本文。
要素 決まり
区切り 投稿の前に <!-- YYYY-MM-DD HH:MM:SS --> を置く。投稿の時刻が残るので、返しの間隔をあとで測れる
投稿済み 区切りに Bluesky の URI と CID を足す
画像 本文の下に ![ALT](images/…) の行で書く。ファイル名には縦横の画素数を入れる
鍵 見出しの下に <!-- re:lock --> の1行を置く

ファイルは他のエディタで直してよい。書き込む前にファイルの更新時刻を比べ、外で直されていたら書き込まずに止める。書きかけの入力は手元に残す。

6. 画像 #

  • 「画像」ボタン、貼り付け、ドラッグで、1投稿に4枚まで付ける
  • 長辺2,000px以内の JPEG に描き直し、950KB以下に縮めて保存する(Bluesky の上限は1枚2MB)。描き直すので、撮影情報や位置情報は残らない
  • 画像ごとに ALT の入力欄を出す。空でも投稿できるが、Bluesky に投稿するときに ALT のない枚数を示して確かめる

ALT は、画像を言葉にした材料でもある。あとで Markdown を読むとき、画像の中身として残るのは ALT だけだからである。

7. Markdown・数式・表 #

  • 投稿を Markdown として表示する。数式は $...$(文中)と $$...$$(段落)、表は | 列 | の書き方で書く
  • 入力欄は文字のままにし、数式か表を書いたときだけ、欄の下に表示の結果を出す
  • 本文に書いた HTML は表示に使わない
  • 金額の $5 や、キャッシュタグの $ATPR は数式と見なさない

8. Bluesky への投稿 #

8.1 基本 #

  • Bluesky の操作は、書く画面の帯の「Bluesky」1つにまとめる。押すとメニューが開き、「投稿する」「同期する」「Bluesky で開く」のうち、そのスレッドで使えるものだけを出す。未投稿の件数はボタンの横に小さな丸で出す
  • メニューの「投稿する」で、未公開の投稿を順にスレッドとして投稿する。2件目からは直前の投稿への返信として送る
  • 1件送るごとにファイルへ書く。途中で失敗しても、次は続きから送る
  • 書き足した分は、あとから同じスレッドの続きとして送れる
  • 公開した投稿は直せない。番号のラベルの色を変え、直す対象から外す。サーバーも書き換えを受け付けない
  • 認証は、アプリパスワードをリポジトリ直下の .env に書く

8.2 鍵 #

スレッドごとに鍵をかけられる。鍵をかけたスレッドは「Bluesky に投稿」ボタンを出さず、サーバーも投稿の依頼を断る。Bluesky に出してはいけないメモを、間違って投稿しないためである。鍵は投稿単位にはしない。途中の投稿を飛ばすと、Bluesky 側の返信のつながりが崩れるからである。

8.3 本文の注記 #

リンク・メンション・ハッシュタグ・キャッシュタグを、投稿するときに本文から探して付ける(Bluesky の facet)。判定は公式ライブラリ @atproto/api の rich-text/detection.ts に合わせる。ただし日本語の文に合わせて、次の点を変える。

項目 公式 Re:
# @ $ の直前 行頭・空白・( だけ 句点やかなの直後も認める(「書いた。#返しモデル」)
ハッシュタグの終わり 次の空白まで 全角の句読点でも切る
キャッシュタグの後ろ 空白か ASCII の句読点 英数字以外なら認める(「$ATPRの投稿」)
スキームのないドメイン 行頭・空白・( の直後 全角の句読点の直後も認める。かなや漢字の直後は認めない
ホスト名のハイフン 認めない 認める(公式では my-site.com がリンクにならない)

本文に書いたスレッドの名前(4.6)には、相手のスレッドの第一投稿へのリンクを付ける。

[サイト名](URL) と書くと、投稿では URL を消し、「サイト名」の文字にリンクを張る。論文に出典を示す書き方に合わせたものである。字数もリンクの文字列で数えるので、URL の長さは字数に入らない。Markdown ファイルは記法のまま残す。画像の ![ALT](…) は対象にしない。

投稿の言語(langs)は、本文にかなか漢字があれば ja、なければ en にする。

8.4 埋め込み #

公式アプリと同じ扱いにする。

  • bsky.app の投稿の URL があれば引用にする
  • 画像があれば画像を付ける。引用と画像は両方付けられる
  • どちらもなければ、最初の URL のリンクカードを付ける(題名・説明・サムネイルは cardyb.bsky.app から取る)

8.5 数式と表 #

Bluesky は Markdown も数式も解釈しない。投稿するときに、数式と表を本文に出てくる順に [数式1] [表1] に替え、表示した画像を同じ順に添える。ALT には元の LaTeX や表の記号を入れる。太字・コード・見出しは記号だけを外す。画像が4枚を超える投稿と、替えて300字を超える投稿は、送る前に止める。Markdown ファイルは元の記号のまま残す。

8.6 同期 #

Bluesky 側で足した返信や消した投稿を、Re: の記録に合わせる。投稿済みのスレッドでは、帯の「Bluesky」のメニューに「同期する」が出る。

  • 自分の PDS から、そのスレッドに属する自分の投稿を集める。ログインは要らない
  • スレッドの頭から、自分の返信を順にたどる。途中の投稿が消えていたら、消えた投稿への返信から続きをたどる
  • Re: の記録にある投稿は Re: の側を残す。元の画像と ALT があるからである
  • Bluesky で足した投稿は画像ごと取り込む。短く表示されたリンクは URL 全体に戻す
  • Bluesky で消えた投稿は記録から外す。未投稿の下書きは末尾に残す
  • 他人の返信と、本筋から枝分かれした自分の返信は取り込まない。枝分かれは件数だけ知らせる
  • 合わせる前に、足す件数と外す件数、それぞれの冒頭を示して確かめる。合わせる前の版は piles/ に残す

一覧の帯の「取り込む」に Bluesky のスレッドの URL を入れると、Bluesky で書いたスレッドを手元に作る。

  • 返信の URL でもよい。スレッドの頭まで遡り、頭から自分の返信を同期と同じ方法でたどる
  • 名前は頭の投稿の日時にする。同じ頭の投稿を持つスレッドが手元にあれば、新しく作らず同期する
  • 自分の投稿でなければ鍵をかける(8.2)。他人のスレッドの続きを Bluesky へ投稿しないためである

9. 守ること #

  • サーバーは手元(127.0.0.1 と ::1)にだけ待ち受ける。外からはつながらない。localhost が IPv6 の ::1 を先に返す環境があるので、両方で待つ
  • 投稿のレコードには $type・text・createdAt・langs・reply・facets・embed 以外を入れない
  • アプリパスワードはファイルに書き、コードに書かない

10. まだないもの #

  • 複数の人がブラウザだけで使える形(保存をブラウザの中に移し、Bluesky への投稿を atproto の OAuth で行う)
  • Bluesky 以外への投稿(leaflet など)