@home-v0/cli 0.1.0 → 0.2.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/README.md +11 -11
- package/dist/home-v0.js +12 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @home-v0/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[home-v0](https://home-v0.com) helps a homeowner decide what to do with the outside of their house and send the plan to whoever will build it. This CLI builds a house in 3D in home-v0 from a folder of photos and floor plans, by hand or with an AI agent (Claude Code, Codex, Cursor…). An agent in home-v0 builds the model; the CLI uploads the house, follows the build, and saves the agent's chat, renders and 3D model next to your files.
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
6
|
npx @home-v0/cli login --token hv0_… # API key from home-v0 → API keys
|
|
@@ -10,15 +10,15 @@ npx @home-v0/cli build our-house # 10 to 40
|
|
|
10
10
|
npx @home-v0/cli say our-house -m "The roof is steeper: the section shows 45 degrees"
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
| Command
|
|
14
|
-
|
|
|
15
|
-
| `login [--token]`, `logout`
|
|
16
|
-
| `init [dir] --name … --place …`
|
|
17
|
-
| `houses [dir]`
|
|
18
|
-
| `build [house]`
|
|
19
|
-
| `say [house] -m …`
|
|
20
|
-
| `follow`, `pull`, `stop` `[house]`
|
|
21
|
-
| `guide [--agents-md]`
|
|
13
|
+
| Command | What it does |
|
|
14
|
+
| ---------------------------------- | -------------------------------------------------------------------- |
|
|
15
|
+
| `login [--token]`, `logout` | Save or forget an API key (or set `HOME_V0_API_KEY`) |
|
|
16
|
+
| `init [dir] --name … --place …` | Start a house folder: `house.json`, `photos/`, `drawings/` |
|
|
17
|
+
| `houses [dir]` | List the house folders below a folder |
|
|
18
|
+
| `build [house]` | Make the house in home-v0, upload its files and follow the build |
|
|
19
|
+
| `say [house] -m …` | Tell the agent what to change and follow its answer |
|
|
20
|
+
| `follow`, `pull`, `stop` `[house]` | Keep following, save the latest files once, or stop the agent's turn |
|
|
21
|
+
| `guide [--agents-md]` | The folder format, the workflow and how to review a build |
|
|
22
22
|
|
|
23
23
|
A house is a folder with a `house.json`, the current folder by default.
|
|
24
24
|
|
|
@@ -30,4 +30,4 @@ Exit codes: 0 done, 1 the build failed or is waiting on a key or limit, 2 a mist
|
|
|
30
30
|
|
|
31
31
|
## Developing
|
|
32
32
|
|
|
33
|
-
From the repo root: `npm run home -- <command>` runs the source against `--api-url http://localhost:3000` or any home-v0. A local API needs no key: the CLI makes its own account there. `npm run build -w @home-v0/cli` bundles `dist/home-v0.js`, which is what gets published.
|
|
33
|
+
From the repo root: `npm run home -- <command>` runs the source against `--api-url http://localhost:3000` or any home-v0. A local API needs no key: the CLI makes its own account there. `npm run build -w @home-v0/cli` bundles `dist/home-v0.js`, which is what gets published. Releases go through `.github/workflows/release-cli.yml`: bump the version here in a PR, then run the workflow.
|
package/dist/home-v0.js
CHANGED
|
@@ -52,14 +52,11 @@ var HomeApi = class {
|
|
|
52
52
|
return this.request("GET", `places/search?${new URLSearchParams({ q: query })}`);
|
|
53
53
|
}
|
|
54
54
|
createProject(name, place) {
|
|
55
|
-
return this.request("POST", "projects", { json: { name,
|
|
55
|
+
return this.request("POST", "projects", { json: { name, place } });
|
|
56
56
|
}
|
|
57
57
|
deleteProject(id) {
|
|
58
58
|
return this.request("DELETE", `projects/${id}`);
|
|
59
59
|
}
|
|
60
|
-
spaces(projectId) {
|
|
61
|
-
return this.request("GET", `projects/${projectId}/spaces`);
|
|
62
|
-
}
|
|
63
60
|
space(id) {
|
|
64
61
|
return this.request("GET", `spaces/${id}`);
|
|
65
62
|
}
|
|
@@ -180,10 +177,10 @@ var webUrlFor = (apiUrl) => {
|
|
|
180
177
|
// src/guide.ts
|
|
181
178
|
var guide = () => `# Building a house in home-v0 with the CLI
|
|
182
179
|
|
|
183
|
-
home-v0
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
agent) prepare a folder; the CLI does the rest.
|
|
180
|
+
home-v0 helps a homeowner decide what to do with the outside of their house and send the plan to whoever will
|
|
181
|
+
build it. An AI agent builds the house in 3D from its photos and floor plans. The \`home-v0\` CLI does what you'd
|
|
182
|
+
do in the app: it makes the house, uploads its photos and drawings, starts the build, and saves the agent's chat,
|
|
183
|
+
renders and 3D model in the house's folder. You (a person or an AI agent) prepare a folder; the CLI does the rest.
|
|
187
184
|
|
|
188
185
|
## Sign in
|
|
189
186
|
|
|
@@ -225,8 +222,7 @@ my-house/
|
|
|
225
222
|
|
|
226
223
|
Photos: the whole outside of the house from eye level, each side if you can. Street View screenshots work well.
|
|
227
224
|
At least one photo is required: the app reads the house from its photos. Drawings are optional but make the model
|
|
228
|
-
much closer: plans decide wall lengths
|
|
229
|
-
plan is built inside too.
|
|
225
|
+
much closer: plans decide wall lengths and openings on sides the photos don't show.
|
|
230
226
|
|
|
231
227
|
## Workflow
|
|
232
228
|
|
|
@@ -241,7 +237,7 @@ plan is built inside too.
|
|
|
241
237
|
4. \`home-v0 follow my-house\` keeps watching if a command timed out; \`home-v0 pull my-house\` saves the latest files
|
|
242
238
|
without waiting; \`home-v0 stop my-house\` stops the agent's current turn.
|
|
243
239
|
|
|
244
|
-
Open the link in \`run.json\` to see the model in 3D
|
|
240
|
+
Open the link in \`run.json\` to see the model in 3D and try ideas on it in the app.
|
|
245
241
|
|
|
246
242
|
## Review
|
|
247
243
|
|
|
@@ -251,7 +247,6 @@ Compare each render with the photos and drawings, element by element:
|
|
|
251
247
|
- the roof: type, pitch, overhangs, which way the ridge runs, dormers and chimneys
|
|
252
248
|
- openings on each side: how many, where, and how big
|
|
253
249
|
- materials and colours
|
|
254
|
-
- inside each floor that has a plan: walls, doors, stairs and room names
|
|
255
250
|
|
|
256
251
|
Say which render and which photo or drawing each point comes from, and how sure you are when a render's angle hides
|
|
257
252
|
something. Fix the biggest differences first.
|
|
@@ -475,7 +470,7 @@ function chatMarkdown(run, messages) {
|
|
|
475
470
|
}
|
|
476
471
|
|
|
477
472
|
// src/version.ts
|
|
478
|
-
var VERSION = true ? "0.
|
|
473
|
+
var VERSION = true ? "0.2.0" : JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
479
474
|
|
|
480
475
|
// src/main.ts
|
|
481
476
|
var POLL_MS = 3e3;
|
|
@@ -647,11 +642,9 @@ async function startBuild(api, house) {
|
|
|
647
642
|
const project = await api.createProject(house.name, place);
|
|
648
643
|
let run;
|
|
649
644
|
try {
|
|
650
|
-
|
|
651
|
-
if (!exterior) throw new Error(`The new house ${project.id} has no exterior`);
|
|
652
|
-
let space = await api.addPhotos(exterior.id, house.photos);
|
|
645
|
+
let space = await api.addPhotos(project.spaceId, house.photos);
|
|
653
646
|
for (let i = 0; i < house.drawings.length; i += MAX_DRAWING_FILES_PER_UPLOAD) {
|
|
654
|
-
space = await api.addDrawings(
|
|
647
|
+
space = await api.addDrawings(project.spaceId, house.drawings.slice(i, i + MAX_DRAWING_FILES_PER_UPLOAD));
|
|
655
648
|
}
|
|
656
649
|
console.log(
|
|
657
650
|
` uploaded ${count(space.photos.length, "photo")} and ${count(space.drawings.length, "page")} of drawings`
|
|
@@ -660,10 +653,10 @@ async function startBuild(api, house) {
|
|
|
660
653
|
apiUrl: api.baseUrl,
|
|
661
654
|
webUrl: `${webUrlFor(api.baseUrl)}/projects/${project.id}/exterior`,
|
|
662
655
|
projectId: project.id,
|
|
663
|
-
spaceId:
|
|
656
|
+
spaceId: project.spaceId,
|
|
664
657
|
startedAt: startedAt.toISOString()
|
|
665
658
|
});
|
|
666
|
-
await api.capture(
|
|
659
|
+
await api.capture(project.spaceId);
|
|
667
660
|
} catch (error) {
|
|
668
661
|
await api.deleteProject(project.id).catch(() => void 0);
|
|
669
662
|
if (run) await rm2(run.folder, { recursive: true, force: true });
|