From layerline
Manage Layerline Storage (LS) files and the per-entity File Boxes that group them. Use whenever the user asks Claude Code to find a file in Layerline by path, list files in a project or folder, get a download URL, restore an old version, lock/unlock a file before editing, share a file or folder with an external link, configure cloud sync rules, or attach files to an asset/task/shot/GDD-asset's File Box. Covers file ops (list/find/rename/move/delete), version history and restore, exclusive locks with audit trail, presigned download URLs (~1h TTL), share links (public/password/email-invite), include/exclude sync glob rules, storage usage stats, and the File Box pattern for grouping LS files under a higher-level entity.
How this skill is triggered — by the user, by Claude, or both
Slash command
/layerline:storageThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Workflow for the file storage layer in Layerline (`mcp__layerline__ls_*` tools + the file-box tools).
Workflow for the file storage layer in Layerline (mcp__layerline__ls_* tools + the file-box tools).
A file can exist in LS without being attached to any box. Most production files end up in at least one box (the asset box for the asset they belong to).
ls_list_files(projectId, path?, lockStatus?, search?, limit?, offset?, sortBy?, sortOrder?)
// path: prefix (e.g. "Characters/")
// lockStatus: "locked" | "unlocked"
// sortBy: "name" | "path" | "updatedAt" | "size"
// sortOrder: "asc" | "desc"
ls_get_file(fileId)
ls_find_file_by_path(projectId, path) // exact match; returns { found: false, ... } if missing
ls_rename_file(fileId, name) // changes display name only
ls_move_file(fileId, path) // changes the path within the project
ls_delete_file(fileId) // soft delete
path is the project-relative path including filename, e.g. "Characters/Hero/model.fbx". Don't prepend the project name.
ls_get_version_history(fileId, page?, limit?) // newest first
ls_get_version(versionId)
ls_get_download_url(fileId, versionId?) // omit versionId → current version
ls_restore_version(fileId, versionId) // creates a new version that copies the restored one
ls_get_download_url returns a presigned S3 URL that's good for ~1 hour and doesn't need an auth header — fetch it with any HTTP client. Use this when you need to actually read the bytes (e.g. inspect a config, copy a model into a Godot project).
There is no upload tool exposed via MCP. Uploads happen through the desktop client or the REST upload endpoint. If the user asks "upload this", explain they need to drop the file via the Layerline app — the agent can't push bytes through MCP.
Exclusive locks: only the locker (or admin via force-unlock) can push new versions while a file is locked.
ls_lock_file(fileId, reason?)
ls_unlock_file(fileId) // owner only
ls_force_unlock_file(fileId, organizationId?) // org admin/owner only
ls_get_lock_status(fileId) // { locked: true, ... } or { locked: false }
ls_get_lock_history(fileId) // audit trail
Use locks before "I'm starting work on this rig", and unlock when you push the new version. Don't force-unlock without authorization — it stomps another user's work in progress.
ls_get_file_activity(fileId, page?, limit?)
ls_get_project_storage_activity(projectId, page?, limit?)
ls_get_storage_usage(organizationId?, projectId?) // bytes used, file/version counts, quota
ls_create_share_link(projectId, fileId? | folderPath?, shareType, authMethod, password?, expiresIn?, maxDownloads?, label?)
// shareType: "public" | "protected"
// authMethod: "none" | "password" | "email_invite"
// expiresIn: "1d" | "7d" | "30d" | "90d" | "never"
ls_list_shares(projectId, organizationId?)
ls_get_share(projectId, shareId)
ls_update_share(projectId, shareId, expiresIn?, password?, label?, maxDownloads?)
ls_revoke_share(projectId, shareId) // immediate; cannot be undone
Pick exactly one of fileId or folderPath. For password-protected shares, set authMethod: "password" and pass password. For email-invite shares, set authMethod: "email_invite" (the system handles invite emails out-of-band).
Glob patterns that include or exclude files from cloud sync at the project level.
ls_list_sync_rules(projectId)
ls_create_sync_rule(projectId, ruleType, pathPattern, isFolder)
// ruleType: "include" | "exclude"
// pathPattern: glob like "*.fbx", "Textures/**", "Backups/"
ls_delete_sync_rule(projectId, ruleId)
ls_batch_set_sync_rules(projectId, rules[]) // wipes existing, installs the new set
ls_batch_set_sync_rules is destructive — confirm with the user before calling if they didn't explicitly ask for a wipe.
A File Box groups LS files under one entity. Every project asset, task, shot, and GDD asset can have a box.
get_file_box(organizationId?, projectId, ownerType, ownerId)
// ownerType: "task" | "shot" | "gdd_asset" | "project_asset"
// returns { exists: false } if no box yet
get_or_create_file_box(organizationId?, projectId, ownerType, ownerId, displayName?)
list_file_box_files(boxId, limit?, offset?)
attach_file_to_box(boxId, lsFileId, notes?)
detach_file_from_box(boxId, fileId) // soft removal; LS file untouched
reattach_file_to_box(boxId, fileId) // restore a detached link
get_file_box_activity(boxId, cursor?, limit?)
delete_file_box(organizationId?, projectId, boxId) // soft delete; LS files untouched
Use get_or_create_file_box when you're about to attach files and don't know if the box exists — it's idempotent.
list_file_box_files returns items that link to LS file ids. Pair the returned lsFileId with ls_get_download_url to get the bytes.
ls_find_file_by_path(projectId, "Characters/Hero Knight/Rigging/hero_rig.fbx").ls_list_files(projectId, search="hero_rig").ls_get_download_url(fileId) → return the URL with its expiresAt.taskId via list_tasks(projectId, search="MGP-42").get_file_box(projectId, ownerType="task", ownerId=taskId). If exists: false, the task has no files yet.list_file_box_files(boxId).ls_get_file(lsFileId) for size/version metadata.ls_find_file_by_path(...) → fileId.ls_get_lock_status(fileId) → check it's not already locked.ls_lock_file(fileId, reason="Rerigging skeleton").ls_find_file_by_path(...) → fileId.ls_get_version_history(fileId) → find the v3 entry's id.ls_restore_version(fileId, versionId). (This creates a new current version that copies v3.)ls_create_share_link(projectId, folderPath="ArtDirection/2026-Q2/", shareType="protected", authMethod="email_invite", expiresIn="30d", label="Q2 Art Direction Review").projectId and heroAssetId.get_or_create_file_box(projectId, ownerType="project_asset", ownerId=heroAssetId) → boxId.ls_find_file_by_path(projectId, "Props/Weapons/hero_sword_v01.fbx") → lsFileId.attach_file_to_box(boxId, lsFileId, notes="primary sword for Hero Knight").fileId and versionId for create_review — see layerline:reviews.ls_get_file_activity shows attach/detach events.layerline:genstudio — generate with projectId + assetName + assetTagFolder auto-uploads and attaches.npx claudepluginhub bitvoke/layerline-skills --plugin layerlineCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.