agentleFS
MicrosoftKnown publishermicrosoft/managed-apps/plugins/microsoft-managed-apps/skills/state/SKILL.md

state

Skill34 starsChanged 4 months agoMITView on GitHub

Store and query a Microsoft Managed App's built-in state and file attachments with `ms project state` CLI schema commands and generated TypeScript clients. First, with the user signed in to the CLI, run `ms feature status --name state --json`; if `feature.enabled` is not `true`, recommend an alternative connector or data source.

  • Installs packages
  • Sends data out

We split this skill into the rules it gives an agent

27 rules. 0 are common, 11 are distinctive, and 16 are very specific to this project.

  • 0

    Common

    Most of the 6 edited versions we read keep these.

  • 11

    Distinctive

    This author's own choices. Worth a look.

  • 16

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Very specific:

    Every Microsoft Managed App can use built-in app state when the state feature is enabled for the current CLI/environment: a NoSQL store the …

    line 13
  2. Very specific:

    Before using any guidance in this skill, it is recommended that the user is signed in to the CLI.

    line 24
  3. Distinctive:

    When state is not enabled, recommend an alternative data-source path based on the user's need:

    line 41
  4. Distinctive:

    Do not suggest manual schema edits or custom proxy workarounds as a substitute for the disabled feature.

    line 50
  5. Very specific:

    Before testing data behavior locally, make sure the app has @microsoft/managed-apps-vite-plugin 0.4.2 or later (the version that added …

    line 56
  6. Very specific:

    Check the installed version first, for example with npm ls @microsoft/managed-apps-vite-plugin (or read version in …

    line 60
  7. Distinctive:

    Do not change the app architecture just to work around local data failures (no middle-tier functions, proxies, or CORS/auth workarounds).

    line 88
  8. Very specific:

    Make sure the user is signed in (ms auth status.

    line 108
  9. Very specific:

    Run ms project state generate-code after every successful schema change.

    line 116
  10. Distinctive:

    Import and use the generated TypeScript services from app code.

    line 117
  11. Very specific:

    If no schema path exists yet, start by adding the first collection with the CLI.

    line 135
  12. Very specific:

    Name property: prefer a human-readable name property for each item (put a single-string item's text there).

    line 171
  13. Distinctive:

    Only pass the flags you intend to change.

    line 183
  14. Very specific:

    Use --force only when non-interactive automation is necessary and the user already approved the removal.

    line 197
  15. Distinctive:

    Run this after every successful schema change:

    line 229
  16. Distinctive:

    Treat that folder as generator-owned:

    line 244
  17. Distinctive:

    never edit generated models, services, validators, query helpers, or manifests by hand.

    line 249
  18. Very specific:

    Import from the generated barrel.

    line 253
  19. Distinctive:

    Do not send them in write models.

    line 299
  20. Very specific:

    No filename is stored; add a separate property if needed.

    line 328
  21. Very specific:

    Feature gate first: Never use this skill's state workflow before ms feature status --name state --json reports feature.enabled: true.

    line 346
  22. Distinctive:

    Schema changes are CLI-only: Never patch the schema JSON to add properties, constraints, indexes, locale, or validation settings.

    line 348
  23. Very specific:

    Unsupported schema shapes need a decision: If the requested design needs nested objects, arrays, enums, $ref, composition keywords, …

    line 351
  24. Very specific:

    CLI attribution is automatic: Do not tell users to export MS_CLI_ORIGIN.

    line 361
  25. Very specific:

    run the narrowest relevant build/typecheck/lint for the app or package.

    line 379
  26. Distinctive:

    prefer generated services for schema-backed state behavior covered by codegen.

    line 380
  27. Very specific:

    run local gateway dev with ms app dev and verify generated-service behavior locally.

    line 381

“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

📋 Shared Instructions: shared-instructions.md — Cross-cutting concerns.

Managed Apps State with CLI schema + generated client

Every Microsoft Managed App can use built-in app state when the state feature is enabled for the current CLI/environment: a NoSQL store the app calls directly (no middle-tier function, connector, or SDK; the host attaches auth). Records are grouped into collections by an item type name; the server assigns each record an itemId.

For schema-backed state, do not edit schema JSON by hand. Use ms project state ... to change the schema, run ms project state generate-code, then call the generated TypeScript services from app code.

Mandatory feature gate

Before using any guidance in this skill, it is recommended that the user is signed in to the CLI. Run ms auth status, and if it reports no signed-in account, ask the user to run ms auth login. ms feature status never prompts for sign-in, and features that are on by default for the user's organization only apply once they are signed in, so a signed-out check can report state as disabled even when it is available to them.

Then run:

ms feature status --name state --json

Continue only when the output has "success": true and feature.enabled is true. Read the JSON rather than the human-readable output, which lists several settings that can each say "enabled". If the command fails (non-zero exit or "success": false), the feature is not found, or feature.enabled is false, stop and do not run any ms project state ... command.

When state is not enabled, recommend an alternative data-source path based on the user's need:

  • Durable relational/business data: use /add-dataverse.
  • SharePoint lists or document-backed collaboration data: use /add-sharepoint.
  • Workbook-backed tabular data: use /add-excel.
  • Mail, calendar, user profile, Teams, Azure DevOps, OneDrive, Copilot Studio, or Work IQ scenarios: use the matching /add-* skill.
  • Anything else: use /add-data-source to discover and bind the appropriate connector.

Do not suggest manual schema edits or custom proxy workarounds as a substitute for the disabled feature.

⚠️ Local testing requires local gateway mode

Generated state services require the Managed Apps local gateway path during local development. Before testing data behavior locally, make sure the app has @microsoft/managed-apps-vite-plugin 0.4.2 or later (the version that added devMode: 'localGateway'; older versions won't start the local gateway), then opt the app into local gateway mode.

Check the installed version first, for example with npm ls @microsoft/managed-apps-vite-plugin (or read version in node_modules/@microsoft/managed-apps-vite-plugin/package.json). If it is 0.4.2 or later, skip the install. If it is missing or older, install the latest with the app's package manager:

npm install -D @microsoft/managed-apps-vite-plugin@latest
# or: bun add -D @microsoft/managed-apps-vite-plugin@latest
# or: pnpm add -D @microsoft/managed-apps-vite-plugin@latest
# or: yarn add -D @microsoft/managed-apps-vite-plugin@latest

Then update the app's vite.config.ts so the managedApps() plugin call enables the local gateway, preserving any existing options:

managedApps({
  ...existingOptions,
  devMode: 'localGateway',
})

Now run local dev normally:

ms app dev

Do not change the app architecture just to work around local data failures (no middle-tier functions, proxies, or CORS/auth workarounds). Fix the Vite plugin/local gateway setup instead.

Contract

SurfaceUseDon't use
Feature gatems feature status --name state --json (feature.enabled), with the user signed in, before any state workassuming the feature is available
Schema editsms project state add, alter, remove, set-settingmanual edits to state/schema.json, ms.schema.json, or another configured schema file
Code generationms project state generate-codehandwritten model/service/validator files in the generated output folder
App data accessgenerated services, models, validators, and typed query helperstreating direct state requests as the default when codegen covers the scenario
File attachmentsdirect upload to /.ms/state/attachments, then save the returned URL through a generated servicestoring file bytes inside items
Testing data behaviorVite plugin 0.4.2+ + managedApps({ devMode: 'localGateway' }) + ms app dev; Preview for pre-deploy validationlocal dev without local gateway mode

The generated services own request shapes, ETags, typed filters, paging, validation hooks, per-user scope behavior, and service route details. App code should compose those services with UI/business logic instead of duplicating transport behavior.

Workflow

  1. Make sure the user is signed in (ms auth status; ask them to run ms auth login if not), then run ms feature status --name state --json. Stop and recommend a connector alternative unless feature.enabled is true.
  2. Find the app root (ms.config.json) and the configured schema path.
  3. Inspect existing state schema/settings with ms project state list-schema and ms project state list-settings.
  4. For each new collection, decide up front whether records are per-user (see below).
  5. Make schema changes only with ms project state ... commands.
  6. Run ms project state generate-code after every successful schema change.
  7. Import and use the generated TypeScript services from app code.
  8. Configure local gateway mode before local data testing.
  9. Build/typecheck and verify that generated services are used for behavior covered by codegen.

Schema setup

Find the app root (ms.config.json) and the configured schema path. Prefer state.schemaPath; older apps may use data.schemaPath or legacy db.schemaPath.

{
  "state": {
    "schemaPath": "state/schema.json",
    "enabled": true
  }
}

If no schema path exists yet, start by adding the first collection with the CLI. It writes state.schemaPath: "state/schema.json", creates the schema file, and sets enabled: true unless the config already sets enabled; don't ask the user to hand-configure schema wiring first. The app serves no state while enabled is false, so confirm with the user before changing an explicit false. New schemas take the machine's locale (or en-US); match the app's users with ms project state set-setting --locale <tag>.

Inspect the current schema:

ms project state list-schema
ms project state list-settings

CLI schema commands

Add a collection

ms project state add --collection task

Add properties

ms project state add --collection task --property name --type string --required true --max-length 200 --index true --index-ignore-case true
ms project state add --collection task --property done --type boolean
ms project state add --collection task --property dueDate --type datetime --index true
ms project state add --collection task --property attachment --type binary --kind binary
  • Types: string, number, integer, boolean, datetime, guid, binary.
  • Boolean flags take values: --required true, --index false, etc. They are not bare switches.
  • Indexes: at most four custom indexed properties per collection, top-level scalars only. Only indexed properties (plus itemId, name, createdTime, modifiedTime) can be filtered or sorted.
  • Name property: prefer a human-readable name property for each item (put a single-string item's text there). It is writable, indexed, sortable/filterable, and generated services treat it as the display/title field.

Alter a property

ms project state alter --collection task --property name --max-length 200
ms project state alter --collection task --property done --required false
ms project state alter --collection task --property name --max-length ""

Only pass the flags you intend to change. Empty string clears a type-specific constraint where the CLI supports clearing.

Indexes are add-only. Removing an index or changing its options (including the platform index on name) is rejected even before the first deploy, so choose --index-ignore-case and --index-ignore-accents when you add the property. Adding an index to an already-deployed property is allowed, but validate it in Preview first.

Remove a property

ms project state remove --collection task --property obsoleteField

Use --force only when non-interactive automation is necessary and the user already approved the removal. Stored values are not deleted. Collection removal is intentionally rejected; do not work around it by editing the schema file.

Change schema settings

Set exactly one setting per command:

ms project state set-setting --locale en-US
ms project state set-setting --validation true
ms project state set-setting --validation false

--validation false keeps declared indexes active but makes writes index-only/unvalidated.

Per-user collections

Make a collection per-user when a record belongs to one person (drafts, preferences, personal notes); skip it for catalogs, reference data, and anything collaborative. Decide before it holds records: ownership is immutable and can't be added to a collection that has data. The CLI has no ownership flag, so this is the one schema edit allowed by hand, and only after the user agrees: add "x-ms-ownership": "perUser" to the collection's root object (not a property), change nothing else, and regenerate.

Generated services then take a scope option: private writes/reads only the caller's records, shared writes/reads records visible to all users, and omitting it writes private and reads both. Pass it explicitly on writes. The owner always comes from the caller's token; reads include a platform-managed @ms.scope that you must not send back.

Generate the typed client

Run this after every successful schema change:

ms project state generate-code

For automation or precise diagnostics:

ms project state generate-code --json

Output is written to generated-typescript/ beside the configured schema file. For state.schemaPath: "state/schema.json", output is state/generated-typescript/.

Treat that folder as generator-owned:

  • first generation accepts a missing or empty directory;
  • replacement requires the ownership manifest and no untracked handwritten files;
  • move handwritten wrappers/hooks outside the generated directory;
  • never edit generated models, services, validators, query helpers, or manifests by hand.

App code

Import from the generated barrel. Each collection gets a service class with static methods, read/write types, and a validator: task gives TaskService, TaskRead, TaskWrite, and validateTask(item), which returns ValidationError[] for form errors (services validate on write).

import { TaskService, type TaskRead, type TaskWrite } from '../state/generated-typescript';

export async function createTask(input: TaskWrite): Promise<TaskRead> {
  // With validation on, invalid input fails with error.kind === 'validation'.
  const result = await TaskService.create(input);
  if (!result.success) {
    throw new Error(`Could not create the task: ${result.error.message}`);
  }
  return result.data;
}

export async function listUpcomingTasks(): Promise<TaskRead[]> {
  const q = TaskService.query;
  const result = await TaskService.getAll({
    filter: q.ge('dueDate', new Date().toISOString()),
    orderBy: q.orderBy('dueDate', 'asc'),
    maxItems: 50,
  });
  if (!result.success) {
    throw new Error(`Could not load tasks: ${result.error.message}`);
  }
  return result.data;
}

Direct requests to /.ms/state/{collection}/items[/{itemId}] are acceptable only with a deliberate reason to bypass the generated services. They follow the same contract: send @odata.etag verbatim as If-Match, follow @odata.nextLink to page ($skip is rejected), sort with $orderby=<field> asc|desc, and quote string and date literals in $filter (URL-encode both).

Generated-service behavior

  • Results, not exceptions: service calls return { success: true, data } or { success: false, error } (error.kind, message, status, validationErrors). Check success before using data.
  • Create/update validation: generated validators enforce the declared schema when validation is enabled. update is a full-document PUT/upsert, not a partial patch.
  • Edit with concurrency: generated edit helpers read the item, shallow-merge callback changes, validate, and send the exact quoted ETag in If-Match. Only 412 is retried.
  • Delete is idempotent: deleting a missing item succeeds, so retries are safe.
  • Server-owned fields: itemId, createdTime, modifiedTime, and @odata.etag are read-only. Do not send them in write models.
  • Queries: getAll follows every page (cap it with maxItems); getPage returns one page and a nextLink (top sets the page size). Build filter and orderBy with the typed query builder (eq, ne, gt, lt, le, ge, and, or, orderBy(field, 'asc' | 'desc')); both accept only indexed fields. rawFilter(expr) is the explicit escape hatch for raw OData filters.
  • Per-user data: for x-ms-ownership: "perUser", generated services expose scope-aware reads and writes. Do not send scope to non-per-user collections; the service rejects it with 400.

File attachments

Generated services don't upload files. Declare a reference property (ms project state add --collection note --property photo --type binary --kind image), regenerate, then upload the bytes and save the returned URL through the generated service:

const uploaded = await fetch('/.ms/state/attachments', {
  method: 'POST',
  headers: { 'Content-Type': file.type || 'application/octet-stream' }, // required
  body: file,
}).then((response) => response.json()); // { id, url, contentType, size }

const saved = await NoteService.update(note.itemId, { ...noteFields, photo: uploaded.url });

Display it with <img src={note.photo} />.

  • Save within 15 minutes, or the unreferenced upload is garbage-collected. Store url verbatim.
  • Attachments have no DELETE or PUT: save the property as null (or delete the item) to remove one, and upload a new file to replace it. A file belongs to one item (409 otherwise).
  • No filename is stored; add a separate property if needed. Limits: 10 MiB per file, 10,000 files and 1 GiB per app. Use a real image Content-Type for <img>; SVG is always downloaded.

Preview has its own state

ms app play --mode preview --commit <sha> (full SHA, after ms app build --commit <sha>) runs the app against a separate Preview store: same collections, different records. Test writes, validation, and schema/index changes there before ms app deploy. Preview only engages when the previewed commit differs from the deployed one. After deploying, click Refresh on the app's New version available banner before testing schema changes; a plain reload keeps the old schema.

To purge Preview records (with the user's explicit approval, see rules), run ms project state clear --force --json --non-interactive in the app folder. isComplete: false is normal because deletion finishes in the background; don't retry, and wait a minute or two before relaunching Preview or deploying.

Rules / gotchas

  • Feature gate first. Never use this skill's state workflow before ms feature status --name state --json reports feature.enabled: true.
  • Schema changes are CLI-only. Never patch the schema JSON to add properties, constraints, indexes, locale, or validation settings. The only exception is per-user ownership, as described above.
  • Unsupported schema shapes need a decision. If the requested design needs nested objects, arrays, enums, $ref, composition keywords, pattern, or defaults and the CLI cannot represent it, stop and ask. Do not silently switch to manual schema editing.
  • Indexes are add-only. The CLI rejects removing an index or changing its options, deployed or not. Decide index options when adding a property, and Preview any index added to a deployed property before live deploy.
  • Never drop a declared collection/item type by hand. Collection removal is not a supported CLI write.
  • Do not run ms project state clear unless the user explicitly asks to discard all Preview state for the app/environment. It is not part of schema editing or code generation.
  • CLI attribution is automatic. Do not tell users to export MS_CLI_ORIGIN; the host hook adds it for ms invocations unless the user already set a value.

Verification

ms feature status --name state --json
ms project state list-schema
ms project state list-settings
ms project state generate-code --json

Then:

  • confirm ms.config.json has enabled: true on its state (or data/db) section;
  • confirm the app has @microsoft/managed-apps-vite-plugin 0.4.2 or later;
  • confirm vite.config.ts calls managedApps({ devMode: 'localGateway' }) or preserves existing options while adding devMode: 'localGateway';
  • run the narrowest relevant build/typecheck/lint for the app or package;
  • prefer generated services for schema-backed state behavior covered by codegen;
  • run local gateway dev with ms app dev and verify generated-service behavior locally;
  • preview the committed build with ms app play --mode preview --commit <sha> before deploying.

Download now (ZIP)

  • Other versions8 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 8

    1. cwinvestments/memstack★ 425same name
    2. spmtitsolution/OpenBA-Kit★ 38same name
    3. synaptiai/agent-capability-standard★ 6same name
    4. aihu-project/aihu★ 4same name
    5. aigengame/skills★ 2same name
    6. vlting/claude-skills★ 2same name
    7. gr219/OpenBA-Kit★ 0same name
    8. vbrevik/claude_code_skills★ 0same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • Used alongsideProjects with it also use discover, delegate and 1 more.

    Other files people use alongside this one.

    Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
    • Itsokay-coSkill

      discover

      Automated pattern discovery — finds what correlates with your best and worst sleep nights. Scans workouts, meals, caffeine, tags, gut scores, and timing patterns. Use when the user wants to know what actually affects their sleep.

      Also in 3 projects that use this

    • scott2bSkill

      delegate

      Intelligently analyzes tasks and delegates them to the most appropriate AI system when delegation adds value (project, gitignored)

      Also in 3 projects that use this

    • Microsoft AzureSkill

      verify

      End-to-end app testing pipeline for browser-based web apps on cloud browsers via Azure Playwright Workspaces: verify the live app, author tests for working flows, heal failing tests, then re-run with video and produce one consolidated report. Three phases (app verification, test authoring, test healing) plus a scoped final sanity run; each phase emits a sub-report. Use when asked to "verify my app", "make sure my app works and has good test coverage", "do a full QA pass", "add tests where I'm missing coverage", "fix failing tests and add new ones", "smoke test before deploy", "QA my deployment", or any combined verify-and-test ask. Requires Azure CLI (`az login`) and a Playwright Workspace resource ID — bootstraps configs on first invocation. Browser-based web apps with Playwright only — not for unit/API tests, native mobile/desktop, load/perf, or full accessibility audits.

      Also in 3 projects that use this

  • In this repository23 other files it gives its agents.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.