rpgjs-studio
Use the RPGJS Studio HTTP API to create or manage a 2D RPG game. Trigger this skill when Codex needs to CRUD maps, map events, database records, media assets, or general project settings in RPGJS Studio, especially when the task should be done through `curl` or another HTTP client with an API key and configurable base URL.
How do I install this agent skill?
npx skills add https://github.com/rsamaium/rpg-js --skill rpgjs-studioIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill allows managing an RPGJS Studio project via its official HTTP API. It performs standard CRUD operations on game assets like maps, actors, and items using curl. It implements security best practices by handling sensitive API keys via environment variables, explicitly forbidding the storage of secrets in local context files, and using a trusted vendor domain.
- Socketpass
No alerts
- Snykwarn
Risk: MEDIUM · 1 issue
What does this agent skill do?
RPGJS Studio API Skill
Use this skill to execute content-management tasks against an RPGJS Studio instance.
Public game database reads resolve actor and enemy appearances in batches per project, preserving media links and explicit overrides. See references/database.md for the response behavior.
Image and cinematic generation
For a new character, use type: "spritesheet" with metadata.generationMode: "idle" to create a transparent 1024×768 image of four static poses (down, left, right, up) in a 2×2 grid for 5 credits. Studio then opens /media/apps/character-editor/:id; create named animations there through spritesheet.ai as separate media associated with the base character, using the idle sheet as the reference image. Existing spritesheet animation requests remain 15 credits. See references/media.md.
For deletion in the Studio editor, use the project-scoped character animation endpoint documented in references/media.md; it removes the animation reference and stored image together.
Base64 references accept MIME parameters; recognized PNG/JPEG/GIF/WebP signatures take precedence over missing or incorrect MIME headers, including text/xml. Invalid references return HTTP 400 and refund the startup debit.
Media generation debits metered API-key credits on execute before enqueueing; estimates do not debit. Startup failures are refunded, and terminal execution failures use a persisted refund step. A queued response is acceptance only: poll the returned instance. See references/media.md for billing and reference storage behavior.
To play a video in an event, use show_cinematic with { "video": "media-id", "allowSkip": false, "bgm": "pause", "preload": true }. Only video is required: skipping and preloading default to true; bgm defaults to "duck" (15% music volume). "pause" resumes music afterwards. Adjacent video blocks share one overlay. See references/media.md for details; no map-to-video association is required.
Direct map generation release
Express the requested map visual style in objective, in the user's language.
The generator follows that style and only defaults to high-definition pixel art
when the objective specifies none. Terrain and wall materials preserve the
concept art direction. See references/maps.md; do not add a separate style
field to the API payload.
For generation without an assistant, read the durable workflow and direct progress
sections in references/maps.md. Use the existing prepare/execute endpoints,
explicit credit confirmation, project-scoped status and intermediate preview.
Require finalized: true and mapId before presenting a saved result. Never infer
completion from the workflow status alone. Safe spawn is tracked upstream in
RSamaium/RPG-JS#367; do not implement a local collision workaround.
Inputs
- Check whether a local
RPGSTUDIO.mdfile exists in the current working directory. - If
RPGSTUDIO.mdexists, treat it as local project context and read it first. - Use it to recover persistent values such as:
BASE_URL- any other project-specific instructions relevant to API usage
- Do not recover, request, or persist a
projectId. The API key is scoped to the RPGJS Studio project, so work directly on the user's requested resource. - If
RPGSTUDIO.mddoes not exist, continue normally. - Resolve
BASE_URLfrom the user if provided. - Default
BASE_URLtohttps://rpgjs.studiowhen the user did not specify another host. - Read the API key from the environment variable
RPGSTUDIO_API_KEY.
Mandatory startup workflow
- Check whether
RPGSTUDIO_API_KEYexists before any API call. - When checking
RPGSTUDIO_API_KEY, never print its value in the terminal and never echo it back in the response. - If the variable is missing or empty, stop and tell the user to create an API key first on
${BASE_URL}/api-keys, then exportRPGSTUDIO_API_KEY. - Build authenticated requests with these headers:
-H "x-api-key:$RPGSTUDIO_API_KEY"
-H "Content-Type: application/json"
- Prefer
curlfor HTTP calls. Use another HTTP client only if there is a clear reason. - Fail fast on authentication errors. If the API returns an invalid-key style response,
401, or403, stop the task and tell the user to verify the key or contact support. - Read only the reference file that matches the user task:
references/database.mdreferences/maps.mdreferences/events.mdreferences/event-examples.md
references/blocks.mdreferences/media.mdreferences/settings.mdreferences/project-env.mdreferences/mmorpg.md
Local memory file
Use RPGSTUDIO.md as a lightweight local memory file for the current project.
- Read it at the start if it exists.
- Reuse values already stored there instead of asking again.
- After the task, update or create it with stable, non-secret context discovered during execution.
Typical contents:
- last used
BASE_URL - project-specific conventions or notes useful for future calls
Do not use RPGSTUDIO.md to select a project. The current RPGSTUDIO_API_KEY already identifies the target project, so proceed directly with the user's request.
Never store secrets in this file.
- Do not store
RPGSTUDIO_API_KEY. - Do not print
RPGSTUDIO_API_KEY. - Do not copy raw secret values into logs, terminal output, or markdown.
Request pattern
Define the base command once and reuse it:
BASE_URL="${BASE_URL:-https://rpgjs.studio}"
curl -sS \
-H "x-api-key:$RPGSTUDIO_API_KEY" \
-H "Content-Type: application/json"
For write operations, prefer:
curl -sS -X POST "$BASE_URL/..." \
-H "x-api-key:$RPGSTUDIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{...}'
Execution rules
- Start by identifying the resource domain, then load the matching reference file.
- Use REST semantics:
GET,POST,PUT,DELETE. - Resolve foreign keys before creation or update:
- Search media with
/api/media?query=<search>. - Search database records with
/api/database/:type?query=<search>. - If a matching dependency exists, reuse its returned
_id. - If not found, create it first, then continue with the returned
_id.
- Search media with
- Never call a project listing endpoint just to choose a project. The API key determines the project context.
- When the user asks to create game objects, send the smallest valid payload first, then enrich it only if the task requires more fields.
- Reuse IDs returned by the API instead of guessing them.
- When the user provides a database
_idfor a read, update, or delete task, callGET /api/database/:type/:idfirst and inspect the existing record before deciding the payload or reporting the content. - If an endpoint shape is uncertain, inspect the response from a nearby
GETendpoint first and adapt from that live payload. - Do not continue after an auth failure.
- If a missing dependency would require AI media generation, always call the unified media generation endpoint with
action: "estimate"first. - After the estimate, report the required credits to the user and ask for confirmation before calling
action: "execute". - Never start an AI media generation directly without this estimate and confirmation step.
- For
POST /api/maps/generate, rely onreferences/maps.mdfor the AI map generation workflow and endpoint-specific failure behavior. - Summarize the exact records created, updated, or deleted in the final response.
- When a task reveals stable project context such as
BASE_URLor local conventions, persist that non-secret context intoRPGSTUDIO.mdfor future runs.
Common checks
databasetask: read references/database.mdmaptask: read references/maps.mdeventtask: read references/events.mdevent exampletask: read references/event-examples.mdevent workflow blocktask: read references/blocks.mdmediatask: read references/media.mdsettingstask: read references/settings.mdproject envtask: read references/project-env.mdMMORPG publicationtask: read references/mmorpg.md
Current schema notes
- An authenticated Studio session can publish the current project with
POST /api/mmorpg/publish. Publication prepares every map before sending any update. Failures return a stablecode,stage, and optionalresourceId; seereferences/mmorpg.mdfor the response contract.GET /api/mmorpg/publicationreports whether this project's MMORPG has been published successfully and supplies its playable URL. Preparation caches source reads only for that publication. Versioned R2 publication and active-room-only propagation are implemented for RPG-JS #374 in the framework working tree and integrated in Studio's local configuration throughMMORPG_PUBLICATIONS; release and production integration remain pending. Read the framework API section ofreferences/mmorpg.mdbefore integrating. - A character event whose only behavior is one dialogue can store it directly in
triggers[].typeData.dialogueon anonActiontrigger. It does not need a block collection. Resolve bothgraphic(spritesheet) andfacesetmedia first; propose confirmed generation when either type has no suitable result. An explicit faceset-generation refusal may omit the faceset. If the user explicitly forbids all asset generation, create the functional event with whichever coherent searched appearance IDs exist and omit any missinggraphicorfaceset. - For a character that sells a database item, follow the canonical shop
workflow: resolve or create the real item with a positive
price, then create onecall_shopblock referencing its_id. The RPGJS shop charges the price before granting the item. Do not synthesize manual choice/gold/item branches or placeholder resource identifiers. - Map-generation
followUpPlan.events[]accepts an optional pixelposition: { x, y }. It must stay insidewidth * 48byheight * 48; Studio validates it through a compact event-map context and falls back to the map start when it is absent or invalid. - New assistant map generations include a persisted description, an optional
source
assistantConversationId, and afollowUpPlan.musicsuggestion with{ id, title, description, prompt }. Historical API callers may omit the conversation id and music suggestion. show_textblocks may setinputEnabled: trueand must then provideinputVariableId, the_idof a database variable receiving the submitted string or number. Cancelling the input storesnull; seereferences/blocks.mdfor the typed input options.- Maps, events, block collections, and database records support multilingual semantic search through their existing list endpoints with
query. The optionalminScoreparameter accepts0..1and defaults to0.40; see the matching resource reference for endpoint-specific filters and response shapes. - Project environment variables are managed with authenticated project routes:
GET /api/projects/:projectId/env,PUT /api/projects/:projectId/env/:name, andDELETE /api/projects/:projectId/env/:name. Plain values are returned in responses; secret values expose onlyisSetand must never be logged or printed. - Playable characters are database Actors under
/api/database/actors. The public runtime database includes Actors and the public project exposesmainActorIdso a new game can preselect the project hero. - Playable identities are database Classes under
/api/database/classes. New Actors require a validclassId; existing legacy Actors without one remain readable. Classes ownname,description,icon, and level-gatedskills, while Actors own appearance, statistics, inventory, and equipment. A Class assigned to any Actor cannot be deleted until those Actors are reassigned. - Character spritesheet metadata can contain
illustration, the media_idof a transparent 4:5 JRPG character illustration inherited by every Actor using that spritesheet. AI generation typeillustrationcosts 5 credits. - Database create and update validation treats
nullfrom non-nullable form fields as an omitted value. When the JSON Schema declares adefault, that default is applied instead; explicit0values and explicitly nullable fields are preserved. Optional object groups containing only omitted values, such as{ "hitbox": { "width": null, "height": null } }, are omitted as well. A validation400identifies the first invalid field with a dotted path inmessage, for example{ "message": "parameters.pdef.start: Required" }. menus.characterSelectconfigures the new-game Actor selector. It supports every Actor withsettings.allActors: true, or an ordered list of Studio Actor_idvalues insettings.actorIds. The selection is player/save-local and does not mutatemainActorId.- Event workflows can open the same selector with
call_character_selectand can assign a Class to the active player withchange_class. The selector can expose every Actor or an ordered unique subset and can optionally allow cancellation. Applying a selected Actor preserves acquired progression; seereferences/blocks.mdfor the exact payloads. - Maps may expose a shader terrain
terrainLayerobject withversion: 1,mode: "control-texture", pixelwidth/height,tileSize,palette, andcontrolTexturemetadata. The control texture is RGBA8; terrain palette index is encoded asR + G * 256, optional light usesBwith128as neutral, andAstores terrain mask coverage for pixel brush strokes. Soft edges are computed from transition/blend metadata at render time. Legacy tile grids are normalized intotileSize x tileSizeblocks, but brush edits can update individual world pixels in the control texture. - Game or editor integrations that need to reproduce Studio terrain rendering must use
@rpgjs/render-map2d. Decode terrain and control images in the host, callnormalizeTerrainMap()andprepareTerrainMap(), then render world-aligned regions withrenderTerrainRegion(). Do not reimplement road, carpet, nine-slice, water, or morphology pixels in an Angular, Pixi, or CanvasEngine adapter. POST /api/map-generationsis the project-scoped confirmed Cloudflare Workflow for map creation and editing. It accepts optional terrain/element-set references, generates missing assets, extracts semantic terrain patterns, builds terrain/morphology, preserves separated element positions, and persists the final map. Use prepare, explicit confirmation, execute, then poll the returned instance untilcomplete; the response includes the finalmapId. Failed terminal responses expose refund/retry flags, andPOST /api/map-generations/:instanceId/retrystarts a fresh instance only after the former attempt is refunded. Targeted edits use normalized polygons and inherit current assets when omitted; seereferences/maps.md.- Maps may expose a terrain morphology
terrainMorphologyLayerobject withversion: 1,mode: "terrain-morphology", pixelwidth/height,tileSize, andfeatures[]. Each feature is either{ kind: "hole", params, strokes }or{ kind: "wall", params, strokes }; strokes store world-pixelpoints[]andradius. Hole params supportdepth,roundness,roughness, optional facadetextureId, optional bottom-fillfillTextureId,fillHeightclamped to0..100, and optional per-holewaveIntensity,waveDirection, andwaveSpeed; omitted wave fields inherit the map'swaterAnimationvalues, whilewaveIntensity: 0keeps the fill static.textureIdis not used as the bottom-fill fallback. Wall params supportheight,roundness,roughness, optional facadetextureId,surfaceTextureId,trimTextureId,baseTextureId, andrenderMode: "procedural" | "collision-only"; collision-only generated walls block movement but defer their visual towallSurfaceLayer.wallStyle: "rock"renders stratified rock faces with a rock rim and a floor contact shadow; Studio dug caves use it on a wall that covers the whole map, carved by erase operations. Studio also storesrockTexture: "masonry" | "natural"on rock walls (procedural face texture, defaultmasonry: cut stone courses;natural: irregular weathered rock facets). WithouttextureId, the game renders these faces per pixel from the wall mask, like the editor: lit at the top, darker at the foot, at most 55% of the opening below, with a contact shadow in the wall base. The editor's wall smoothness control maps toroughness = 1 - smoothness. The renderer merges hole/wall masks as signed terrain levels before drawing and merges morphology strokes into terrain collision as blocking cells. The Studio editor levels holes and walls when they are drawn: a wall drawn over a hole erases the hole there (back to walkable ground) and a hole drawn inside a wall erases the wall there, so saved maps only contain ordinary paint and erase operations. - Generated maps may expose
wallSurfaceLayerwithversion: 1,mode: "wall-surface", map-pixel dimensions,materials[], and an external RGBA8controlTexture.Ris the zero-based material index,Gis0=void,1=top,2=face, or3=trim,Bis reserved, andAis coverage. Each material references dedicated top, face and trim texture ids plus an optional base id. Studio renders these masks pixel-exactly and edits/undoes them together with wall collision morphology.PUT /api/maps/:mapIdpersists edits fromwallSurfaceLayerplus base64wallSurfaceControlTexture; the API stores the PNG outside the map document. - Maps may expose
waterAnimation: { enabled, speed, intensity, direction }for map-level liquid animation defaults.directionis measured clockwise in screen-space degrees (0right,90down) and defaults to90. Filled holes inherit these defaults unless their params override them; wave highlights are derived from each fill's local color or texture instead of using a fixed blue tint. PUT /api/maps/:mapIdsupports partial section updates. Omitted map fields are preserved, so prefer sending only changed sections:startX/startYfor start position,eventsfor placements,terrainMorphologyLayerplus optionalwallSurfaceLayer/wallSurfaceControlTexturefor generated wall geometry, terrain fields for terrain/control texture, element layer arrays for objects, and tileset params for media selection.- Maps may expose top-level lighting settings as
lighting: { sun: { enabled: boolean, intensity: number } }. The sun intensity is clamped to0..1; when enabled, runtime/editor integrations can use it to display automatic shadows for walls, characters, and elements. - Maps may expose
mapLoadBlockCollectionId: string | null. When set,GET /api/game/maps/:mapIdhydrates that collection intomapLoadBlocks, and the RPGJS Studio runtime executes those blocks from the servermap.onJoin(player, map)hook when a player enters the map. This workflow has a player and map context, but no current event context. - Event workflow builders can use execution profiles.
eventBuilderProfiles.mapLoadexposes blocks whoserequiredCapabilitiesfit a player-aware map context and removes current-event field choices from compatible schemas. - Terrain media metadata exposes
sourceTexture, directrowsandcolumns,textureGrid: { columns, rows, tileSize? },terrainTextures[], andtransitions[]. EachterrainTextures[]entry is{ id, index, label, collision?, renderTileSize?, renderingStyle?: "pixel-art" | "hd-2d", defaultRenderMode? };indexis the atlas-cell source of truth,collisionmarks painted map cells as blocking,renderTileSizecontrols the repeated texture size in map-editor world pixels, defaulting to the legacy320pattern size when absent, andrenderingStyle: "hd-2d"enables smooth map-editor scaling while omitted metadata preserves legacy pixel-art rendering.defaultRenderModesupportshard,fade,nine-slice,water, andcustom:hardis crisp,fadeuseswidth, the UIgrass edgepreset is stored asfadewithwidth: 12andcurve: "sharp"and renders as a grass fringe,nine-slicestores a source-cell-pixelcenter: { x, y, width, height }, repeats that center, projects the surrounding border bands along every painted contour, and always prevents fade bleed,wateris the stored generic liquid mode and keeps the atlas texture while deriving clipped tint, shoreline depth, static ripples, and edge glints from the atlas cell color so lava/swamp/acid/oil do not get a fixed blue outline, and unknowncustommodes fall back to an edge highlight unless theirshaderKeyis liquid-like.transitions[]stores exception rules{ from, to, mode, priority? }between terrain ids; it is not a generated Wang transition matrix. Studio terrain generation defaults to a4x4source texture atlas in the UI and persists the generated atlas directly; it no longer creates Wang/autotile output through the image-processing container. Generation requests can setmetadata.sourceTextureColumnsandmetadata.sourceTextureRows; Studio also sendsterrainAtlasColumns,terrainAtlasRows,terrainStyleId, andterrainStylePromptso the server prompt can build a shader-friendly seamless material atlas. Element set (tileset) generation can passmetadata.terrainReferenceImageandmetadata.terrainReferenceMediaIdto use an existing terrain image as a style-compatibility guide; the image data is execution-only and should not be persisted. - Playable character settings are database actors under
/api/database/actors; the project stores the selected actor_idinmainActorId. UseGET /api/database/actors/mainandPUT /api/database/actors/:id/mainto read or change the main hero. The actor owns appearance, hitbox, progression, inventory, animations, and skills. - Actor
hitbox: { width, height }uses positive RPGJS-pixel dimensions and defaults to32 x 32when omitted. The public game project and offline export resolvemainActorIdback to the runtime-compatiblehero,animations, andskillsfields. - Database actors and enemies support combat animation spritesheet media IDs under
animations:attack,hurt,die, andcastSpell. - Linked character animations named
cast,Cast Spell,castspell,castSpell, orcastSkillresolve to the canonicalanimations.castSpellfield; explicit actor/enemy overrides retain precedence. - Actors and enemies automatically inherit a selected character sprite's linked faceset and named combat animations. Set
facesetor individualanimationsmedia IDs only to override those defaults; see references/database.md. - The RPGJS starter runtime uses these spritesheets in action battle: attack actions, damage/hurt feedback, delayed death removal, and skill/cast usage can temporarily switch to the configured spritesheet.
- Database enemies support action battle AI options under
behavior:enemyType,attackCooldown,visionRange,attackRange,dodgeChance,dodgeCooldown,fleeThreshold,attackPatterns,patrolWaypoints, andgroupBehavior. - Database enemies expose a lightweight preview endpoint:
GET /api/database/enemies/preview?ids=<id1,id2>. Use it when only_id,name, andgraphicare needed for known enemy ids instead of listing or reading full enemy records. Send at most 100 distinct ids per request. GET /api/eventsreturns the legacy event array by default. Addpageorlimitto opt into paginated responses:GET /api/events?page=1&limit=24returns{ data, meta }. Paginated event lists default tosortBy=createdAt&sortDirection=descand supportsortBy=createdAt|updatedAt|name,sortDirection=asc|desc,eventType=all|character|enemy|free, andassignment=all|assigned|unassigned.- Database actors and enemies support level-gated skill acquisition under
skills:{ skillId, level }. - Database skills support media IDs under
icon,animation, andsound. - Project settings support global
audio.uisemantic cues (navigate,confirm,cancel,open,close,error) shared by every native menu. General Action Battle defaults live incombatAudio(battleMusic,attack,skill,hit,hurt,die). Both groups are edited in the Project Audio tab. - Title-screen background music and image are configured with
menus.titleScreen.settings.backgroundMusicandbackgroundImage. Maps do not override combat audio. Database enemies can override battle music and source/reaction cues underaudio.combat. Database skills usesoundfor casting andimpactSoundfor impact; all sound values are Studio media IDs. - Generate full-scene title-screen or in-game artwork with media generation type
image. It produces an opaque, center-cropped 16:9 landscape media record; this is distinct fromillustration, which remains a transparent 4:5 character portrait. Use the resulting media_idinmenus.titleScreen.settings.backgroundImage. - Game/runtime code can read media data usable in the game with
GET /api/game/media/:mediaId; usereferences/media.mdfor details. - Media type changes should use
PUT /api/media/update/:mediaIdinstead of the metadata-only admin endpoint; this synchronizesmetadata.typewith the roottypefield. - Game map responses from
GET /api/game/maps/:mapIdhydrate eventparams.graphic,params.faceset,triggers[].graphic, andtriggers[].facesetas media objects when possible, and expose the active page hitbox asevent.hitbox: { width, height }; usereferences/maps.mdfor the runtime response shape. - Event workflow blocks can call or spawn reusable game events with
call_common_eventandspawn_common_event. Both usecommonEventId;spawn_common_eventcan resolve its position fromplayer,current_event,variable, orfixed. - Event page triggers use
trigger: "player_touch"andtrigger: "event_touch"in page payloads. Runtime trigger payloads store both astype: "onTouch"and distinguish them withtypeData.touchTarget: "player" | "event"; missingtouchTargetmeans player touch for compatibility. In event/event touch workflows, variable and switch blocks use map variables. Player-only blocks receive the first player currently on the map as a temporary fallback until explicit affected-player targeting exists. - Event page
hitboxsupports{ width, height }in RPGJS pixels. Missing hitbox means the runtime default32 x 32. Media/graphic scale changes only the displayed sprite size; it must not alter hitbox width/height. - Event page
optionssupportsdirectionFix,through,alwaysOnTop, andalwaysOnBottom. Use only one rendering layer flag at a time:alwaysOnTopdraws the event above nearby characters, whilealwaysOnBottomdraws it below nearby characters. - Event workflow blocks can use
set_hitboxto calltarget.setHitbox(width, height)on$player,$this, or a map event id.widthandheightare positive RPGJS-pixel dimensions and are not scaled by the target graphic scale. - Event workflow blocks can use
camera_followto callplayer.cameraFollow(target, { smoothMove }). The target is resolved fromeventIdwith$player,$this, or a map event id.smoothMovedefaults totrue; optionaltimeandeasecreate the advanced smooth transition object supported by RPGJS. Theeasefield is a dropdown enum of common easing names such aslinear,easeInQuad,easeOutQuad, andeaseInOutQuad. - Event workflow variable writes must use the public
set_variableblock.change_variableis legacy runtime compatibility only and must not be generated for new payloads.set_variablesupportsvalueSourcevaluesconstant,variable,random,player_x,player_y,player_direction,map_id,gold,player_id,player_name,level,hp, andsp.
For enemy combat pacing, use the per-pattern behavior.attackProfiles timing
overrides documented in references/database.md; retain omitted values to
inherit the engine defaults.
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/rsamaium/rpg-js/rpgjs-studio">View rpgjs-studio on skillZs</a>