@homie-rocks/studio 0.48.4 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/app-starters/gathering/README.md +4 -0
- package/app-starters/gathering/app.json +162 -0
- package/app-starters/gathering/index.html +3 -0
- package/app-starters/gathering/map/main.json +1 -0
- package/app-starters/gathering/src/move.ts +3 -0
- package/app-starters/gathering/src/rules.ts +21 -0
- package/app-starters/gathering/src/view.ts +74 -0
- package/app-starters/giving/README.md +5 -0
- package/app-starters/giving/app.json +162 -0
- package/app-starters/giving/index.html +3 -0
- package/app-starters/giving/map/main.json +1 -0
- package/app-starters/giving/src/move.ts +3 -0
- package/app-starters/giving/src/rules.ts +21 -0
- package/app-starters/giving/src/view.ts +74 -0
- package/app-starters/jobs/README.md +4 -0
- package/app-starters/jobs/app.json +162 -0
- package/app-starters/jobs/index.html +3 -0
- package/app-starters/jobs/map/main.json +1 -0
- package/app-starters/jobs/src/move.ts +3 -0
- package/app-starters/jobs/src/rules.ts +21 -0
- package/app-starters/jobs/src/view.ts +74 -0
- package/app-starters/quiz/README.md +4 -0
- package/app-starters/quiz/app.json +162 -0
- package/app-starters/quiz/index.html +3 -0
- package/app-starters/quiz/map/main.json +1 -0
- package/app-starters/quiz/src/move.ts +3 -0
- package/app-starters/quiz/src/rules.ts +21 -0
- package/app-starters/quiz/src/view.ts +74 -0
- package/app-starters/welcome/app.json +25 -2
- package/app-starters/welcome/index.html +1 -1
- package/app-starters/welcome/src/view.ts +20 -8
- package/bin/homie-studio.mjs +20 -16
- package/functions/FUNCTIONS.md +1 -1
- package/guides/app/SKILL.md +178 -0
- package/guides/art/SKILL.md +154 -0
- package/guides/art/references/RIGHTS.md +20 -0
- package/guides/art/scripts/art.mjs +308 -0
- package/guides/models/SKILL.md +198 -0
- package/guides/models/references/RIGHTS.md +46 -0
- package/guides/models/references/models.json +175 -0
- package/guides/models/scripts/models.mjs +483 -0
- package/guides/music/SKILL.md +197 -0
- package/guides/music/references/COMPOSITION.md +59 -0
- package/guides/music/references/GAME-AUDIO.md +50 -0
- package/guides/music/references/RIGHTS.md +43 -0
- package/guides/music/scripts/lib/audio.mjs +258 -0
- package/guides/music/scripts/lib/eleven.mjs +260 -0
- package/guides/music/scripts/lib/studio.mjs +147 -0
- package/guides/music/scripts/music.mjs +644 -0
- package/guides/parts/SKILL.md +158 -0
- package/guides/plan/SKILL.md +126 -0
- package/guides/plan/references/CODEX.md +105 -0
- package/guides/plan/references/INTERVIEW.md +86 -0
- package/guides/playtest/SKILL.md +205 -0
- package/guides/playtest/references/METHOD.md +124 -0
- package/guides/playtest/references/REVIEWER.md +78 -0
- package/guides/playtest/scripts/lib/exit.mjs +31 -0
- package/guides/playtest/scripts/lib/judge.mjs +502 -0
- package/guides/playtest/scripts/lib/pixels.mjs +128 -0
- package/guides/playtest/scripts/lib/preflight.mjs +69 -0
- package/guides/playtest/scripts/playtest.mjs +870 -0
- package/guides/shop/SKILL.md +153 -0
- package/guides/sound/SKILL.md +156 -0
- package/guides/sound/references/GAME-SOUND.md +100 -0
- package/guides/sound/references/SCORE.md +131 -0
- package/guides/sound/references/TRAPS.md +93 -0
- package/guides/sound/scripts/lib/measure.mjs +252 -0
- package/guides/sound/scripts/lib/score.mjs +415 -0
- package/guides/sound/scripts/lib/sfx.mjs +222 -0
- package/guides/sound/scripts/lib/synth.mjs +509 -0
- package/guides/sound/scripts/sound.mjs +520 -0
- package/guides/studio-setup/SKILL.md +419 -0
- package/guides/style/SKILL.md +105 -0
- package/lib/app-needs.mjs +63 -0
- package/lib/authoring-guides.mjs +5 -4
- package/lib/build.mjs +5 -4
- package/lib/check-site.mjs +6 -6
- package/lib/check.mjs +18 -5
- package/lib/codex.mjs +95 -18
- package/lib/decisions.mjs +9 -7
- package/lib/dev.mjs +4 -2
- package/lib/doctor.mjs +1 -1
- package/lib/handoff.mjs +13 -8
- package/lib/mcp-tools.mjs +19 -17
- package/lib/mcp.mjs +1 -1
- package/lib/parts.mjs +6 -6
- package/lib/scaffold.mjs +45 -11
- package/lib/shop-links.mjs +2 -2
- package/lib/shop.mjs +5 -3
- package/lib/studio.mjs +7 -6
- package/lib/template-history.json +84 -0
- package/package.json +4 -4
- package/shop/SHOP.md +4 -0
- package/shop/shop.ts +4 -4
- package/worker/app-format.mjs +1 -1
- package/worker/build-id.mjs +1 -1
- package/worker/functions-schema.mjs +15 -0
- package/worker/index.mjs +2 -1
- package/worker/parts.mjs +4 -4
- package/worker/shop-page.mjs +22 -16
- package/worker/shop-rules.mjs +4 -3
- package/worker/shop.mjs +6 -2
- package/worker/site.mjs +4 -2
- package/worker/version.mjs +1 -1
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: studio-setup
|
|
3
|
+
description: "Set up a Homie studio (one repository with games/, apps/, music/, videos/ and posts/, and a site with public game rooms on the studio's own Cloudflare) with the AI handling setup and defaults: setup status first (accounts and tools, what each unlocks, the exact fix), choose editable defaults, plan the requested game or app, build it with progress the person can watch, playtest, put it online and list it in the homie.rocks directory. Use when someone asks to set up, create or start a studio or a game studio, asks what they need or whether they are set up, or says \"set up a game studio called X\" (with or without \"and make a multiplayer game\")."
|
|
4
|
+
compatibility: Node 22. Reads, and offers only when a feature needs them, each provider's own tools (Wrangler (Cloudflare, pinned in the studio), the GitHub CLI, the ElevenLabs CLI, a fal key, Ollama for Clef on this computer, and as an option the stripe CLI's Stripe Projects). The plugin's providers.json lists them.
|
|
5
|
+
metadata:
|
|
6
|
+
providers: cloudflare github elevenlabs fal stripe ollama
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
**Apps:** For a business, venue, cause or customer app, follow the `app` skill: `apps/<id>/app.json`, one morphing screen, roles and parts. Reuse these engines and workflows; do not impose game rounds, scores, bots, a game demo or page navigation. The app check proves shared actions and reconnect; app stores use the same standalone command.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Set up a studio
|
|
13
|
+
|
|
14
|
+
A Homie studio is ONE folder the person can see and open: `AGENTS.md` (+ `CLAUDE.md`
|
|
15
|
+
importing it), `games/`, `apps/`, `music/`, `videos/`, `posts/`, and a site: a Cloudflare Worker with a
|
|
16
|
+
D1 database and the Table/Lobby Durable Objects that serve the studio's pages and its public
|
|
17
|
+
game rooms from the studio's **own** Cloudflare account, on Cloudflare. The
|
|
18
|
+
code comes from `@homie-rocks/studio`, pinned in the studio's `package.json`. The person never
|
|
19
|
+
types a command: you run everything, and they approve what matters (Cloudflare, once, in their
|
|
20
|
+
browser). Homie for studios is in **beta**.
|
|
21
|
+
|
|
22
|
+
## The new-studio checklist
|
|
23
|
+
|
|
24
|
+
Carry the request through without waiting between setup, planning, building and checking.
|
|
25
|
+
Show brief progress, not a form. Choose the name from the request, otherwise "My Studio".
|
|
26
|
+
The demo and small-change lesson below are optional, only for someone who asks for a tutorial.
|
|
27
|
+
Plan from the premise with sensible engineering and design defaults; the person changes them later
|
|
28
|
+
by asking. A business or non-profit may need an app or site: do not force a game or game interview.
|
|
29
|
+
Use phone and computer controls, a small first version, local sound and CC0 art. New games
|
|
30
|
+
use rules plus view with the server as host; read the game skill and RULES.md before coding. Build with one agent
|
|
31
|
+
unless parallel work was requested. Keep provider approvals, paid budgets and required host holds.
|
|
32
|
+
An existing request to go live or list is authorization; do not ask again outside those holds.
|
|
33
|
+
|
|
34
|
+
**An app first:** For an app request, run `app new <id>` in the empty studio, build the requested roles and shared action, and run its app check. Give the `/<id>/open` link as soon as it passes; continue to the requested publish flow without a game demo or interview. The same keyless shop is optional, with its visible Shop control when something is for sale.
|
|
35
|
+
|
|
36
|
+
**A Play link first.** Build the game to the point where it plays, run the two-browser `check`, and the moment
|
|
37
|
+
it passes tell the person, with the link they can open now (`http://127.0.0.1:8787/<id>/play`, two tabs for two
|
|
38
|
+
players): a first run should have someone playing in minutes, not after an hour of polish. Only then go on
|
|
39
|
+
to sound, art, the playtest's fixes and the landing page, saying in a line what you are doing next.
|
|
40
|
+
|
|
41
|
+
## 0. Setup status, first
|
|
42
|
+
|
|
43
|
+
Before anything is made, and whenever the person asks what they need, whether they are set up, or
|
|
44
|
+
is waiting (a usage limit resetting is a good time), run the setup status. It only reads, takes a
|
|
45
|
+
few seconds, and never prints a key:
|
|
46
|
+
|
|
47
|
+
1. With the Homie connector (the Homie MCP tool `studio_scaffold` is in your tool list), call it with the
|
|
48
|
+
studio's name (if they have not named it yet, use "My Studio" for now; it only reads). It returns the
|
|
49
|
+
exact pinned command, like
|
|
50
|
+
`npx -y @homie-rocks/studio@<version> new "<folder>" --name "<Name>" --homie https://homie.rocks`,
|
|
51
|
+
and a numbered list of next steps: this checklist decides the order, not that list. **Without the
|
|
52
|
+
connector, go on** ("Without the connector" below): the toolkit is `@homie-rocks/studio` on npm, and
|
|
53
|
+
`@latest` is its version here.
|
|
54
|
+
2. Run that same package with `setup status` instead of `new ...`:
|
|
55
|
+
`npx -y @homie-rocks/studio@<version> setup status --connector yes --json` (inside a studio:
|
|
56
|
+
`npx --no-install homie-studio setup status --connector yes --json`). If it does not know
|
|
57
|
+
`setup status` (a toolkit older than 0.11.0 calls it unknown, or asks for a studio first), run `npx -y @homie-rocks/studio@latest setup status
|
|
58
|
+
--connector yes --json` for the status only (it only reads). `--connector yes` because
|
|
59
|
+
the Homie tools are in your tool list; if `studio_scaffold` is not there, say `--connector no`
|
|
60
|
+
and run it from `@latest`. In Codex add `--client codex`, in Grok Build `--client grok`: the status then
|
|
61
|
+
says whether Homie's holds are on (item 6), and when another MCP server has taken the connector's name.
|
|
62
|
+
3. Use the status internally. Report the current work in plain words and only the single next
|
|
63
|
+
action that actually needs the person. You run `fix.run`; a provider sign-in is their browser
|
|
64
|
+
approval. Do not make them understand runtimes, connectors, ids or optional providers.
|
|
65
|
+
|
|
66
|
+
4. **Never block on an optional row.** Say what it unlocks and that it can wait until that feature is
|
|
67
|
+
wanted; the skill that needs it (`music`, `art`, `video`) offers it then. A "do this now" row you can
|
|
68
|
+
do (`fix.run`, like `npx wrangler login` or `brew install ffmpeg`): run it yourself as part of setup. A row the person does on their own (`fix.open`) can be done any time, even while they wait
|
|
69
|
+
for something else: give them the link. The optional "Clef on this computer" row is a large download:
|
|
70
|
+
say its size first (`ollama pull clef-flash`, about 11 GB) and run it only after their yes.
|
|
71
|
+
5. Run it again whenever they say they did something, and tick the row.
|
|
72
|
+
6. **Homie's holds (Codex, Grok Build).** With `--client` the status has a `holds` row: whether Homie's
|
|
73
|
+
hooks ran just now in this app (`"on": true`). When it is off, say so in one sentence in this first reply,
|
|
74
|
+
with the row's fix. In Codex: "Homie's holds are off in this session: open `/hooks` and trust Homie's
|
|
75
|
+
three hooks. Until then I'll ask you before a deploy, a Cloudflare change, a paid call or a model
|
|
76
|
+
download." In Grok Build: "Homie's holds are off in this session: install the Homie plugin again with
|
|
77
|
+
`--trust` and start a new session. Until then I'll ask you before a deploy, a Cloudflare change, a paid
|
|
78
|
+
call or a model download." Then
|
|
79
|
+
do ask, every time, also when the app approves commands for you. When it is on, say nothing about it and
|
|
80
|
+
change nothing: the hooks hold what they hold. A status with no `holds` row in Codex or Grok (a toolkit
|
|
81
|
+
before 0.30.2) cannot tell: say the sentence anyway.
|
|
82
|
+
|
|
83
|
+
**Without the connector, with a shell: go on.** A studio is made, checked, put online and listed with the
|
|
84
|
+
studio's own commands; the connector is not needed for any of it. When the Homie tools are not in your tool
|
|
85
|
+
list and you can run commands:
|
|
86
|
+
|
|
87
|
+
- Say it once, in one line: "The Homie connector is not connected in this app, so I'm making the studio with
|
|
88
|
+
its own commands. Connected, it adds the homie.rocks directory search, the cards
|
|
89
|
+
where an app draws them, and notes to Homie."
|
|
90
|
+
- The status is `npx -y @homie-rocks/studio@latest setup status --connector no --json`. Its connector row
|
|
91
|
+
says why when it can tell: another MCP server named `homie` is set up in this app and has taken the name
|
|
92
|
+
the plugin's connector uses. Its `fix.run` adds Homie's connector under its own name: run it yourself and never wait for it.
|
|
93
|
+
- The studio is `npx -y @homie-rocks/studio@latest new <folder> --name "<Name>"` (step 1), and from then on
|
|
94
|
+
`npx --no-install homie-studio …` inside it.
|
|
95
|
+
- Where a step names a Homie MCP tool, run the command the same step names beside it (`game new`,
|
|
96
|
+
`deploy`, `publish`, `stats`). Tell Homie is the connector's `homie_feedback` (in Claude Code also
|
|
97
|
+
`/feedback`): where neither is here, make no offer.
|
|
98
|
+
|
|
99
|
+
**Stop only when there is neither** the Homie tools nor a way to run a command. Then say exactly how to add
|
|
100
|
+
the connector in that app, and stop: Claude Code, `/plugin`, install or enable "homie" (marketplace
|
|
101
|
+
`homie-rocks/homie`), and `/mcp` shows it connected; Codex, `codex plugin marketplace add homie-rocks/homie`
|
|
102
|
+
then `codex plugin add homie@homie` and a new session; Grok Build, `grok plugin install
|
|
103
|
+
homie-rocks/homie#plugins/homie` and a new session; the Claude app, Grok chat or another app with connectors,
|
|
104
|
+
a custom connector at `https://homie.rocks/mcp`.
|
|
105
|
+
|
|
106
|
+
**Each provider's own tools, lazily.** Homie works through each provider's own CLI, plugin or MCP
|
|
107
|
+
server (Wrangler for Cloudflare, the GitHub CLI, ElevenLabs' CLI, fal's MCP server), never a copy of
|
|
108
|
+
their code: the plugin's `providers.json` lists them, with what stays Homie's (budgets and receipts,
|
|
109
|
+
the kids rules, the owner's one-tap asks, secrets never in the chat, the rights notes). Offer one only
|
|
110
|
+
when the person wants what it unlocks, in the skill that needs it; you install required tools and they sign in on the provider's own page.
|
|
111
|
+
|
|
112
|
+
**The status line (Claude Code only).** When requested: `npx --no-install homie-studio statusline --install` (`--remove` takes it away). Claude Code
|
|
113
|
+
reads the setting from the folder it was started in: if that is the folder above the studio (you made the
|
|
114
|
+
studio as a subfolder), add `--project <that folder>`. It never replaces a status line they already have;
|
|
115
|
+
if it says so, leave theirs. Never turn it on unasked. In Claude Code 2.1.287 or later the Homie mod (part
|
|
116
|
+
of this plugin) already draws the studio's band above the prompt and the Studio pane (`/studio`), so offer
|
|
117
|
+
the status line only to someone who wants the line under the prompt as well.
|
|
118
|
+
|
|
119
|
+
**Homie's holds in Codex.** In Codex, Homie's hooks hold what the mod holds in Claude Code: an edit to a
|
|
120
|
+
file `studio.json` `"protect"` lists, a production deploy, a change to the studio's Cloudflare account
|
|
121
|
+
outside its deploy, a paid call past the budget or whose cost cannot be read first, and a Clef model
|
|
122
|
+
download; they refuse what the mod refuses, and take secrets out of what you read. Codex runs a plugin's
|
|
123
|
+
hooks only after the person trusts them once: after installing Homie, tell them to open `/hooks` and
|
|
124
|
+
trust Homie's three (until then nothing is held, so ask before each of those yourself). Never assume they
|
|
125
|
+
are on: the setup status says which it is (item 6 above). A held call comes
|
|
126
|
+
back refused with a code, and the person sees what it holds: say in a sentence what it would do and ask.
|
|
127
|
+
They answer in their own message, `proceed <code>` (that exact call goes through once) or `cancel
|
|
128
|
+
<code>`; then run exactly the same call again, or not at all. Never write that answer yourself, in a
|
|
129
|
+
command or a file: only the person's own message counts. `node <this plugin's folder>/hooks/codex.mjs check
|
|
130
|
+
-- <command>` (the folder above `skills/`) says what Homie would do with a command, and runs nothing.
|
|
131
|
+
|
|
132
|
+
**Homie's holds in Grok.** In Grok Build, Homie's hooks (`hooks/grok.json`, deciding with the module the mod
|
|
133
|
+
and the Codex hooks ask, `hooks/lib/holds.mjs`) hold and refuse the same calls as in Codex, and take secrets out
|
|
134
|
+
of what you read. Grok runs a plugin's hooks only once the person has trusted the plugin (`grok plugin install
|
|
135
|
+
homie-rocks/homie#plugins/homie --trust`, then a new session; `/hooks` lists them). Never assume they are on:
|
|
136
|
+
the setup status with `--client grok` says which it is (item 6 above), and while it says off, before a
|
|
137
|
+
production deploy, a Cloudflare change outside that deploy, a paid call, a model download or an edit to a file
|
|
138
|
+
`studio.json` `"protect"` lists, say what it would do in one sentence and wait for the person's yes, also when
|
|
139
|
+
Grok approves commands by itself; and never repeat a key or a token you read. A held call comes back denied
|
|
140
|
+
with a code, and the person answers `proceed <code>` or `cancel <code>` in their own message, as in Codex; then
|
|
141
|
+
run exactly the same call again, or not at all. Never write that answer yourself. In Grok chat (the connector
|
|
142
|
+
only, no plugin) there are no hooks: ask, every time. `node <this plugin's folder>/hooks/grok.mjs check --
|
|
143
|
+
<command>` says what Homie would hold, and runs nothing.
|
|
144
|
+
|
|
145
|
+
## Grok and Grok Bot
|
|
146
|
+
|
|
147
|
+
In Grok Build the Homie plugin brings the connector (its tools read `homie__studio_scaffold` and the like);
|
|
148
|
+
its hooks hold once the plugin is trusted (above). Say `--client grok` to the setup status. In Grok chat the connector is
|
|
149
|
+
`https://homie.rocks/mcp`, once the person has added it. Use the one that is here; with neither, and a shell,
|
|
150
|
+
go on without it (step 0). Do not send the person to Claude's GitHub app, to claude.ai/code, or to a button
|
|
151
|
+
that only says "Connect to Claude". The studio's first-run band says **Connect this chat**.
|
|
152
|
+
|
|
153
|
+
- **Cloudflare** stays one tap on Cloudflare's own page. Grok has no Cloudflare connector and must never
|
|
154
|
+
ask for a token. On a phone, the setup card's "Make the studio on Cloudflare" is that tap. On a computer,
|
|
155
|
+
`npx wrangler login` opens the same approval.
|
|
156
|
+
- **This computer** is a Grok Bot, or Grok Build with a folder. Run the checklist here. When the chat has a
|
|
157
|
+
setup id `hs_…`, check in once from the studio's own repository:
|
|
158
|
+
`npx --no-install homie-studio setup attach <hs_…> --client grok`. That tells the directory Grok works in
|
|
159
|
+
this repository. It does not need Claude's GitHub app. GitHub, when this chat already has it, is enough
|
|
160
|
+
to push the branch and open the pull request.
|
|
161
|
+
- **A build** the chat opened (`hb_…`): `npx --no-install homie-studio handoff <hb_…> --client grok`. The
|
|
162
|
+
session fetches the brief itself. There is no Claude Code window to open, and no second session to start.
|
|
163
|
+
|
|
164
|
+
## 1. The studio
|
|
165
|
+
|
|
166
|
+
Use the requested name, their business name, or "My Studio"; it can change later.
|
|
167
|
+
Then say in two or three lines what will happen, and go on: you make the studio folder here (no game
|
|
168
|
+
in it yet: its home page says "First game coming soon" until the first one is made); later, when it goes online, Cloudflare opens in their browser **once** to approve (a free
|
|
169
|
+
account); on their account you will create one Worker, one D1 database and two
|
|
170
|
+
Durable Objects, all free on the Workers Free plan; the homie.rocks directory lists the games (only the
|
|
171
|
+
site's address, the studio's name, each game's name, blurb and Play link).
|
|
172
|
+
|
|
173
|
+
1. Call `studio_scaffold` with the name (and a folder if the person named one) and run the command it
|
|
174
|
+
returns; without the connector, run `npx -y @homie-rocks/studio@latest new <folder> --name "<Name>"`.
|
|
175
|
+
Either lists every file it writes and installs the pinned toolkit and `wrangler` (about 20 s).
|
|
176
|
+
2. Folder: the one the person named; otherwise a NEW folder named after the studio's slug inside the
|
|
177
|
+
current directory (e.g. `./night-owls`). Never in a folder that already holds other files, never in
|
|
178
|
+
the home folder, never outside the current directory.
|
|
179
|
+
**Other studios in the same folder** (a folder beside this one with its own `studio.json`) are other
|
|
180
|
+
people's work: never read them or copy from them, not even as a model for this studio or its game,
|
|
181
|
+
unless the person asks.
|
|
182
|
+
**An earlier attempt:** if a folder of this name already exists and is not a studio (notes, a plan, a
|
|
183
|
+
charter from before), say so and ASK whether to fold its premise in: with a yes, copy its notes into the
|
|
184
|
+
studio's `notes/earlier/<folder>/` and use them in the plan; remove the old folder only with a second yes
|
|
185
|
+
(to the Trash, so it can come back). Never delete or overwrite it unasked.
|
|
186
|
+
3. From here on run the studio's own copy: `npm run <script>` or `npx --no-install homie-studio <command>`
|
|
187
|
+
(`--no-install` never fetches a package by that bare name).
|
|
188
|
+
4. Continue with the requested build.
|
|
189
|
+
|
|
190
|
+
A missing connector is no reason to stop: with a shell, make the studio with the command above and say in
|
|
191
|
+
one line that the connector is not connected ("Without the connector", step 0). Never invent the package
|
|
192
|
+
address: it is `@homie-rocks/studio`, and this skill is where it is written down.
|
|
193
|
+
|
|
194
|
+
## 2. See a working game (optional tutorial)
|
|
195
|
+
|
|
196
|
+
**Show a live one; copy nothing.** A new studio has no game, and it gets none it did not ask for.
|
|
197
|
+
`npx --no-install homie-studio demo` names a live multiplayer game on Homie Arcade (made with this same
|
|
198
|
+
toolkit) with its Play link: give them the link and say to open it in two browser tabs, or on a phone and
|
|
199
|
+
a computer, and they are two players in the same public room, with bots in the empty seats. Then ask:
|
|
200
|
+
"Want a copy of a working starter in your own studio to change, or shall we go straight to planning your
|
|
201
|
+
game?"
|
|
202
|
+
|
|
203
|
+
It always names one. Where your commands have no network (Codex runs them that way by default), it cannot
|
|
204
|
+
read the arcade and answers `"reached": false` with the arcade's standing first pick, Asteroids Arena:
|
|
205
|
+
https://arcade.homie.rocks/asteroids-arena/play. That link opens in the person's own browser, not in your
|
|
206
|
+
session, so give it as the live game it is and say nothing about the lookup. The same address serves when
|
|
207
|
+
the command cannot be run at all.
|
|
208
|
+
|
|
209
|
+
**Only when they ask for a copy** (now, or in their first message): the Gem Rush starter (grab gems, knock
|
|
210
|
+
rivals away; bots fill the empty seats), or Ember Vale (`--from ember-vale`: a hero who lasts for days, with
|
|
211
|
+
cloud saves) when they want a persistent game. Another studio's whole game cannot be copied; pieces
|
|
212
|
+
of one that its studio shared can (the `parts` skill).
|
|
213
|
+
|
|
214
|
+
```sh
|
|
215
|
+
npx --no-install homie-studio game new <id> --from gem-rush --name "<Name>"
|
|
216
|
+
npm run dev # in the background: http://127.0.0.1:8787/<id>/play
|
|
217
|
+
npx --no-install homie-studio check <id> --url http://127.0.0.1:8787 --shots ./.checks
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`check` proves it first: two fresh browsers press Play, share a room and see a round finish (about 70 s).
|
|
221
|
+
Show one of its pictures. Start `npm run dev` as a background task your app keeps alive (Claude Code: the
|
|
222
|
+
Bash tool's `run_in_background`); stop it with `npx --no-install homie-studio dev --stop`, which stops
|
|
223
|
+
exactly this studio's dev server and nothing else. Never `pkill`, `killall` or `lsof ... | xargs kill`: other
|
|
224
|
+
projects on this machine may run their own `wrangler dev`. Without a game, `npm run dev` shows the studio's
|
|
225
|
+
own home page ("First game coming soon") at http://127.0.0.1:8787/.
|
|
226
|
+
|
|
227
|
+
## 3. One small change (optional tutorial)
|
|
228
|
+
|
|
229
|
+
"Now tell me one thing to change, in your own words." With a copied starter, it is the game: a colour, the
|
|
230
|
+
speed, what you collect, the name (in `games/<id>/`). Without one, it is the studio's own home page: its
|
|
231
|
+
colours (`site/theme.json`), a tagline (`studio.json` `"tagline"`), or a first post ("we're making our first
|
|
232
|
+
game"; `posts/README.md`). Make exactly that, `npm run build`, and tell them to reload. If they say "you
|
|
233
|
+
pick", make one visible change (the colours, or the name and its colours) and say what it was. This is the
|
|
234
|
+
whole loop in a minute: they say it, they see it. Keep the change small; the big ideas go into the plan.
|
|
235
|
+
|
|
236
|
+
## 4. Plan your game: the Game Codex
|
|
237
|
+
|
|
238
|
+
Follow the `plan` skill: record your defaults in CODEX.md, show it and continue. No interview
|
|
239
|
+
unless requested. Engineering and design choices are yours; the person can steer at any time.
|
|
240
|
+
|
|
241
|
+
## 5. Build it
|
|
242
|
+
|
|
243
|
+
Use one agent by default and the `game` skill for a game. Give the Play link when checks pass.
|
|
244
|
+
Open a progress feed for every build so they can watch it:
|
|
245
|
+
|
|
246
|
+
```sh
|
|
247
|
+
npx --no-install homie-studio progress start <id> --title "<this milestone, from the codex>"
|
|
248
|
+
npx --no-install homie-studio progress stage plan done --note "<the plan in one line>"
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`build`, `check` and `deploy` report into it. The codex page's **Build status** tab shows it (a
|
|
252
|
+
percentage, each step and check going green, how to try it, what was spent) and redraws itself; the
|
|
253
|
+
status line shows one line of it in Claude Code, and the Homie mod's Studio pane (Claude Code 2.1.287 or
|
|
254
|
+
later) shows all of it with the latest check frame and opens by itself. In the Claude app, add `--share` and call
|
|
255
|
+
`build_progress` with the build id it prints: the card follows the build. In Codex and Grok Build Homie
|
|
256
|
+
draws no status line, pane or card, so there the codex page is the progress view (`npx --no-install homie-studio codex <id> --open`).
|
|
257
|
+
|
|
258
|
+
## 6. Playtest it, then put it online
|
|
259
|
+
|
|
260
|
+
**Playtest** with the `playtest` skill; fix what it ranks first. If it is slow on a phone, the `perf` skill
|
|
261
|
+
measures why and keeps only the changes that make it faster beyond the noise. If a move feels weak (the jump, the
|
|
262
|
+
hit), the `lab` skill tunes it with the person, New beside Today.
|
|
263
|
+
|
|
264
|
+
**The site** is made from the studio (`node_modules/@homie-rocks/studio/site/SITE.md`): Home, Games,
|
|
265
|
+
Music, Videos, Rooms and Posts, each once the studio has something in it, in the studio's own look, with
|
|
266
|
+
"Made with Homie" at the foot of every page (keep it). Before going online:
|
|
267
|
+
|
|
268
|
+
1. **Its look.** `site/theme.json`: colours that belong to the studio's name and its first game (`bg`,
|
|
269
|
+
`fg`, `accent`, `glow`, or a `palette`); the codex's palette is a good start. A one-line `"tagline"`
|
|
270
|
+
in `studio.json`.
|
|
271
|
+
2. **The game's landing** (`/<id>/`): "Its landing page" in the `game` skill. At least the words
|
|
272
|
+
(game.json `landing`) and a cover from a real frame (the `art` skill's free `frame` and `cover`).
|
|
273
|
+
3. **A first post**: `posts/<today>-<game id>-is-live.md` with `title:`, `summary:` and `game: <id>`
|
|
274
|
+
(`posts/README.md` has the format).
|
|
275
|
+
4. **Look at it**: `npm run build`, `npm run dev`, then `npx --no-install homie-studio look --url
|
|
276
|
+
http://127.0.0.1:8787`, open the pictures, fix, again.
|
|
277
|
+
|
|
278
|
+
**Cloudflare**, checked only now (a studio that never deploys never needs it):
|
|
279
|
+
|
|
280
|
+
1. `npx wrangler whoami` in the studio folder. Not signed in: run `npx wrangler login` and tell the
|
|
281
|
+
person in one line that Cloudflare opened in their browser and they should approve it (their own account). That is their only step. Never ask for or write an API key.
|
|
282
|
+
2. Before the first deploy, `npx --no-install homie-studio deploy --plan`, and tell them its gist in two
|
|
283
|
+
or three lines: the resources (one Worker, one D1 database, two Durable Objects; no R2), the cost
|
|
284
|
+
(on your account), and what the directory stores. Then go on.
|
|
285
|
+
3. `npm run deploy`. It creates the Worker and the D1 database named in `studio.json`, applies
|
|
286
|
+
migrations, deploys, and reads the live site once, which makes the site claim itself in the
|
|
287
|
+
directory. It refuses to touch anything of the same name it did not create (rename in `studio.json`
|
|
288
|
+
and `wrangler.jsonc`; never delete or overwrite the other resource). If it answers with a `needs`
|
|
289
|
+
step, say it in one line and wait: `cloudflare-verify-email` (the account verifies its email address
|
|
290
|
+
first: the email Cloudflare sent, one tap), `workers-dev-subdomain` (the AI registers the workers.dev address
|
|
291
|
+
once, on the link it gives). `setup status` remembers which.
|
|
292
|
+
4. `npx --no-install homie-studio check <id> --url <the live site>`: the same two-browser proof, live.
|
|
293
|
+
|
|
294
|
+
**Tell Homie, once.** At the end of a first setup (the game is online, or the person stops for the day), and at
|
|
295
|
+
any point the person is stuck, confused or frustrated, or after an error you could not fix, you may offer, once in
|
|
296
|
+
the session, to send the people who make Homie a short note about how it went: "Want me to tell Homie that the
|
|
297
|
+
subdomain step was confusing? This is what I'd send:". Draft it with `homie_feedback` (`offered: true`; a draft
|
|
298
|
+
sends nothing), in plain words from what happened, with the step it was about (`step: "studio-setup: put it
|
|
299
|
+
online"`). Show it exactly as it would go (in the Claude app its card has Send, Edit and Don't send) and send it
|
|
300
|
+
only after they say yes; in Claude Code, Claude Code itself asks them with the exact note, and in Codex
|
|
301
|
+
Homie's hooks hold the send for their `proceed <code>`. A no is final for the
|
|
302
|
+
session: say nothing was sent and carry on. Never make help wait on it, never offer twice, never put a key, a log,
|
|
303
|
+
a file, code or anyone's name in it, and a reply address only if they typed it. When they ask to tell Homie
|
|
304
|
+
something themselves, draft it with `offered: false`.
|
|
305
|
+
|
|
306
|
+
### Another way: Cloudflare (and ElevenLabs) through Stripe Projects
|
|
307
|
+
|
|
308
|
+
`npx wrangler login` stays the way. Offer this only when the person has **no Cloudflare account** (and wants songs but
|
|
309
|
+
has no ElevenLabs either), and would rather have both made for them in one go: Stripe Projects
|
|
310
|
+
(docs.stripe.com/projects), Stripe's CLI plugin, makes or links provider accounts on the person's own Stripe sign-in
|
|
311
|
+
and hands the credentials to the studio folder. It is a prototype in this version (`setup --via stripe-projects`).
|
|
312
|
+
|
|
313
|
+
1. Say it in two lines: Stripe signs them in; Cloudflare makes a free account for their Stripe email (or, if they
|
|
314
|
+
have one, shows its own approval page once); on their own accounts; they accept Cloudflare's terms
|
|
315
|
+
(and ElevenLabs': whose free plan has **no commercial licence**, so songs made on it are not for sale).
|
|
316
|
+
2. `npx --no-install homie-studio setup --via stripe-projects [--with elevenlabs] --dry-run`: what it would do.
|
|
317
|
+
3. Run it without `--dry-run`. It stops at each step that is the person's and says which, as `needs`:
|
|
318
|
+
- `stripe-cli` / `projects-plugin`: run the command it names (the person approves the install);
|
|
319
|
+
- `projects-init`: run `stripe projects init --yes`; Stripe opens its sign-in in their browser. It must be **their
|
|
320
|
+
own** Stripe account (a new free one is fine). If the Stripe CLI on this computer is signed in to some other
|
|
321
|
+
account (a work or client one), stop and ask; never use it;
|
|
322
|
+
- `accept-terms`: ask the person; only after their yes, run it again with `--accept-tos`;
|
|
323
|
+
- `link-cloudflare`: run `stripe projects link cloudflare`; their browser shows Cloudflare's approval page;
|
|
324
|
+
- `paid`: stop. Nothing paid is ever added; this is theirs to decide in Stripe Projects, not yours.
|
|
325
|
+
4. When it answers ok, `npm run deploy` as usual: Wrangler deploys with the Projects token.
|
|
326
|
+
|
|
327
|
+
What it keeps where: the Cloudflare account id goes in `studio.json` (`cloudflare.auth: "stripe-projects"`); the token
|
|
328
|
+
stays in Projects' vault and the git-ignored `.env` it syncs, and the toolkit hands it to Wrangler itself. Follow
|
|
329
|
+
Projects' own rules: never print, read out or `cat` an env value (`stripe projects env --json` lists names only), never
|
|
330
|
+
commit `.env`, `.env.*` or `.projects/vault/` (the command checks `.gitignore`), never hand-edit `.projects/`. If a
|
|
331
|
+
later deploy says the token is not accepted: `stripe projects env --pull` in the studio folder, then deploy again.
|
|
332
|
+
|
|
333
|
+
The live address `deploy` prints is on `workers.dev`, which names the person's Cloudflare account;
|
|
334
|
+
`deploy` keeps it in `.studio/local.json` (git-ignored). Never write it into a committed file. A custom
|
|
335
|
+
domain is set with `studio_domain` (Desktop), or by the AI adding `cloudflare.domain` and
|
|
336
|
+
`{ "pattern": "<hostname>", "custom_domain": true }` to the Wrangler routes. Deploy uses the
|
|
337
|
+
existing Cloudflare sign-in to create DNS and TLS. Never ask the person for a zone id or DNS record. Never touch a route the studio does not own: a catch-all
|
|
338
|
+
or wildcard route already on that domain belongs to another site there, and the deploy's warning gives the
|
|
339
|
+
one line to add instead (the `publish` skill has the rest).
|
|
340
|
+
|
|
341
|
+
**The directory, only when asked.** Going online never lists a studio: listing in the homie.rocks directory
|
|
342
|
+
is its own step, it is public, and it is the person's to ask for. When they asked to be listed (in their first
|
|
343
|
+
message or now), or say yes when you offer it once the site is live, call the Homie MCP tool `studio_publish`
|
|
344
|
+
with the live site address (without the connector, `npx --no-install homie-studio publish`). It lists the
|
|
345
|
+
games with their Play links (at most 12 per studio in the beta; its owner can unlist a listing that
|
|
346
|
+
breaks its rules).
|
|
347
|
+
|
|
348
|
+
**Tell the person**, three to five lines: the studio folder, the live site, each game's landing
|
|
349
|
+
(`/<id>/`) and Play link, the directory link when it was listed (and that it is not, when it was not), that two browsers finished a round on the live site, what
|
|
350
|
+
runs on their Cloudflare and what it costs (free). The codex is on the site for them alone:
|
|
351
|
+
`npx --no-install homie-studio codex link <id>` gives a one-time link for their own browser (a phone
|
|
352
|
+
works). The studio keeps its own stats for them (`npx --no-install homie-studio stats`, or `stats link`).
|
|
353
|
+
Add: Homie for studios is in beta; bugs, port requests and questions go to
|
|
354
|
+
https://github.com/homie-rocks/homie/issues/new/choose. Commit the studio (`git add -A && git commit -m
|
|
355
|
+
"..."` inside the studio folder: it is the studio's own repository).
|
|
356
|
+
|
|
357
|
+
## An existing studio that is behind: what's new
|
|
358
|
+
|
|
359
|
+
A studio pins one `@homie-rocks/studio` version in its `package.json`. When you open a studio, or the person asks
|
|
360
|
+
"what's new" or to update or upgrade it, compare that pin with the newest (`npm view @homie-rocks/studio version`; in
|
|
361
|
+
Claude Desktop the studio card says so itself). When the studio is behind:
|
|
362
|
+
|
|
363
|
+
1. Tell the person, in a few plain lines, what's new since their version: run
|
|
364
|
+
`npx -y @homie-rocks/studio@latest upgrade` in the studio (it changes nothing). It starts with "What's new since
|
|
365
|
+
<their version>", one line per version from the new version's own CHANGELOG.md, then the upgrade notes: anything
|
|
366
|
+
they have to do themselves. Pass those on in your own words, the upgrade notes first; never paste the whole list.
|
|
367
|
+
(In Claude Desktop: `studio_run` with `["upgrade"]`.)
|
|
368
|
+
2. Say what the upgrade would change in the studio (the plan under "The changes"), and that nothing they wrote
|
|
369
|
+
themselves is touched.
|
|
370
|
+
3. Only with their yes: the `--apply` command the plan names, then `npm install` (`studio_install`), `npm run build`,
|
|
371
|
+
a look at the site, and one commit for the upgrade on its own.
|
|
372
|
+
|
|
373
|
+
Every version's notes are also at https://github.com/homie-rocks/homie/blob/main/CHANGELOG.md.
|
|
374
|
+
|
|
375
|
+
## Another computer or collaborator
|
|
376
|
+
|
|
377
|
+
A private GitHub backup is optional, not a first-run requirement. If requested, install gh yourself,
|
|
378
|
+
start its browser/device sign-in, create a private repository and push. Discover the account and
|
|
379
|
+
repository names; never ask for an id, token or command. In a browser-capable host you enter the
|
|
380
|
+
device code on https://github.com/login/device; the owner signs in and approves. In Desktop without
|
|
381
|
+
browser control, explain that GitHub's device code is the remaining host limitation.
|
|
382
|
+
|
|
383
|
+
On another computer, install Homie in the host, then `studio_open` with the repository clones and
|
|
384
|
+
installs it. Use the existing name, plan and version. Reauthorize Cloudflare or Stripe only when
|
|
385
|
+
needed; never copy credentials or local owner state. For an explicitly requested collaborator,
|
|
386
|
+
resolve the named GitHub user, invite them to the repository with the requested role, and let them
|
|
387
|
+
accept GitHub's link. Repository access does not require Cloudflare billing or Stripe access.
|
|
388
|
+
|
|
389
|
+
## Storage, later and only when asked
|
|
390
|
+
|
|
391
|
+
Songs, videos and other large media go to the studio's storage (an R2 bucket), not git. A studio that
|
|
392
|
+
makes games never needs it. When the person wants it: `npx --no-install homie-studio storage add`.
|
|
393
|
+
Cloudflare asks for a payment method on the account before R2 works (its first 10 GB a month are free),
|
|
394
|
+
so say that first and let the person decide; if R2 is not turned on, the command gives the dashboard
|
|
395
|
+
link and creates nothing. Then every `npm run deploy` binds it and moves the big songs and videos
|
|
396
|
+
there (checked by SHA-256, at the same addresses); `homie-studio media move --dry-run` says which.
|
|
397
|
+
|
|
398
|
+
## Never
|
|
399
|
+
|
|
400
|
+
- Never jump ahead of the checklist, and never copy a starter or another studio's game into the studio
|
|
401
|
+
unless the person asked for it.
|
|
402
|
+
- Never read or copy from another studio in the same folder unless the person asks: it is somebody else's
|
|
403
|
+
work.
|
|
404
|
+
- Never stop for a missing connector while you can run a command, and never tell the person the connector
|
|
405
|
+
is needed to make a studio.
|
|
406
|
+
- Never put a key, token or password in the studio or in chat.
|
|
407
|
+
- Never touch Cloudflare resources the studio did not create.
|
|
408
|
+
- Never add a payment method, buy anything or turn on a paid plan for the person (in Stripe Projects too: no
|
|
409
|
+
`--confirm-paid-service`, no `stripe projects billing`, no `upgrade`).
|
|
410
|
+
- Never use `~/.homie`; the studio needs no Homie box.
|
|
411
|
+
- Never ask the person to type a command.
|
|
412
|
+
- Never send a note to Homie (`homie_feedback`) the person has not seen word for word and said yes to, and never
|
|
413
|
+
offer one more than once in a session.
|
|
414
|
+
|
|
415
|
+
## Connect an AI to this studio
|
|
416
|
+
|
|
417
|
+
Every studio serves its own MCP at `<site>/mcp`. Use the `tools` skill for studio-defined business actions, signed integrations and staff AI access. Reuse office and app-record built-ins first. After an authorized deploy, hand over the MCP address and `<site>/_studio/office/connections`: the person approves with the studio account they already have, with no key to copy. Staff connect their own account and retain only their app grants. Client connector setup is separate from the studio approval. Never deploy merely to set up a local tool test.
|
|
418
|
+
|
|
419
|
+
For a business or cause, use `studio_scaffold {name, kind:"business"}` or `homie-studio new <folder> --kind cause`. Continue directly with the app skill and the appropriate `app new --from` starter; no game demo or planning interview unless requested.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: style
|
|
3
|
+
description: "A game's look as a set of decisions that fit together — render style, palette, shape language, proportions, materials, light, camera, fonts and effects; then the cast, its library family, scale and phone budgets — each picked automatically from the person's words with a one-line why, which the person can steer (\"warmer\", \"closer\"), lock, or explore on a style board of three directions drawn by the game engine itself (free; a painted mood image only on their own fal account). Locked and pinned decisions keep every asset coherent: change one and the blast radius lists exactly what went stale and what remaking it would cost, and nothing is remade without a yes. Use when someone talks about a game's look or style, \"make it look like…\", \"show me other looks\", \"keep that palette\", \"darker\", \"the art doesn't fit together\", or before making any models or art for a game."
|
|
4
|
+
compatibility: Node 22 and Chrome. The style board is free; a painted mood image uses the creator's own fal account (FAL_KEY), through the models skill.
|
|
5
|
+
metadata:
|
|
6
|
+
providers: fal
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# The look of a game: decisions, the board, locks
|
|
10
|
+
|
|
11
|
+
A game's art direction lives in `games/<id>/codex/decisions.json` (private, like the codex) and is drawn in
|
|
12
|
+
the Game Codex's **Art direction** tab: every decision with its value, its why, and its state. It is the style
|
|
13
|
+
bible. Everything made for the game (models, textures, covers, title cards) is made under it and records the
|
|
14
|
+
revision it was made under, so the game stays one game.
|
|
15
|
+
|
|
16
|
+
| State | Meaning | Who changes it |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| **auto** | your pick, with its why | you, freely |
|
|
19
|
+
| **steered** | the person nudged it ("warmer") | you may refine within the nudge, never undo it |
|
|
20
|
+
| **pinned** | the first asset built on it pinned it (locked by use) | you only while nothing paid or published depends on it; else ask |
|
|
21
|
+
| **locked** | the person froze it | only the person: unlock needs their reason, after they saw the blast radius |
|
|
22
|
+
|
|
23
|
+
A lock protects taste, not money: no signed approval, but you never change a locked value on your own, and you
|
|
24
|
+
record their words when you lock for them.
|
|
25
|
+
|
|
26
|
+
## The automatic path (the default: no questions)
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npx --no-install homie-studio style init <id> --prompt "<the person's own words about the game>"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
It fills about thirty decisions from their words, the codex and the genre, writes `style.json` (the palette,
|
|
33
|
+
fonts, light and camera the game draws with) and redraws the codex. Say ONE line: "Look: flat low-poly,
|
|
34
|
+
autumn grove palette, golden hour, high three-quarter camera; open the codex to change anything." Then build
|
|
35
|
+
with free routes only (the engine and the starter library: the `models` skill) unless the plan set an art
|
|
36
|
+
budget. The first asset you add pins the decisions it was made under.
|
|
37
|
+
|
|
38
|
+
## The hands-on path
|
|
39
|
+
|
|
40
|
+
When the person wants to steer the look closely (only when they request it), show the **style board**:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
npx --no-install homie-studio style board <id>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
(In an app with Homie's cards: `style_explore`; the card has Pick, Mix, Steer and Lock.) Three coherent
|
|
47
|
+
directions, each **drawn by the game's own engine**: its palette on a ground and a sky, its light and fog, its
|
|
48
|
+
camera, its material model (flat, toon with ink outlines, painted, PBR, pixel), a character stand-in at the
|
|
49
|
+
decided proportions, and the starter library family's own pieces re-tinted into the palette, with the title in
|
|
50
|
+
its display font. Free, about 20 seconds, saved under `games/<id>/codex/board/`. Look at all three yourself
|
|
51
|
+
before you show them (file_read), and say in one line each what is different.
|
|
52
|
+
|
|
53
|
+
- **Pick**: `style pick <id> b`. **Mix**: `style pick <id> --mix style.palette=b,style.camera=c`.
|
|
54
|
+
- **Steer**: `style steer <id> style.palette "warmer"` (warmer, cooler, less saturated, darker, lighter, a hex
|
|
55
|
+
colour with its job; light: golden hour, night, harder shadows; camera: closer, further, higher, top-down;
|
|
56
|
+
shape: chunkier, sharper; materials: add outlines). Words it does not know are recorded; refine the value
|
|
57
|
+
with `style set` within them.
|
|
58
|
+
- **Lock** when the person says so: `style lock <id> style.palette --words "<what they said>"`, or the whole
|
|
59
|
+
style: `style lock <id> style --words "…"`.
|
|
60
|
+
- **A painted mood image** per direction is optional and PAID (about US$0.035 each, the person's own fal
|
|
61
|
+
account, `models.mjs mood`): a picture the engine cannot draw is a target, never a promise, and the card says
|
|
62
|
+
so. Offer it only when the engine's swatches leave the person unsure.
|
|
63
|
+
- **Golden images**: once the style is locked, two to six approved pictures (a chosen mood image, a concept they
|
|
64
|
+
loved, their own art) become the references of every generated concept: `style golden <id> add <image>`.
|
|
65
|
+
|
|
66
|
+
## The characters: the cast card
|
|
67
|
+
|
|
68
|
+
`cast_plan` (or `npx --no-install homie-studio cast <id>`) shows the decisions that shape characters together:
|
|
69
|
+
proportions (heads tall, metres), the shape language and its silhouette rule (every character readable black on white
|
|
70
|
+
at 64 px: the lineup checks it), the palette, the library family, the skeleton family (`rig.skeleton`) and where rigs
|
|
71
|
+
come from; then every character made or planned, with its source, skeleton, bones, triangles and clips. A library
|
|
72
|
+
character comes in free (`asset_add`); a generated one through the `models` skill's `character` (paid, priced first);
|
|
73
|
+
their clips and feel are the `animate` skill's. A starter game's own `style.json` is what `style init` starts from:
|
|
74
|
+
it never repaints a working game behind its back.
|
|
75
|
+
|
|
76
|
+
## Changing a locked decision: the blast radius first
|
|
77
|
+
|
|
78
|
+
When the person wants a locked or pinned decision changed, never just change it:
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
npx --no-install homie-studio style blast <id> style.palette # what goes stale, and the cost
|
|
82
|
+
npx --no-install homie-studio style set <id> style.palette <value> --unlock --reason "<their words>" # shows it again, changes nothing
|
|
83
|
+
npx --no-install homie-studio style set <id> style.palette <value> --unlock --reason "<their words>" --confirm # after their yes
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Tell them the list in plain words: which assets go stale, which are fixed for free (a palette re-tint of
|
|
87
|
+
flat-coloured models, another library match, a procedural one regenerated) and what remaking the generated ones
|
|
88
|
+
would cost. Nothing is remade by itself: remaking is a new, priced job they approve (the `models` skill).
|
|
89
|
+
|
|
90
|
+
## One look end to end
|
|
91
|
+
|
|
92
|
+
- The game draws with `games/<id>/style.json` (palette, fonts, light, camera): read it rather than hard-coding
|
|
93
|
+
colours, so a change of the palette reaches the HUD and the world.
|
|
94
|
+
- The codex wears a steered or locked palette and fonts; the landing and the trailer's title cards use them too
|
|
95
|
+
(a game with no `landing.theme` takes its accent and glow from `style.json`).
|
|
96
|
+
- `style prompt <id>` is the derived style prompt (about 80 words: medium, shape, palette hexes, light, framing)
|
|
97
|
+
every generated picture starts from. It is computed, never edited by hand.
|
|
98
|
+
|
|
99
|
+
## Never
|
|
100
|
+
|
|
101
|
+
- Never change a locked decision without the person's yes after the blast radius; never remake anything by
|
|
102
|
+
yourself; never lock on your own.
|
|
103
|
+
- Never present a painted mood image as what the game looks like.
|
|
104
|
+
- Never name a living artist in a style ("in the style of …"): describe the look in words.
|
|
105
|
+
- Never "upgrade" a game whose procedural look is its strength to generated meshes without the owner's ask.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Opt-in acceptance evidence, sourced from the person's Codex, not starter labels. */
|
|
2
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
|
|
6
|
+
export function readAppNeeds(root, id) {
|
|
7
|
+
if (!root) return null;
|
|
8
|
+
const file = join(root, 'apps', id, 'CODEX.md');
|
|
9
|
+
if (!existsSync(file)) return null;
|
|
10
|
+
const source = readFileSync(file, 'utf8');
|
|
11
|
+
const block = /^```needs\s*\n([\s\S]*?)^```/m.exec(source);
|
|
12
|
+
if (!block) return null; // An existing prose Codex has not opted into executable needs.
|
|
13
|
+
const needs = JSON.parse(block[1]);
|
|
14
|
+
if (!Array.isArray(needs) || !needs.length) throw new Error('App Codex has no demonstrable needs yet');
|
|
15
|
+
const ids = new Set();
|
|
16
|
+
for (const n of needs) {
|
|
17
|
+
if (!n || !/^[a-zA-Z0-9_-]+$/.test(n.id ?? '') || ids.has(n.id) || typeof n.statement !== 'string' || !n.statement.trim()) throw new Error('Each Codex need requires a unique id and a statement from the request');
|
|
18
|
+
ids.add(n.id);
|
|
19
|
+
}
|
|
20
|
+
return { needs, hash: createHash('sha256').update(source).digest('hex') };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Run real UI actions. A failed or absent flow stays visible; continue collecting other needs. */
|
|
24
|
+
export async function proveAppNeeds({ plan, surfaces, shots, report }) {
|
|
25
|
+
const results = [];
|
|
26
|
+
const surface = name => { const s = surfaces.find(s => s.name === name); if (!s) throw new Error(`unknown surface ${name}`); return s; };
|
|
27
|
+
for (const need of plan.needs) {
|
|
28
|
+
const result = { id: need.id, statement: need.statement, status: 'not', captures: [] };
|
|
29
|
+
try {
|
|
30
|
+
if (!Array.isArray(need.assertions) || !['wall', 'phone'].every(name => need.assertions.some(a => a.surface === name))) throw new Error('needs wall and phone assertions');
|
|
31
|
+
for (const step of need.steps ?? []) {
|
|
32
|
+
const { frame, page } = surface(step.surface);
|
|
33
|
+
if (step.reload) { await page.reload({ waitUntil: 'domcontentloaded' }); await page.waitForFunction(() => window.__shell?.link?.state === 'online'); surface(step.surface).frame = page.frames().find(f => /\/__game\//.test(f.url())); continue; }
|
|
34
|
+
await frame.waitForSelector(step.selector, { visible: true });
|
|
35
|
+
if (step.click) await frame.click(step.selector);
|
|
36
|
+
else if (step.fill !== undefined) { await frame.$eval(step.selector, el => { el.value = ''; el.dispatchEvent(new Event('input', { bubbles: true })); }); await frame.type(step.selector, String(step.fill)); }
|
|
37
|
+
else if (step.select !== undefined) await frame.select(step.selector, String(step.select));
|
|
38
|
+
else throw new Error('step needs click, fill, select or reload');
|
|
39
|
+
}
|
|
40
|
+
for (const assertion of need.assertions) {
|
|
41
|
+
const { frame } = surface(assertion.surface);
|
|
42
|
+
await frame.waitForSelector(assertion.selector, { visible: true, timeout: 10000 });
|
|
43
|
+
if (assertion.text !== undefined) await frame.waitForFunction((selector, text) => document.querySelector(selector)?.textContent.includes(text), { timeout: 10000 }, assertion.selector, String(assertion.text));
|
|
44
|
+
}
|
|
45
|
+
result.status = shots ? 'met' : 'partly';
|
|
46
|
+
result.why = shots ? 'UI assertions passed; inspect captures against the pictured scene' : 'Assertions passed but no captures saved';
|
|
47
|
+
} catch (error) { result.why = error.message; }
|
|
48
|
+
if (shots) for (const name of ['wall', 'phone']) {
|
|
49
|
+
const file = join(shots, `${need.id}-${name}.jpg`);
|
|
50
|
+
try { await surface(name).page.screenshot({ path: file, type: 'jpeg', quality: 85 }); result.captures.push(file); }
|
|
51
|
+
catch (error) { result.status = 'partly'; result.why += `; capture failed: ${error.message}`; }
|
|
52
|
+
}
|
|
53
|
+
report?.check?.(`need-${need.id}`, result.status === 'met' ? 'pass' : 'fail', { label: need.statement, note: result.why });
|
|
54
|
+
results.push(result);
|
|
55
|
+
}
|
|
56
|
+
return results;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function saveAppNeeds(root, id, plan, needs) {
|
|
60
|
+
if (!root) return;
|
|
61
|
+
const dir = join(root, '.studio', 'checks'); mkdirSync(dir, { recursive: true });
|
|
62
|
+
writeFileSync(join(dir, `${id}-needs.json`), JSON.stringify({ at: new Date().toISOString(), codexHash: plan.hash, needs }, null, 2));
|
|
63
|
+
}
|
package/lib/authoring-guides.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import {homedir} from 'node:os';
|
|
|
4
4
|
import {STUDIO_VERSION} from './version.mjs';
|
|
5
5
|
const json=file=>{try{return JSON.parse(readFileSync(file,'utf8'));}catch{return null;}};
|
|
6
6
|
const older=(a,b)=>{const x=a.split('.').map(Number),y=b.split('.').map(Number);for(let i=0;i<3;i++){if(x[i]!==y[i])return x[i]<y[i];}return false;};
|
|
7
|
-
export function authoringGuidance({home=homedir(),version=STUDIO_VERSION}={}) {
|
|
7
|
+
export function authoringGuidance({home=homedir(),version=STUDIO_VERSION,kind='game'}={}) {
|
|
8
8
|
const installed=[];
|
|
9
9
|
const claude=json(join(home,'.claude/plugins/installed_plugins.json'));
|
|
10
10
|
for(const row of claude?.plugins?.['homie@homie']??[]) {
|
|
@@ -18,10 +18,11 @@ export function authoringGuidance({home=homedir(),version=STUDIO_VERSION}={}) {
|
|
|
18
18
|
const v=json(join(cache,entry,'.codex-plugin/plugin.json'))?.version;
|
|
19
19
|
if(v)installed.push({client:'Codex',version:v,update:'Run codex plugin marketplace upgrade homie && codex plugin add homie@homie, then start a new session'});
|
|
20
20
|
}
|
|
21
|
-
const guides
|
|
22
|
-
|
|
21
|
+
const guides=`node_modules/@homie-rocks/studio/guides/${kind === 'app' ? 'app' : 'game'}/`;
|
|
22
|
+
const files=kind === 'app' ? 'SKILL.md' : '{SKILL,RULES,REWRITE}.md';
|
|
23
|
+
return {version,guides,files,warning:installed.filter(p=>/^\d+\.\d+\.\d+$/.test(p.version)&&older(p.version,version)).map(p=>`Homie ${p.client} plugin ${p.version} is older than toolkit ${version}. Its guidance may be stale. Read ${guides}${files}. ${p.update}.`)};
|
|
23
24
|
}
|
|
24
25
|
export function authoringWords(options) {
|
|
25
26
|
const g=authoringGuidance(options);
|
|
26
|
-
return [`Author against toolkit ${g.version}: ${g.guides}{
|
|
27
|
+
return [`Author against toolkit ${g.version}: ${g.guides}${g.files}`,...g.warning];
|
|
27
28
|
}
|