RUNSTR Fitness Skill
Give your AI agent access to your real health and fitness data. RUNSTR is a free fitness app that tracks workouts, habits, journal entries, mood, and steps — and stores encrypted backups on the Nostr protocol. This skill lets your bot read that data so it can help with fitness coaching, habit accountability, mood tracking, and health insights.
What your bot gets access to:
- - Workout history (running, walking, cycling, hiking, strength, yoga, etc.)
- Daily habits and streaks (quit smoking, daily meditation, etc.)
- Journal entries with mood and energy levels
- Daily step counts
- Which charity you support and reward routing
Setup: Getting Your Data to Your Bot
If you're already a RUNSTR user with backups enabled, skip to step 3.
1. Download RUNSTR (if you haven't)
- - iOS: Search "RUNSTR" on the App Store
- Android: Available on Zapstore or direct APK
- GitHub: https://github.com/RUNSTR (open source)
RUNSTR is free. You earn Bitcoin (sats) for working out.
2. Use the App
- - Create or import a Nostr identity (the app generates one for you)
- Track workouts, log habits, write journal entries
- Go to Settings > Backup and tap Backup to Nostr
This encrypts all your fitness data and publishes it to Nostr relays. Only you (with your private key) can read it.
3. Give Your Bot Your nsec
Your
nsec is your Nostr private key. Find it in RUNSTR under
Settings > Keys (or your Nostr key manager).
Tell your bot: "Here's my RUNSTR nsec: nsec1..."
Your bot uses the nsec to decrypt your encrypted fitness backup from Nostr. The nsec is never stored, logged, or transmitted — it's used only for the decryption step in your current session.
Why nsec and not npub? Your fitness data is encrypted. The public key (npub) can only see old public workout posts (if any). The private key (nsec) is needed to decrypt your habits, journals, mood, steps, and current workout history.
Privacy note: If you want a dedicated identity just for fitness data, create a new Nostr account in RUNSTR. Your fitness nsec doesn't have to be your main Nostr identity.
4. Keep Your Backup Fresh
Your bot sees whatever was in your last backup. After a week of new workouts, go to
Settings > Backup in RUNSTR and tap backup again to sync the latest data to Nostr.
For the Agent: How to Fetch RUNSTR Data
Everything below is instructions for the AI agent, not the user.
Prerequisites
INLINECODE0 (Nostr Army Knife) must be installed:
CODEBLOCK0
Relays
Always query these four relays (RUNSTR defaults):
CODEBLOCK1
Step 1: Decode the nsec
CODEBLOCK2
Step 2: Fetch Profile (Kind 0)
CODEBLOCK3
Step 3: Fetch Encrypted Backup (Kind 30078)
This is the primary data source.
CODEBLOCK4
If no backup found: Tell the user: "No backup found on Nostr. Open RUNSTR on your phone, go to Settings > Backup, and create one. Then try again."
If backup found but exportedAt is old: Warn the user that their backup is stale and recent data may be missing. Suggest they re-backup in the app.
Decrypt the Backup
The backup is NIP-44 self-encrypted and gzip-compressed.
Method 1: Using nak
CODEBLOCK5
Method 2: Node.js fallback
CODEBLOCK6
Backup Payload Structure
CODEBLOCK7
Field reference:
- -
workouts[].type: running, walking, cycling, hiking, strength, meditation, yoga, diet, swimming, rowing - INLINECODE3 : seconds
- INLINECODE4 : meters
- INLINECODE5 : "abstinence" (quitting something) or "positive" (building something)
- INLINECODE6 : great, good, neutral, low, bad
- INLINECODE7 : 1-5 scale
- INLINECODE8 : healthkit, health_connect, native
Step 4: Check for Legacy Public Workouts (Kind 1301)
Older users may have public workout events. Always check:
CODEBLOCK8
If found, parse tags array:
| Tag | Example |
|---|
| INLINECODE10 | INLINECODE11 |
| INLINECODE12 |
["distance", "5.2", "km"] |
|
duration |
["duration", "00:30:45"] |
|
calories |
["calories", "312"] |
|
avg_pace |
["avg_pace", "05:39", "min/km"] |
|
steps |
["steps", "8432"] |
|
team |
["team", "hrf"] |
Merge with backup data. Deduplicate by matching workout start times or IDs.
Step 5: Analyze and Present
Workout Summary: Total workouts, breakdown by activity, distance/duration/calories, frequency, personal bests.
Trends: Frequency changes, pace improvement, gaps, active days of week.
Habits: Current streaks, longest streaks, consistency rate.
Journal & Mood: Mood trend, energy averages, workout-mood correlation.
Steps: Daily average, weekly totals, trends.
Charity: Which team/charity, reward routing (user vs charity).
Step 6: Store Health Summary in Memory
Save a structured summary for future conversations so you don't re-query every time:
CODEBLOCK9
Coaching Mode
Once you have data, you can:
- - Recommend workouts based on history and goals
- Suggest rest days based on training load
- Check in on habit streaks
- Correlate mood with activity
- Track goals ("run 20 km this week")
- Remind based on usual workout schedule
Troubleshooting
| Problem | Solution |
|---|
| No backup found | User needs to open RUNSTR > Settings > Backup |
| Backup is stale |
User needs to re-backup in the app |
| Decryption fails | Wrong nsec, or try Method 2 (Node.js) |
| nak not installed |
go install github.com/fiatjaf/nak@latest |
| No Go installed | Use Method 2 (Node.js with NDK) |
| Empty workouts array | User hasn't tracked workouts yet |
| No habits/journal | User hasn't used those features in the app |
About RUNSTR
RUNSTR is a free, open-source fitness app for the Bitcoin/Nostr community. Track workouts, earn Bitcoin (sats) for exercising, support charities, and join fitness competitions. Your data is yours — stored on your device and backed up encrypted to Nostr.
- - Website: https://runstr.app
- GitHub: https://github.com/RUNSTR
- Rewards: 50 sats per daily workout via Lightning address
- PPQ.AI credits: Earn AI credits for working out
RUNSTR 健身技能
让您的AI代理访问您真实的健康和健身数据。RUNSTR是一款免费的健身应用,可追踪锻炼、习惯、日记、情绪和步数,并在Nostr协议上存储加密备份。此技能让您的机器人能够读取这些数据,从而帮助进行健身指导、习惯问责、情绪追踪和健康洞察。
您的机器人可以访问的内容:
- - 锻炼历史(跑步、步行、骑行、徒步、力量训练、瑜伽等)
- 日常习惯和连续记录(戒烟、每日冥想等)
- 带有情绪和能量水平的日记条目
- 每日步数
- 您支持的慈善机构和奖励路由
设置:将您的数据传输到机器人
如果您已经是RUNSTR用户并启用了备份,请跳至第3步。
1. 下载RUNSTR(如果尚未下载)
- - iOS:在App Store搜索RUNSTR
- Android:可在Zapstore或直接APK获取
- GitHub:https://github.com/RUNSTR(开源)
RUNSTR是免费的。您可以通过锻炼赚取比特币(聪)。
2. 使用应用
- - 创建或导入Nostr身份(应用会为您生成一个)
- 追踪锻炼、记录习惯、撰写日记条目
- 前往设置 > 备份,点击备份到Nostr
这将加密您所有的健身数据并发布到Nostr中继。只有您(使用您的私钥)才能读取。
3. 将您的nsec提供给机器人
您的
nsec是您的Nostr私钥。在RUNSTR的
设置 > 密钥(或您的Nostr密钥管理器)中找到它。
告诉您的机器人:这是我的RUNSTR nsec:nsec1...
机器人使用nsec从Nostr解密您加密的健身备份。nsec不会被存储、记录或传输——它仅用于当前会话中的解密步骤。
为什么用nsec而不是npub? 您的健身数据是加密的。公钥(npub)只能看到旧的公开锻炼帖子(如果有的话)。需要私钥(nsec)才能解密您的习惯、日记、情绪、步数和当前锻炼历史。
隐私说明: 如果您想为健身数据使用专用身份,请在RUNSTR中创建一个新的Nostr账户。您的健身nsec不必是您的主要Nostr身份。
4. 保持备份更新
您的机器人会看到您上次备份的内容。经过一周的新锻炼后,前往RUNSTR的
设置 > 备份,再次点击备份以将最新数据同步到Nostr。
针对代理:如何获取RUNSTR数据
以下所有内容都是针对AI代理的说明,而非用户。
先决条件
必须安装nak(Nostr瑞士军刀):
bash
go install github.com/fiatjaf/nak@latest
中继
始终查询这四个中继(RUNSTR默认):
wss://relay.damus.io wss://relay.primal.net wss://nos.lol wss://relay.nostr.band
步骤1:解码nsec
bash
hex_sk=$(nak decode nsec1...)
hexpk=$(nak key public $hexsk)
步骤2:获取个人资料(种类0)
bash
nak req -k 0 -a $hex_pk -l 1 \
wss://relay.damus.io wss://nos.lol | \
jq -r .content | fromjson | {name, about, lud16, picture}
步骤3:获取加密备份(种类30078)
这是主要数据源。
bash
nak req -k 30078 -a $hex_pk -t d=runstr-workout-backup -l 1 \
wss://relay.damus.io wss://relay.primal.net wss://nos.lol wss://relay.nostr.band
如果未找到备份: 告诉用户:在Nostr上未找到备份。请在手机上打开RUNSTR,前往设置 > 备份,创建一个备份。然后重试。
如果找到备份但exportedAt较旧: 警告用户备份已过时,可能缺少近期数据。建议他们在应用中重新备份。
解密备份
备份是NIP-44自加密并经过gzip压缩的。
方法1:使用nak
bash
content=$(nak req -k 30078 -a $hex_pk -t d=runstr-workout-backup -l 1 \
wss://relay.damus.io wss://nos.lol | jq -r .content)
解密(NIP-44自解密:用户对自己的公钥)
decrypted=$(echo $content | nak encrypt --sec $hex
sk $hexpk --decrypt)
解压缩(先检查是否有[compression, gzip]标签)
echo $decrypted | base64 -d | gunzip | jq .
方法2:Node.js备用方案
javascript
// /tmp/decrypt-runstr.mjs — 运行方式:node /tmp/decrypt-runstr.mjs
import { gunzipSync } from zlib;
import NDK, { NDKPrivateKeySigner } from @nostr-dev-kit/ndk;
const signer = new NDKPrivateKeySigner(process.argv[2]);
const user = await signer.user();
const decrypted = await signer.decrypt(user, process.argv[3]);
try {
console.log(gunzipSync(Buffer.from(decrypted, base64)).toString());
} catch {
console.log(decrypted);
}
备份负载结构
json
{
version: 1,
exportedAt: 2025-01-15T10:30:00Z,
appVersion: 1.6.5,
workouts: [
{
id: uuid,
type: running,
startTime: 2025-01-15T07:00:00Z,
endTime: 2025-01-15T07:35:00Z,
duration: 2100,
distance: 5200,
calories: 312
}
],
habits: [
{
id: id,
name: No Smoking,
type: abstinence,
currentStreak: 45,
longestStreak: 45,
checkIns: [2025-01-15, 2025-01-14]
}
],
journal: [
{
id: uuid,
date: 2025-01-15,
content: Great morning run today.,
mood: great,
energy: 4,
tags: [morning, outdoors]
}
],
stepHistory: [
{ date: 2025-01-15, steps: 12450, source: healthkit }
],
preferences: {
unitSystem: imperial,
selectedCharity: hrf
}
}
字段参考:
- - workouts[].type:running, walking, cycling, hiking, strength, meditation, yoga, diet, swimming, rowing
- workouts[].duration:秒
- workouts[].distance:米
- habits[].type:abstinence(戒除某事)或positive(建立某事)
- journal[].mood:great, good, neutral, low, bad
- journal[].energy:1-5等级
- stepHistory[].source:healthkit, health_connect, native
步骤4:检查旧版公开锻炼(种类1301)
老用户可能有公开的锻炼事件。始终检查:
bash
nak req -k 1301 -a $hex_pk -l 50 \
wss://relay.damus.io wss://relay.primal.net wss://nos.lol wss://relay.nostr.band
如果找到,解析tags数组:
| 标签 | 示例 |
|---|
| exercise | [exercise, running] |
| distance |
[distance, 5.2, km] |
| duration | [duration, 00:30:45] |
| calories | [calories, 312] |
| avg
pace | [avgpace, 05:39, min/km] |
| steps | [steps, 8432] |
| team | [team, hrf] |
与备份数据合并。通过匹配锻炼开始时间或ID进行去重。
步骤5:分析和呈现
锻炼摘要: 总锻炼次数、按活动分类、距离/时长/卡路