Spare 创意工坊 · 开发者

Spare 眼镜应用开发者指南

给 Spare 智能眼镜写小应用:装到眼镜上就能用,不用刷机。界面、计时、动画都在眼镜本地运行,手机只帮你取声明过的数据。

任何 Spare 账号登录后都可以发布应用,不需要申请。

快速开始

  1. 登录:在 Spare App「创意工坊」右上角点 +,或在电脑上打开 spare.cool/dev,用 Spare 账号登录。第一次登录会自动成为开发者,handle 取自你的昵称(建应用前可以改),应用 id 是 dev.<handle>.<名字>。
  2. 复制给你的 AI:点「让 AI 帮我做」→「复制给你的 AI」,粘给 Codex、Claude Code、Cursor 或 ChatGPT。它会装上你的专属开发者 MCP(一个地址,当密码对待)。
  3. 说出你的想法:例如「给眼镜做一个番茄钟并发布到 Spare 创意工坊」。AI 会建仓库、读模板里的规则、写代码。
  4. 模拟器预览:AI 调用 simulate,拿回眼镜画面截图,自己检查文字有没有被裁。
  5. 装到自己的眼镜:AI 调用 install_on_my_glasses,你在 App「创意工坊 › 开发者」里点「安装」(需要打开开发者模式)。
  6. 提交审核:你说「可以发布了」,AI 调用 submit_for_review。自动检查和 AI 初审几十秒内完成,然后由 Spare 人工终审。
  7. 上架:通过后所有用户都能在创意工坊看到并安装。

也可以不用 AI:网页控制台新建应用、用 git 或 spare 命令行推代码,或在 App 里「上传应用包 (.spa)」。

应用结构

my-app/
├── app.json      清单 + 界面(必需)
├── main.ss       SpareScript 脚本(必需)
├── icon.png      44×44 灰度图标(列表里 2×3 格子用)
├── assets/       可选图片:PNG,宽为偶数,≤ 128×128
└── scenarios/    模拟器场景(每次云端构建都会跑)

app.json

字段说明
id平台分配的 dev.<handle>.<slug>,不要改
name列表里的名字,≤ 23 字节(约 7 个汉字)
version_name展示版本,semver,如 1.0.0
version不用管:平台按构建号自动写(眼镜要求每次更新变大)
data_version持久数据格式版本;变了,更新时眼镜清掉旧数据
description商店说明
permissions权限白名单,见下
requests让手机代取的数据,见「手机数据桥」
ui界面元素数组

界面元素

最多 48 个。公共字段:id(脚本里直接用这个名字)、type、x y w h、hidden。

类型字段
textsize 12–96、bold、align(left / center / right)、text(≤ 63 字节)、gray
rectradius、gray(填充)、border(> 0 只描边)、children(坐标相对它)
bar进度条:value 0–100、gray、track(底色,默认 55)、radius
imagesrc = assets/ 里的文件名;不写 src 是空框,image(el, -1) 放手机传来的图

main.ss

SpareScript 写法像 JavaScript,只有 32 位整数 和 短字符串(≤ 63 字节)两种值。

var left = 1500;                 // 全局变量(≤ 64 个)
persist var done = 0;            // 持久变量:关掉、重启后还在;改完 save()
fn fmt(s) { return pad(s / 60, 2) + ":" + pad(s % 60, 2); }

on open()    { text(time, fmt(left)); }
on crown(d)  { left = clamp(left + d * 60, 60, 3600); text(time, fmt(left)); }
on click()   { timer(0, 1000, 1); }
on timer(id) { left -= 1; text(time, fmt(left)); }

事件:open close crown(d) click timer(id) data(seq)。语句:var、赋值、if/else、while、break、continue、return。

内建作用
text show gray move size value image改界面
anim_x anim_opa anim_scale本地动画(≤ 2000 ms)
timer(id, ms, repeat)计时器 0–3,≥ 100 ms;ms = 0 停止
now() clock() seconds()毫秒计时 / 当天分钟数 / 当前秒
str num len sub pad字符串
min max clamp abs rand数学
data request connected手机数据桥
battery save exit电量 / 写盘 / 退出

权限白名单

