Publishing
Anyone can read the plugin store at phantm.site/plugins without an account: every listing, its README and the permissions it asks for. The package itself is only sent to the Phantom app, signed in, on a plan, or on any account for a private server plugin.
Publishing sends a packed plugin to the store. The store checks it, and a person at Phantom reads it before it's listed if it needs review. You need a Phantom account to publish, not a plan.
Pack it
npm run packThis builds the plugin, checks its manifest and writes the .tgz the store takes.
Changelog
Set phantom.changelog in package.json before you pack a new version. Players see it in Updates next to the waiting version, on your plugin's store page, and on the plugin once they've updated.
"version": "1.2.0",
"phantom": {
"changelog": "- Watches den doors as well as room doors.\n- Fixed the log emptying when the game reconnects."
}It describes that version only, so write a new one for every release. Leave it out and Phantom says the version came with no notes. See the manifest.
What the store checks
The store:
- reads the package, and refuses one with duplicate paths
- checks the manifest with the same reader the app installs with
- checks the plugin's API version against Phantom's
- refuses a version that isn't newer than every version already sent for that plugin, including ones that failed
- refuses a plugin id that belongs to another account
- reads the built code as text, without running it, for
eval(,new Function(, code or styles loaded from the internet, and lines so long a person rarely writes them
If any check fails, nothing from the package is kept.
Review
A person reads a version when it asks for any permission above the low-risk ones, when the code check flagged something, or when it asks for a permission the listed version didn't have. That's almost every plugin that touches the game. The previous version stays listed during review.
A refused version comes back with the reviewer's note on why.
Tags
The store tags every listed plugin with what it does, so players can find, for example, everything that talks to other players live. You don't choose the tags. They come from the permissions your manifest asks for, the same ones review reads.
| Tag | Shown when the plugin asks for | What players read |
|---|---|---|
| Live | realtime, at either level | Talks to other Phantom players live. |
| Rooms | customRooms, at either level | Adds rooms to the game. |
| Automation | adventures: "act" or minigames: "act" | Plays adventures or minigames for you. |
| Trading | trades: "act" | Sends and answers trades for you. |
| Dens | dens: "act" or denShop: "act" | Changes your den or what you sell in your den shop. |
| Avatar | avatar: "act" | Moves your animal or changes how it looks. |
| Chat | chat: "act" | Says things in chat, or changes what chat shows. |
| Internet | any host in network | Talks to the internet beyond Phantom. |
| Private server | "servers": ["private"] or ["private", "animal-jam"] in the manifest | Runs on Phantom's private server, free for every account. |
On a plugin's page, Rooms reads "Shared rooms" when it asks for customRooms: "act", because that lets it put a player in a room with other people.
Private server is the only tag that comes from the manifest rather than a permission (see servers). Players without a plan browse the store by it.
Tags follow the listed version. Drop network in an update and "Internet" goes once that version is listed. Ask for realtime and "Live" appears once it passes review. Read access to an area never adds a tag on its own.
Reports
Anyone signed in to Phantom can report a listed plugin from its page on the website or in the app, as malicious, not working as described, breaking Phantom's or Animal Jam's rules, offensive, or impersonation or copied work. Phantom's staff read every report. You're never told who reported your plugin, and you can't report your own.
A report that holds up can get your plugin taken off the store. You'll see why in npx phantom-plugin status and in the app, as with any removal.
Why review is strict
A plugin can take full control of the game client and its traffic (flash, packets.modify) and change what the client loads (content). Review isn't optional, and it takes longer for a plugin that asks for everything.
Publish
You need a publishing token. It can publish your plugins and nothing else: it can't read your account, make more tokens or review. Make one in Phantom under Plugins → Developer (it's only shown once), then run this in your plugin's folder:
npx phantom-plugin login # asks for the token, and keeps it for you
npx phantom-plugin publish # builds, packs, checks and sendsphantom-plugin is the command @phantomclient/plugin-cli installs, not a package of its own, so npx phantom-plugin in an empty folder gives a 404. Run it in your plugin's folder, or use the full package name: npx @phantomclient/plugin-cli login.
publish prints the store's checks as they run and says whether the version is live or waiting for review, and why. npx phantom-plugin status shows where each version stands later, with any note from the reviewer.
On a build machine, set PHANTOM_TOKEN instead of running login. No token file is kept.
A plugin's store page shows its README, its versions and every permission it asks for, in the same words as the install dialog.
Emails
Once you've confirmed your email address, the store emails you when a version is waiting for review, when it's listed, when it isn't approved and why, and when a plugin is taken off the store or put back. Each email links to the plugin's page under Plugins in your dashboard on the website, which shows the same information.
When Phantom edits your listing
Phantom's staff can change your plugin's store page: its title, summary, author name, README, homepage and source link. They can't change the package itself, such as its id, version, permissions or code. Their text replaces yours until they hand it back, and publishing a new version doesn't undo it. The page says Listing edited by Phantom staff meanwhile.
You're emailed each time with what changed and why, and it's listed on the plugin's page in your dashboard. Once you've fixed the problem in your own text, ask for the listing to be put back.