· 1 observation
Technical updates · 1
Package or technical metadata updated
View technical comparison →Spryloom v0.1.12
Publish apps to your team
Developer declarations; not independently tested. Listing last checked Nov 4, 2026. Package observed Nov 3, 2026.
Not specified in the available declarations: limitations, pricing & account requirements.
Publish this app so my team can use it.
From the marketplace listing
Spryloom publishes the app you just built so your coworkers can use it, behind sign-in. Say "share this with my team" and the agent writes a small manifest, runs `spry publish`, and gives you a private address. Spryloom builds the app, gives it its own database if it needs one, and runs scheduled jobs and email when the app declares them. Coworkers you invite sign in with an emailed link; nobody else can open it. The skill also guides the agent while it builds, so the app reads its port and settings from the environment, keeps data in Postgres and publishes the first time. Who it's for: anyone building internal tools, dashboards, reports or small team apps with an agent, who wants them used by their team without setting up hosting, a database or sign-in. Limitations: the skill uses the `spry` command line (the npm package `spryloom`), which needs Node.js 20.19 or later and network access. Signing in is a one-time emailed link that you approve yourself. Apps run Node.js or are static pages. File uploads aren't supported yet, and an app can reach only the outside services on Spryloom's list.
Language: English · Automatically detected from descriptions.
· 1 observation
Package or technical metadata updated
View technical comparison →Find competitors to follow as you develop your plugin.
Publish websites ChatGPT writes to a live buildcheap.host URL, then list, read and update them.
Shared terms: publish, address, deploy, later
Publish changes to your CR Servers-hosted website from ChatGPT, with a private preview first and one-step undo.
Shared terms: publish, database, deploy, publishe
Build, test and publish Olbrain AI agents from Codex, with Olbrain's Alchemist builder.
Shared terms: publish, behind, jobs, publishe
AppDeploy lets you create and deploy real web apps directly from ChatGPT. Describe what you want, and AppDeploy turns it into a live publ...
Shared terms: command, dashboard, database, deploy
Build, host and run business apps on Piezas from ChatGPT and Codex.
Shared terms: address, deploy, internal, limitation
---
name: spryloom
description: Publish an app you have just built so the user's coworkers can use it, behind company sign-in, in one step. Use when the user says the app works and asks how to share it, give it to their team, put it somewhere, or get other people using it. Also use while building any app the user intends to share, so it is written in a way that deploys.
---
# Publishing to Spryloom
Spryloom runs small software for teams. You publish; their coworkers sign in with
their company account and use it. The user never sees a container, a database
connection string, or a certificate.
There are two halves to this skill, and the first matters more.
## 1. While you build
Most publish failures are decided long before anyone runs `publish`. You are the
only one who can prevent them, because you are the one writing the code. Follow
these while you build, not as a checklist afterwards.
**Read the port from the environment.** Spryloom assigns a port and passes it in
`PORT`. An app that listens on a fixed number builds fine and then serves
nothing, which is the single most common way an agent-built app fails.
```js
server.listen(process.env.PORT || 3000, '0.0.0.0');
```
Bind to `0.0.0.0`, not `127.0.0.1`. A server bound to loopback is unreachable
from outside its own container.
**Read every setting from the environment.** Database URLs, API keys, and feature
flags arrive as environment variables. Never read them from a file on disk, and
never commit a `.env`. Spryloom injects secrets when the app starts, and they are
in no image layer and no log line.
```js
const databaseUrl = process.env.DATABASE_URL; // Spryloom sets this itself
const apiKey = process.env.STRIPE_API_KEY; // the user sets this, see below
```
**If the app needs a key the user holds**, tell them the command rather than
asking them to paste it to you:
```
spry secrets my-app set STRIPE_API_KEY=...
```
Two things to say when you do. Secrets reach the app when it is published, so
they publish again afterwards. And an app cannot be given a secret before it
exists, so if the app cannot start without one, the first publish will fail and
the second will work. Say that in advance rather than letting them discover it.
**Commit a lockfile.** Run `npm install` so `package-lock.json` exists and is
saved. Without it, the versions installed at build time are not the versions you
tested against.
**Give the app a start script.**
```json
{ "scripts": { "start": "node server.js" } }
```
**Do not assume a developer's machine at build time.** No global tools, no
absolute paths, no reading from outside the project folder. The build runs in a
clean sandbox with nothing but the repository and its dependencies.
**Keep writes to one place.** The filesystem is read-only apart from a temporary
directory. Anything that must survive a restart belongs in the database.
**Use a database rather than a file.** Files written next to the code disappear
when the app restarts. If the app needs to remember something, use Postgres.
## 2. When the user wants to share it
The moment the user says it works and asks how to give it to someone, publish it.
Do not explain hosting. Do not offer a list of providers.
### Ask two questions, not ten
Everything else is inferred.
```
Who should be able to use it?
1. Just you
2. People you invite
3. Anyone at <their company domain>
```
Then, only if the app stores data, confirm the table names you are about to
declare, because coworkers see them on the app's label page.
### Publish from the folder that holds the app
Spryloom needs a folder containing a `package.json` or an `index.html`. In a
repository with several projects, that is the app's own folder, not the root. A
folder with nothing to run is refused, because guessing which subfolder was meant
would be worse than asking.
### Publishing a page
A report, a document, a dashboard of fixed numbers, or a prototype with nothing
saved is a **page**: plain files, no server. Publish it as one. It opens instantly,
costs the user nothing to keep, and sits behind the same sign-in as an app.
- **One file:** pass the `.html` or `.md` file itself to `spry publish`. Markdown is
turned into a readable page. Nothing is written next to the file.
- **Several files:** a folder with an `index.html` and no `package.json`. Images,
CSS and JavaScript next to it come along.
- **A Vite or React app with no server:** publish the folder as usual. Spryloom
runs its build and publishes what the build writes (`dist`) as a page, and
client-side routes work. Give it no `start` script and no server framework,
and declare `backend: none`.
- **Libraries:** a page may load scripts and styles from cdnjs.cloudflare.com,
cdn.jsdelivr.net and unpkg.com, and fonts from Google Fonts. Anything else it
loads must be saved into the folder and linked there, or browsers block it.
- **What it can't do:** a page's scripts can only talk to the page itself, so it
can't call an API or save anything. Don't declare a database, jobs, email or
outside services for a page; they are refused.
- **When it outgrows a page:** once it needs saved data, a schedule or email, add
a `package.json` with a start script and publish again under the same name. It
becomes an app at the same address.
### Write the manifest
Write `spryloom.yaml` in the project root before publishing. You know what the
app needs because you wrote it, so declare it rather than making the platform
guess.
```yaml
app:
name: Vendor Invoice Reconciler
description: Reconciles vendor invoices against purchase orders.
runtime:
frontend: react
backend: node
build: npm run build
start: node server.js
access:
visibility: company
domain: acme.com
signin: [email_link]
admins: [priya@acme.com]
data:
postgres: true
tables: [invoices, purchase_orders, matches]
uploads: false
```
The description is not a formality. It appears in the invitation email and on the
app's label page, and it is how a coworker decides whether to open something a
colleague generated with an AI. Write one sentence saying what the app does for
the person using it.
`signin` takes `email_link` today. `google` is accepted and does nothing yet, so
do not write it: the app's label page tells coworkers how they will actually sign
in, and declaring a method that is not there would make that page wrong.
See `references/manifest.md` for every field.
### Publish
Publish with the `spry` command, run in a terminal from the folder that holds
the app. When `spry` is not installed, `npx -y spryloom` is the same command and
needs nothing installed, so read every `spry` in this skill that way.
`spry` talks to Spryloom over the network. If a command fails because it cannot
reach Spryloom, ask to run it again with network access rather than working
around it.
**Signing in, once per machine.** Run `spry whoami` first. If it says "Not
signed in", ask the person which email address to use and ask
them to run this themselves, in their own terminal:
```
npx -y spryloom login --email you@company.com
```
Signing in waits for the person to open a link Spryloom emails them, and shows a
short code they must check against the page before approving, so it is theirs
to run, not yours. There is no password. Once `spry whoami` names them, carry on.
**Then publish:**
```
spry publish
```
Pass a file or folder when the app is not the current folder:
`spry publish report.html`, `spry publish ./app`. Never stop at "Spryloom is not
connected": signing in and `spry publish` always work.
A publish takes a few minutes: Spryloom builds the app, sets up its database
and waits for it to answer before switching over. `spry publish` shows each stage
while it runs; if the user asks, say which stage it is on. Do not start another
publish while one is running: a second one only watches the first.
Report back exactly what happened: the address, who can sign in, what was
created, and anything that needs the user's attention. Do not narrate the steps
while they run.
**If the command is cut off or stops watching**, the publish is probably still
going: the work happens on Spryloom, not here. Check with `spry apps` before
doing anything else. Publish again only if it shows the
publish failed, never just because watching stopped.
### Then offer to invite people
```
Published: https://vendor-reconciler.acme.spryloom.app
Sign-in: anyone at acme.com
Data: 3 tables, snapshot taken
Want me to send this to anyone?
```
When you invite someone, tell the user what that person will get: an email
naming the app and who invited them, with an **Open** button that signs them in
straight away. It works once, for 7 days; after that they sign in with an
emailed link. They need no account and nothing to install.
## If the app stops
An app that runs out of memory or crashes is stopped, and `spry apps` and the
dashboard both say so rather than claiming it is fine. Start it again with:
```
spry restart my-app
```
That starts the version already there, and shows its stages like a publish.
`spry rollback` and `spry restore` do the same. Do not republish to recover from a crash:
the code has not changed, and rebuilding risks a different result from a
dependency that moved since.
## If publishing fails
The failure message says what is wrong and what to do. Fix the cause and publish
again; do not work around it.
Two rules about failures:
- **A failure caused by one of the rules in part 1 is your mistake, not the
user's.** Fix the code, say what you got wrong in one line, and publish again.
Do not ask the user to fix it.
- **Never disable a check to get past it.** If a publish is refused because the
app has no start command or declares tables it does not have, the refusal is
correct.
**If the app should act on its own**, such as a reminder, a daily digest, an
email when something is assigned, or a post to Slack, read
`references/acting.md` before writing it. Use a declared job, not a timer in
the server. Use the notification helper, not a mail library. Declare each
outside host in `egress`, from the list there.
## What not to do
- Do not suggest Vercel, Railway, Fly, Render, or a VPS. The user asked for their
coworkers to be able to use this.
- Do not add authentication to the app. Spryloom signs people in and tells the app
who they are through a header. Auth code inside the app is redundant and will
conflict.
- Do not create a Dockerfile unless the app genuinely needs one. Spryloom writes a
correct one. If a Dockerfile already exists, it is used as-is.
- Do not put secrets in `spryloom.yaml`. It is committed to the repository.
## Reading who is signed in
Spryloom signs people in and tells the app who arrived, in two headers. The app
never implements sign-in, and never verifies anything.
```js
const email = request.headers['x-spryloom-email']; // who they are
const role = request.headers['x-spryloom-role']; // 'admin' or 'user'
```
Trust them. Spryloom deletes every `x-spryloom-*` header that arrives with a
request before it decides anything, so the only way one reaches the app is from
Spryloom itself. A client that sends one gets its request refused outright.
Use the header rather than anything the client submitted. If a form carries an
author field, ignore it and use `x-spryloom-email`: the header cannot be forged
and the form can.
`x-spryloom-identity` also arrives, carrying the same facts signed, for an app
that would rather check them itself. Most apps should not bother.
**Roles.** `admin` is the person who published the app and anybody listed in
`access.admins`. Everyone else is `user`. Use the difference where it matters —
who may delete things, who sees everything — and nowhere else.
Referenced files: 2 — file references are metadata, not package contents.
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
Package observed Nov 3, 2026.
plugins_6ac5b4d409a48191b5fd6e2f98a7748a
Download plugin data (JSON)