移動中に決めたこと、どこに残っていますか。
電車の中で「この案件はこう進める」と決める。スマホにメモする。その日は覚えています。
二週間後、「なぜそう決めたんだっけ」と思い出せなくなります。
私はここを、スマホのDiscordに一行打つだけで済むようにしました。
!decide 3 見積は先に出す。着手は正式発注のあと
数秒で返信が来ます。同時に、自宅のパソコンにある判断の一覧表(Markdownファイル)の
先頭に、日付つきで1行が挿し込まれています。
調べものも同じです。「先月の判断を一覧にして」と普通の日本語で書くと、
パソコン側のAIがファイルを読んで、結果を返してきます。
この記事は、その構成の作り方と、作ってみて分かった注意点をまとめたものです。
2026年9月時点の構成で、Claude Codeは 2.1.278、discord.py は 2.3.2 を使っています。
作る前に困っていたこと
外出先で使える道具はスマホしかなく、スマホで書いたメモは行き止まりになります。
- メモアプリに書く → あとで探せない
- 自分宛てにメールする → 受信箱に埋もれる
- 頭で覚える → 二週間で消える
足りないのは書く場所ではなく、日付と理由がそろった形で残ることでした。
「9月20日に、こういう理由でこう決めた」まで残っていれば、後から使えます。
作ってみて変わったこと(先に書きます)
効果を時間で示せる段階ではないので、正直に定性で書きます。
作る価値があるかを先に判断できるよう、ここを前に置きます。
変わったのは、判断を残すかどうかを迷わなくなったことでした。
以前は「これは残すほどのことか」と考えて、結局残しませんでした。
いまは一行打つだけなので、迷う手間のほうが大きくなりました。結果として残る量が増えています。
もうひとつは、過去の判断を引くようになったことです。
探す場所が1つに決まっているので、実際に探します。探して出てこなければ、それも分かります。
短くなったのは作業時間ではなく、残すか迷う時間でした。
中核はDiscord・Claude Code・Obsidianの3つ
考え方はとても単純です。
| 部品 | 役割 |
|---|---|
| Discord | スマホ側の入力窓。専用サーバーを1つ作り、自分だけが入る |
| Claude Code(CLI版) | パソコン側で動くAI。指示を受けてファイルを読み書きする |
| Obsidian | 記録の置き場。中身はただのMarkdownファイル |
実際に動かすには、この3つに加えて、Python製のBot、常時起動しているパソコン、
それを常駐させる仕組みが必要です。詳しくは後述します。
Discordを使ったのは、自分専用のサーバー1つで運用でき、Botを一般公開する手続きも要らないからです。
自分ひとりで使う道具にはちょうどよい形でした。
ただし誤解しないように書いておきます。
打った内容とBotの返信は、Discordのサービスを経由します。 端末の中だけで完結する仕組みではありません。
Obsidianを使ったのは、保存されるのが普通のテキストファイルだからです。
専用の形式で囲い込まれないので、AIがそのまま読めます。ここが効いています。
Obsidian側は、特別な設定をしていません。フォルダにMarkdownファイルが並んでいるだけです。
Claude CodeのCLIに、指示を渡すところ
肝心のところは、拍子抜けするほど短いコードです。
Claude CodeのCLI(コマンドで動く版)を、そのまま呼び出しています。
python
proc = await asyncio.create_subprocess_exec(
CLAUDE_BIN,
"--print", # 対話せず、結果だけ返す
"--dangerously-skip-permissions", # 確認を求めずに実行する
"--output-format", "text",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE, # 返事を受け取るのに必要
stderr=subprocess.PIPE,
cwd=cwd, # 作業するフォルダを指定する
)
stdout, stderr = await asyncio.wait_for(
proc.communicate(input=task.encode()),
timeout=180,
)
やっていることは「AIに指示文を渡して、返事を受け取る」だけです。
ファイルを探す、読む、書き換えるは、AIが自分でやります。
こちら側に、ファイルを操作するコードは1行もありません。
たとえば「過去の記録を検索する」処理も、検索のコードは書いていません。
「このフォルダをgrepで探して、見つかったファイルを読んで、300字以内で答えて」と
手順を日本語で指示しているだけです。探すのも読むのもAI側の仕事です。
作業するフォルダ(cwd)を渡すのは大事です。
これを指定しないと、AIはどのフォルダの話なのか分からず、見当違いの場所を探します。
用意するもの
先にお伝えしておくと、この記事は丸写しで動くコードを配る記事ではありません。
構成の考え方と、実際に引っかかった箇所を残すことを目的にしています。
作るのに必要なものは、次のとおりです。
| 用意するもの | 補足 |
|---|---|
| Discordのアカウントと、自分専用サーバー | 無料。サーバーは自分ひとりだけにする |
| Discord Botのトークン | Discord Developer Portalでアプリを登録して取得する |
| 常時起動できるパソコン | 私はLinuxのデスクトップを使っています |
| Claude CodeのCLI | ログインを済ませておく。私は 2.1.278 |
Python と discord.py |
私は discord.py==2.3.2 |
| 記録を置くフォルダ | 中身はただのMarkdownファイル。Obsidianでなくても構わない |
Developer Portalでの作業は3つです。アプリを登録してトークンを発行する、
メッセージの本文を読み取る権限(Message Content Intent)を有効にする、
そしてOAuth2のURL生成でBotを自分のサーバーに招待する。
Message Content Intentが無効だと、Botは起動しても、通常のメッセージ本文を期待どおり処理できません。
ここは見落としやすい設定です。
環境変数には、Botのトークン、許可するユーザーのID、記録フォルダのパスを入れています。
トークンをコードに直接書かないでください。
パッケージは pip install -r requirements.txt で入れています。
まずは python bot.py を手で動かして、返事が来ることを確かめてから常駐させるほうが早いです。
パソコン側で待たせておく
外出先から頼むので、パソコン側は常に待っている必要があります。
Linuxなら、systemdに登録するだけです。
ini
[Service]
ExecStart=/usr/bin/python3 /path/to/discord_agent/bot.py
Restart=on-failure
RestartSec=10
Restart=on-failure を入れておくと、異常終了しても10秒後に起き上がります。
外出先から頼む道具なので、落ちたことに気づけるのは帰宅後です。
自分で起こし直さなくていい形にしておくのは、この用途では必須でした。
上のファイルを /etc/systemd/system/discord-agent.service として置き、
[Unit] と [Install](WantedBy=multi-user.target)を含めた形で保存します。
そのあとの操作は次のとおりです。
bash
sudo systemctl daemon-reload # ファイルを置いた・変えたら必ず実行する
sudo systemctl enable --now discord-agent # 自動起動を有効にして起動する
systemctl status discord-agent # 動いているか見る
journalctl -u discord-agent -f # ログを流しながら見る
sudo systemctl restart discord-agent # コードを変えたあと
sudo systemctl stop discord-agent # 止める
daemon-reload は、変更したファイルをsystemdに読み直させる操作です。
すでに動いているプロセスに反映するには、そのあとの restart も必要です。
動作確認は、Discordで !myid と打つのが手軽です。
自分のユーザーIDが返ってくれば、Botまで届いています。
返ってこない場合は、まず systemctl status とログを見てください。
そのうえで、Botのトークン、チャンネルの権限、Message Content Intent、
許可ユーザーIDの順に確認すると切り分けられます。
判断を「表の先頭」に挿し込む(ここだけ自分で書いた)
!decide だけは、AIに任せず自分でコードを書きました。理由は後で述べます。
判断の一覧は、日付の新しいものを上に並べた表にしています。
ここに追記するとき、素朴に「ファイルの末尾に足す」と失敗します。
降順の表に末尾追記すると、いちばん新しい判断が、いちばん古い位置に入ります。
そこで、表の区切り行(|---|---|)を探して、その直後に挿し込んでいます。
python
for index, line in enumerate(lines):
stripped = line.strip()
if stripped.startswith("|") and "-" in stripped and set(stripped) <= set("|-: \t"):
separator = index
break
lines.insert(separator + 1, entry + "\n")
さらに2つ、地味ですが必要だった処理があります。
- 本文に
|が入ると表が壊れるので、全角の|に置き換えています - 改行を除去しています。表の1マスに改行は入れられません
書き込みは、一時ファイルに書いてから置き換える形にしました(os.replace)。
書いている途中で失敗しても、元のファイルが半分書きかけの状態で上書きされません。
置き換えが済んでいなければ、元のファイルがそのまま残ります。
(電源断まで守れるわけではありません。そこまで必要なら、書き込み後にディスクへの同期を待つ処理が要ります。
私はそこまではやっていません。)
判断の一覧は、後から見返すための正本です。壊れると困る度合いが、他のファイルと違います。
ここをAIに任せなかったのは、挿し込む位置が間違っても、返事は「できました」になってしまうからです。
自分で確かめられる形にしておきたい処理は、自分で書いています。
つまずいた点(ここが本題かもしれません)
作ってから気づいたことを、正直に並べます。
1. 「聞かれて止まる」には2種類ある
ここは混同しやすいので、分けて書きます。
ファイル操作の許可を求める確認は、--dangerously-skip-permissions を付けているので出ません。
これはその名のとおり、確認を飛ばすためのオプションです(危険な点は後述します)。
止まるのはもう一方です。AIが作業に入らず、聞き返して終わることがあります。
「対象はどちらのフォルダですか」「この方針で進めてよいですか」と返して、そこで終わります。
--print は一往復で終わる形式なので、答える機会がありません。
対策は指示文の側です。
- 「確認を求めず、最後まで進めてください」と明示する
- 対象のフォルダ・ファイル・件数を、指示文の中で具体的に指定する
聞き返す余地を残さない書き方にしておく、ということです。
2. 待つのをやめるだけでは、AIは止まらない
タイムアウトを180秒にしています。長い作業は返ってきません。
ここで一度間違えました。最初は、こう書いていました。
python
await asyncio.wait_for(proc.communicate(...), timeout=180)
これは待つのをやめるだけで、起動したAIのプロセスは動き続けます。
Discordにはタイムアウトの返事が出るのに、裏では作業が続いている状態になります。
終了まで面倒を見るには、明示的に止める必要がありました。
python
except asyncio.TimeoutError:
proc.kill()
await proc.communicate() # 終了を待って回収する
raise RuntimeError("180秒で終了しました")
これは記事を書く過程で気づいて直した箇所です。
実際に確かめました。直す前は、タイムアウト後もプロセスが残っていました。直したあとは残りません。
ただし、止まるのは直接起動したプロセスまでです。
そこからさらに別のプロセスが起動していた場合、kill() だけでは止まる保証がありません。
そこまで確実に止めたい用途では、プロセスをグループ単位で終了させる作りにする必要があります。
そして180秒という数字は、制限というより頼める作業の粒度を決めています。
「先月の判断を一覧にして」は返ってきます。「記事を1本書いて」は返ってきません。
外出先から頼むのは、調べものと記録に向いています。
3. Discordは1通2,000字まで
長い返事はそのままでは送れません。1,900字で区切って複数通に分けています。
4. Discordは表を描画しない
Discordの書式は、Markdownの一部だけに対応しています。表は対応していません。
AIが表の形で返してくると、記号がそのまま並んだ状態で届きます。
指示文の側に「箇条書きで返して」と書いておくほうが確実でした。
5. 許可するユーザーを、IDで固定する
ここは省略できません。
```python
ALLOWED_USERS = set(os.environ["ALLOWED_USERS"].split(","))
def is_allowed(user) -> bool:
return str(user.id) in ALLOWED_USERS
```
自分のIDを知るための !myid は、誰でも使えるようにしています(IDが分からないと設定できないため)。
!decide を許可されていない人が打つと、拒否のメッセージを返します。
それ以外のメッセージは、許可した人以外には無反応です。
ここは真似しないでください
--dangerously-skip-permissions は、名前のとおり危ないオプションです。
AIが確認なしにファイルを操作します。
私が個人利用しているのは、次の条件がそろっているからです。
- 動かしているのは自分専用のパソコンである
- Discordサーバーは自分ひとりしかいない
- 操作できるユーザーをIDで限定している
- 置いてあるのは自分の記録で、他社から預かったデータは入っていない
ただし、これは安全を保証する条件ではありません。
ユーザーIDの制限は、Discordから直接指示できる人を絞るだけです。
AIが読み取ったファイルや取得した情報の中に、指示のように見える文章が混ざっていた場合、
それに従ってしまう可能性は残ります。読ませるものを選ぶ必要がある、ということです。
そしてもう一点、混同されやすいので明記します。
ファイルがパソコンの中にあることと、中身が外に出ないことは別の話です。
AIが読んだファイルの内容は、処理のためにAI提供元のサーバーへ送られます。
「ローカルのファイルを扱っているから外部に出ない」わけではありません。
判断を残す仕組みとしては便利ですが、そこに何を置くかは選ぶ必要があります。
そしてもう一つ、私自身が最初に誤解していた点です。
フォルダを分けたり、作業フォルダを指定したりしても、アクセス範囲の制限にはなりません。
先に出た cwd は「どこから始めるか」の指定にすぎません。
このオプションを付けたAIは、Botを動かしているOSユーザーが読めるファイルすべてに届きます。
記録のフォルダだけを見るとは限りません。
以上を踏まえて、お客様のデータや、会社の業務データが入る環境ではこの形にしないでください。
業務で使うなら、このオプションを外すのが基本です。
どうしても無人で動かす必要があるなら、専用のOSユーザーかコンテナで動かし、
対象フォルダ以外はOSの権限で読めない状態にする必要があります。
その環境に、SSHの鍵、ブラウザの保存情報、他サービスのログイン情報を置かないでください。
自動化でいちばん危ないのは、自宅で便利だった構成をそのまま業務に持ち込むことです。
Botを作らずに、履歴を残す部分だけ始める
ここまで読んで「そこまではやらない」と思われた方へ。
入口を作らなくても、履歴を残す部分だけなら今日から始められます。
すでに業務で使えるAIがある職場なら、そこが入口になります。
たとえばMicrosoft 365のCopilotは、案件について調べたことを聞くと、
見出しと箇条書きの形でまとめて返してくれます。人に依頼して集まった情報も、同じようにまとめられます。
ただし、社内のメールや文書を横断して広く参照させる使い方には、原則として専用のライセンスと職場側の設定が必要です。
ライセンスがない場合でも、自分で渡したファイルなど、限られた範囲なら参照できることがあります。
どこまで見られるかは、その人のアクセス権の範囲でも変わります。
何が使えるかは、社内の管理担当に確認するのが確実です。
その出力を、ただのテキストファイルが並ぶ置き場に貯めていくだけで履歴になります。
振り返るときに、誰がどれだけ何をやったかを読み返せます。Obsidianはその置き場として使っているだけです。
大事なのは入口の作り込みではなく、出力がテキストで残り、あとから検索できる形になっていることです。
Botは、外出先からその置き場に触れるようにするための窓にすぎません。
⚠️ 業務の情報を社外のサービスや個人の端末に置いてよいかは、勤務先の規程で決まります。
便利さの前に、そこを確認してください。
よくある質問
Q: スマホにObsidianを入れる必要はありますか?
A: 要りません。この構成では、スマホ側はDiscordだけです。ファイルはパソコン側にあります。
Q: パソコンを閉じていたら使えませんか?
A: 使えません。常時起動しているパソコンが必要です。私はLinuxのデスクトップを常時起動しています。
Q: AIの利用料はかかりますか?
A: 私はClaude Codeのサブスクリプションの範囲で使っています。使用量には上限があります。
なお、APIキーを設定した状態で使うと、そちらの従量課金になります。
料金の条件は変わるので、金額の判断は公式の料金ページで確かめてください。
Q: Windowsでも動きますか?
A: 仕組み上は動きますが、私は確認していません。常駐のさせ方(systemdの部分)はWindows向けに書き換える必要があります。
Q: Discord以外でもできますか?
A: できます。要るのは「スマホから文字を送れて、Botが受け取れる窓」だけです。Slackでも同じ構成が組めます。
おわりに
作るときに決めるべきことは、2つだけだと思っています。
- どこまでAIに任せるか:間違えたときに自分で気づけない処理は、自分で書く
- どこまでAIに読ませるか:ファイルが手元にあっても、中身は処理のため外に出る
判断や依頼の履歴が人の頭とチャットの流れの中にしかないと、引き継ぎのときに消えます。
そこを整えるのは、道具の話の前に、何をどこに残すかを決める話です。
「自社の業務でも、記録と履歴の残し方から整理したい」というご相談を承っています。
業務の流れを整理して「何を作るか」を決めるところ(要件定義)から、運用後の保守まで対応します。
- ホームページ:https://mamagotolab.com
- ご依頼(クラウドワークス):https://crowdworks.jp/public/employees/6942778
関連記事
- 引き継ぎ手順書が伝わらない原因と直し方──読む人が詰まる3つの言葉
- ブラウザ操作を記録して手順書を作るChrome拡張──CSVで同じ登録を一括入力する
ママゴトラボは、業務の自動化ツールを「何を作るか」を決めるところ(要件定義)から設計してつくる開発ラボです。
属人化した業務の見える化から、自動化ツールの開発・保守まで承っています。
👉 ママゴトラボ|業務自動化の開発ラボ
その業務、自動化できるかもしれません
「毎回手でやっている作業」を、「何を作るか」を決めるところ(要件定義)から見直してツールにします。GAS・Python・VBAでの自動化のご相談を承っています。
ココナラで相談する →