权限用途审核
network:<域名>http_json 请求的主机;必须是公网域名,URL 必须 https人工确认主机
locationlocation / weather 请求必须人工审
notificationsnotify_count 请求—
microphone spare_notes眼镜笔记相关必须人工审

只申请真正用到的权限。

眼镜画面与交互规范

手机数据桥

眼镜不联网。应用在 requests 里逐条声明数据,眼镜只说「第几个请求 + ≤ 10 字节参数」,URL 永远来自 app.json。

"permissions": ["network:api.example.com"],
"requests": [{ "name": "quote", "kind": "http_json",
  "url": "https://api.example.com/q?s={arg}", "fields": { "px": "price" } }]
on open()    { request(quote, "AAPL"); }
on data(seq) {
  if (data("_err") != "") { text(px, "--"); return; }
  text(px, data("px"));
}
kind返回权限
http_jsonfields 映射的键network:<主机>
locationlat lon citylocation
weathertemp text iconlocation
time_synctz—
notify_countcountnotifications

失败时只回一个键 _err(bad / kind / perm / auth / net)。手机限频 ≤ 1 次/秒。离线时 data() 是上次的缓存,connected() 为假,记得显示「等待连接」。

调试与模拟器

审核规则

上架前都要经过:自动检查 → AI 初审 → Spare 人工终审(通常 1 个工作日)。被打回的意见会写进你的仓库 issue,AI 用 get_review_feedback 就能读到。

常见拒审原因:

用户可以举报应用;违规应用会被下架。

版本与渠道

渠道谁能看到签名
dev只有你自己的手机(开发者区)平台开发者密钥
beta测试者创意工坊密钥(审核通过后)
stable所有人创意工坊密钥(审核通过后)

完整示例:喝水提醒

表冠调目标杯数,单击记一杯,进度条显示完成度,数字关掉也记得;完成目标后再单击从头开始。

app.json:

{
 "id": "dev.yourname.water",
 "name": "喝水",
 "version_name": "1.0.0",
 "version": 1,
 "data_version": 1,
 "description": "单击记一杯水,转表冠调每天目标;完成后再单击从头开始。",
 "permissions": [],
 "requests": [],
 "ui": [
  { "id": "big", "type": "text", "x": 0, "y": 30, "w": 540, "h": 100, "size": 88, "bold": true, "align": "center", "text": "0/8" },
  { "id": "bar", "type": "bar", "x": 70, "y": 140, "w": 400, "h": 10, "radius": 5, "value": 0 },
  { "id": "hint", "type": "text", "x": 0, "y": 160, "w": 540, "h": 30, "size": 22, "align": "center", "gray": 130, "text": "单击记一杯 · 转表冠调目标" }
 ]
}

main.ss:

persist var cups = 0;
persist var goal = 8;

fn draw() {
  text(big, str(cups) + "/" + str(goal));
  value(bar, min(100, cups * 100 / goal));
  if (cups >= goal) { text(hint, "完成了!单击从头开始"); } else { text(hint, "单击记一杯 · 转表冠调目标"); }
}

on open()   { draw(); }
on click()  {
  if (cups >= goal) { cups = 0; } else { cups += 1; anim_opa(big, 80, 255, 300); }
  save();
  draw();
}
on crown(d) { goal = clamp(goal + d, 1, 20); save(); draw(); }

scenarios/smoke.txt:

open
shot open
click
click
tick 400
shot two
crown +1
shot goal

常见问题

要申请才能发布吗? 不用。登录 Spare 账号就是开发者。

handle 能改吗? 建第一个应用之前可以(网页控制台或 App 开发者区),之后就固定了,因为应用 id 和仓库地址里用到它。

AI 说调不到 MCP? Claude Code 装好后要新开一个会话(或 /mcp 重连)。地址失效了就再「复制给你的 AI」一次,旧地址会作废。

为什么我的应用在眼镜上「应用出错」? 超了每次事件的指令数或界面调用数。检查循环,不要在一次事件里改太多元素。

能收费吗? 暂时都免费。

有数量限制吗? 每个账号最多 30 个应用,每天新建 5 个、提交审核 10 次,每小时构建 60 次。