bodylog について
bodylog は、エージェント向けの個人用トレーニング・食事記録ツールで、コマンドライン、Python ライブラリ、Claude スキルを備えています。データはローカルの SQLite ファイルに保存され、栄養情報には USDA と Open Food Facts のデータを使います。アカウントやクラウド保存は不要です。
主な機能
- 01チャットからトレーニングと食事を記録
- 02カロリー、栄養素、目標、連続記録を追跡
- 03USDA と Open Food Facts のデータを利用
- 04記録をローカルの SQLite ファイルに保存
- 05種目別の履歴と自己記録を確認
- 06共有可能なトレーニング・食事カードを生成
活用シーン
- 01トレーニング中にセットを記録
- 02食事を記録して一日の栄養合計を確認
- 03週間トレーニング量と自己記録を確認
- 04共有用のトレーニングまたは食事カードを作成
MCP 対応
bodylog には MCP サーバーが含まれ、トレーニングや食事の記録・編集、進捗確認、カード作成のツールを提供します。任意の MCP クライアントで利用できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx bodylogBODYLOG_DBSQLite file for the log (default ~/.bodylog/log.db)BODYLOG_CARDSDirectory for rendered card PNGs (default ~/.bodylog/cards)FDC_API_KEYシークレットUSDA FoodData Central API key (free at api.data.gov); DEMO_KEY is used without oneBODYLOG_OFFLINESet to 1 to use only the bundled USDA table, no network lookupsローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
15掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| rpe | any | いいえ | |
| kind | string | いいえ | |
| reps | any | いいえ | |
| text | any | いいえ | |
| unit | any | いいえ | |
| count | integer | いいえ | |
| notes | any | いいえ | |
| weight | any | いいえ | |
| exercise | any | いいえ |
詳細
bodylog
個人用エージェント向けのトレーニングと食事の記録ツールです。チャットで、声に出して伝えるようにセット内容や食事をエージェントに伝えます。記録を保存し、実際の栄養データを使ってカロリーとマクロ栄養素を計算し、連続記録を管理して、共有可能なカードを返します。
あらゆるエージェントで使える単一パッケージです。MCP サーバー(bodylog-mcp)、CLI(bodylog)、Python ライブラリ、Claude スキルが含まれます。すべてがローカルの SQLite ファイル 1 つに保存されます。アカウント、クラウド、ソーシャル機能はありません。
| 食事の記録 | ストーリー | トレーニング |
|---|---|---|
![]() | ![]() | ![]() |
その他:食事、ライト、1 日の食事とトレーニング (全体)、トレーニングのストーリー、 8 種目のトレーニング、2 ページ、kg と lb の混在、 写真用ステッカー。
インストール
Python 3.10 以降。
pip install bodylog # CLI + library + MCP server
uvx --from bodylog bodylog-mcp # run the MCP server without installing
Claude Code のプラグインとして(スキルと MCP サーバーをまとめてインストール):
/plugin marketplace add abhaymettu/bodylog
/plugin install bodylog@bodylog
Claude Code の MCP サーバーのみ:
claude mcp add bodylog -- uvx --from bodylog bodylog-mcp
その他の MCP クライアント:
{
"mcpServers": {
"bodylog": {
"command": "uvx",
"args": ["--from", "bodylog", "bodylog-mcp"],
"env": { "FDC_API_KEY": "optional, free at https://api.data.gov/signup/" }
}
}
}
設定項目(すべて省略可能):
| 変数 | デフォルト | 内容 |
|---|---|---|
BODYLOG_DB | ~/.bodylog/log.db | SQLite ファイル |
BODYLOG_CARDS | ~/.bodylog/cards/ | カード PNG の保存先 |
BODYLOG_UNIT | 最も多く記録された単位 | トレーニングの合計に使う kg または lb |
FDC_API_KEY | DEMO_KEY | USDA FoodData Central キー。DEMO_KEY では 1 時間あたり数回しか検索できません |
BODYLOG_OFFLINE | オフ | 1 にすると、バンドルされた食品テーブルのみを使用し、ネットワークに接続しません |
スキルは skills/bodylog/SKILL.md にあります。プラグインを使わない場合は、skills/bodylog/ をエージェントのスキルフォルダーにコピーするか、シンボリックリンクを作成してください。
食事
CLI は MCP ツールが返す内容を表示します(bodylog eat は log_food です)。オフラインでの実際の実行例です。
$ bodylog eat "2 eggs, toast and a protein shake"
#1 breakfast: 2 × egg, 100 g: 143 kcal, P 12.6 C 0.7 F 9.5
#2 breakfast: toast, 22 g: 64 kcal, P 2 C 12 F 0.9
#3 breakfast: whey protein, 26 g: 92 kcal, P 20.3 C 1.6 F 0.4
$ bodylog eat "greek yogurt with blueberries and a handful of almonds"
#4 breakfast: greek yogurt, 170 g: 100 kcal, P 17.3 C 6.1 F 0.7
#5 breakfast: blueberries, 148 g: 84 kcal, P 1.1 C 21.4 F 0.5
#6 breakfast: 1 handful almonds: not counted (no weight for a handful of almonds; give grams or one of: almond, cup, oz)
$ bodylog food-fix 6 --grams 28
#6 breakfast: 28 g almonds: 162 kcal, P 5.9 C 6 F 14
個数だけを指定した場合、その食品について USDA の標準的な分量が使われます。大きな卵 1 個(50 g)、トースト 1 枚、ホエイ 1 杯(FNDDS の「1 scoop, NFS」、26 g)などです。MCP を通じて、エージェントは推測する代わりに、項目 6 について短い質問を 1 つ尋ねます。
食品の数値が取得される仕組み:
- 同梱テーブル。 USDA FoodData Central(SR Legacy と FNDDS)から取得した一般的な食品 62 種。それぞれに FDC ID、100 g あたりの値、USDA 独自の分量(大きな卵 1 個、パン 1 枚、米 1 カップ)が含まれます。オフラインで動作します。
scripts/build_common_foods.pyで USDA のダウンロードデータから再構築されます。 - キャッシュ。 以前に検索したデータが SQLite ファイルに保存されます。
- USDA FoodData Central の検索(
POST /fdc/v1/foods/search、survey、SR Legacy、Foundation foods)。FDC_API_KEYまたはDEMO_KEYを使用します。 - Open Food Facts によるブランド食品や包装食品の検索、およびバーコードによる製品検索(
GET /api/v2/product/<barcode>.json、キー不要)。
検索結果は、食品名に指定されたすべての単語が含まれる場合にのみ使用されます。含まれない場合は、最も近い候補とともに項目を unknown として保持し、エージェントがどれを指しているのか尋ねられるようにします。量をグラムに換算できない項目(ひとつかみ、または USDA に体積換算重量がない食品のミリリットル)は needs_amount として保持されます。どちらも修正されるまで合計に含まれず、作り上げた数値が補われることもありません。ラベルから読み取った数値は、指定された値のまま(manual)保存されます。
また、kcal、タンパク質、炭水化物、脂質の1日の目標、日数単位の記録継続日数(まだ記録していない日は途切れたとみなされません)と週数単位のトレーニング継続週数、さらにダーク、ライト、クリア、ストーリー形式のデイリーカードもあります。その日にトレーニングも行った場合、カードにトレーニングブロックが追加されます。
ワークアウト
30秒デモ
以下のチャットは、実際に log_set(text=...) を実行したときのものです。右側の列には、各メッセージについてストアに記録された内容が表示されています。
you: push day -> title: Push Day
you: bench 20 kg x 10 warm up -> Bench Press: 20 kg x 10 (warmup)
you: 60kg x 10 -> Bench Press: 60 kg x 10
you: 67.5 kg x 4 -> Bench Press: 67.5 kg x 4
you: 62.5 kg x 8 rpe 9 -> Bench Press: 62.5 kg x 8
you: next incline db press 55 lb x 10 -> Incline Dumbbell Press: 55 lb x 10
you: same -> Incline Dumbbell Press: 55 lb x 10
you: 55lb x 9 -> Incline Dumbbell Press: 55 lb x 9
you: 12.5 kg x 12 -> Incline Dumbbell Press: 12.5 kg x 12
you: that was triceps pushdowns on the cable -> named 1 set(s) Triceps Cable Pushdown
you: 12.5 kg x 11 -> Triceps Cable Pushdown: 12.5 kg x 11
you: lateral raise 15 lb x 14 -> Lateral Raise: 15 lb x 14
you: 15 lb x 12 -> Lateral Raise: 15 lb x 12
you: one more -> Lateral Raise: 15 lb x 12
you: wrapped up, workout took 1h 3m -> ended session 4
**Push Day**
Thursday, Sep 17 · 6:05 PM
1h 3m · 2,640 kg · 11 sets · 12 PRs
Muscles: Chest 55%, Shoulders 27%, Triceps 18%
**Bench Press** · Chest · 3 sets · best 60 kg x 10 · PR: Heaviest weight, Best 1RM, Best set volume, Most reps
W. 20 kg x 10 (warm-up)
1. 60 kg x 10 🏆 Best 1RM, Best set volume, Most reps
2. 67.5 kg x 4 🏆 Heaviest weight
3. 62.5 kg x 8 @ RPE 9
**Incline Dumbbell Press** · Chest · 3 sets · best 55 lb x 10 · PR: Best 1RM, Best set volume, Most reps
1. 55 lb x 10 🏆 Best 1RM, Best set volume, Most reps
2. 55 lb x 10
3. 55 lb x 9
**Triceps Cable Pushdown** · Triceps · 2 sets · best 12.5 kg x 12 · PR: Heaviest weight, Best 1RM
1. 12.5 kg x 12 🏆 Heaviest weight, Best 1RM
2. 12.5 kg x 11
**Lateral Raise** · Shoulders · 3 sets · best 15 lb x 14 · PR: Best 1RM, Best set volume, Most reps
1. 15 lb x 14 🏆 Best 1RM, Best set volume, Most reps
2. 15 lb x 12
3. 15 lb x 12
This week: 2 workouts, 4,687 kg (−14% vs last week to date)
最後のメッセージでワークアウトが終了するため、ツールはこのページの上部にあるワークアウト PNG とともにこのカードを返します(end_session も同じ処理を行います)。PR は、tests/fixtures/chat.txt にある3つの過去のセッションと比較して記録されます。
チャットの読み取り方法
- セット:
60kg x 8、60 x 8、50lbs for 9、8 reps at 60kg、3x10 @ 90lb、60kg 3x8、12 reps(自重)。フラグ:warmup、drop set、to failure、rpe 9。 - エクササイズ:メッセージの冒頭で指定する(
incline db press 55 lb x 10)、開始を宣言する(now squats)、または後から名前を指定する(this is tricep cable pushdowns btw)方法があります。名前のないセットは、直前のエクササイズを引き継ぎます。 - 後から名前を指定すると、まだエクササイズ名が付いていないセットに適用されます。すべてのセットにすでに名前が付いている場合は、最後のセットと同じ重量で引き継がれている末尾のセット群に適用されます。新しいマシンに移ってから、1、2セット後にエクササイズ名を指定する一般的なケースに対応します。名前を指定する前に重量を変えた場合は、それより前のセットに
edit_last_set(exercise=...)を使ってください。 - エクササイズ名は、1つのエクササイズ名に統一されます。大文字小文字、複数形、
db/bbの略記、語順、補助語句(on the)、動作を変えない筋肉名は区別されません。そのため、tricep cable pushdowns、cable pushdown、triceps pushdowns on the cableは同じエクササイズになりますが、triceps curlとbiceps curlは別のエクササイズとして扱われます。ほかの名前はbodylog aliasで登録できます。 - コマンド:
same/one moreで直前のセットを繰り返し、done, 1h 5m/workout took 45 minでワークアウトを終了します。貼り付けられたログ内のエージェントの返信(Agent:、Assistant:、Claude:)はスキップされます。
数値の意味
- ボリュームは、ワーキングセットにおける重量 x 回数です。ウォームアップはカードに表示されますが、ボリューム、セット数、PR には含まれません。各セットには記録時の単位が表示されます。合計値はすべてのセットを正確に1つの単位に換算します。単位は、指定した
unit、それがなければ$BODYLOG_UNIT、それもなければ最も多くのセットで使われた単位になります。 - 筋肉の内訳は、主要な筋肉グループごとのワーキングセットの割合です。一般的なリフトを網羅する
muscles.pyの名前マップを使い、未知の名前は「その他」として数えます。割合の合計は常に100%です。 - 推定1RMにはEpleyの式、
weight x (1 + reps / 30)を使います。 - PR は、開始時刻がそれより前のセッションと比較して記録されます。最重量、推定1RMの最高値、セットボリューム(1セットでの重量 x 回数)の最高値、および過去に挙げた重量での最多回数です(エクササイズごとに1件、最大の伸びを記録)。エクササイズを初めて行ったときはPRが記録されないため、初回のワークアウトですべてのセットにPRが表示されることはありません。
- 週の項目では、今週と先週を同じ曜日・時刻までの範囲で比較するため、月曜日のワークアウトが90%減として表示されることはありません。
- 期間は終了時にユーザーが伝えた値です。セッションの開始時刻は、終了時刻からその期間を差し引いて設定されます。
MCP ツール
| ツール | 機能 |
|---|---|
log_set | オープン中のワークアウトにセットを追加します(必要に応じてワークアウトを開始します)。構造化フィールド、または text として生のメッセージを指定できます。そのセットで更新されたPRを返します。 |
edit_last_set | 最後のセットを修正または削除します。 |
end_session | ユーザーが指定した期間(「1h 5m」)でワークアウトを終了します。カードをテキストとPNGページで返します。 |
session_card | 任意のセッションのカードです。theme は dark、light、clear、style は full または story、unit は kg または lb です。 |
exercise_history、prs、weekly_volume | エクササイズごとの進捗、全期間の記録、週ごとのボリュームを表示します。 |
import_chat | 貼り付けたチャットログからワークアウトを遡って記録します。繰り返し実行しても安全です。 |
log_food | ユーザーの言葉から食事を記録するか、名前、バーコード、食品IDのいずれかで指定した食品を量またはラベルの数値とともに記録します。各項目のステータスとその日の合計を返します。 |
edit_food | 食品項目の量、食品、食事、数値を修正するか、削除します。 |
lookup_food | 記録せずに名前またはバーコードで検索します。 |
food_day | その日の項目を食事別に表示し、合計、目標、残り、連続記録、フラグ付き項目、ワークアウトを表示します。 |
food_card | その日のカードをテキストとPNGで表示します。theme、style は full または story です。 |
set_goals、streaks | 1日の目標、記録とトレーニングの連続記録を管理します。 |
CLI とライブラリ
bodylog log "bench 60kg x 8"
bodylog end "1h 5m" --title "Push Day"
bodylog eat "chicken breast 180g, 1.5 cups rice and broccoli"
bodylog food-fix 12 --grams 28
bodylog goals --kcal 2400 --protein 160
bodylog food-card --style story
bodylog --help
from bodylog import Store, log_text, log_food, day_summary, summary, render_png
from bodylog.foodcard import render_png as food_png
store = Store() # ~/.bodylog/log.db
log_text(store, "bench 60kg x 8")
log_food(store, "2 eggs, toast and a protein shake")
food_png(day_summary(store), "today.png", style="story")
Pythonを使う理由
MCP Python SDKではツールごとに数行のコードで済み、Pillowを使えばブラウザーなしでカードを描画でき、sqlite3 と urllib はPythonに同梱されています。実行時の依存関係はPillowと mcp です。カードにはInter(SIL Open Font License、src/bodylog/fonts/ に同梱)を使っているため、どこでも同じ見た目になります。
開発
uv sync
uv run pytest # offline: API calls replay recorded responses
uv run python scripts/render_examples.py # regenerate examples/ (offline)
テストでネットワークやリポジトリにアクセスすることはありません。tests/fixtures/http/ に実際のUSDAおよびOpen Food Factsのレスポンスが保存されており、テストで書き込まれるすべてのファイルは一時ディレクトリに保存されます。
構成:store.py(SQLite)、names.py、chatlog.py、stats.py、muscles.py、card.py(ワークアウト)、food.py(食事の解析、照合、合計、連続記録)、sources.py(USDAおよびOpen Food Facts)、foodcard.py(その日のカード)、cli.py、server.py(MCP)、data/common_foods.json(同梱のUSDAテーブル)。
クレジット
食品データ:USDA FoodData Central(パブリックドメイン)および Open Food Facts(Open Database License。製品データの出典はOpen Food Factsの貢献者として表示されています)。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。


