---
title: "Try a policy in the playground"
description: "Run a Cedar or Rego policy on a request in the browser or the terminal, see the line that decided, run its tests, replay recorded decisions and share the state as a link."
section: "guides"
status: "Planned for 0.7"
spec: "policy-playground"
canonical: "https://mainsdk.dev/docs/guides/try-a-policy-in-the-playground"
updated: "2026-10-28"
---

# Try a policy in the playground

> Run a Cedar or Rego policy on a request in the browser or the terminal, see the line that decided, run its tests, replay recorded decisions and share the state as a link.

Status: Planned for 0.7 · Canonical: https://mainsdk.dev/docs/guides/try-a-policy-in-the-playground · Updated: 2026-10-28

Before a policy change reaches your app, try it on a request. The playground shows the decision, the line that decided it, which tests pass, and which recorded decisions the change would flip. It takes about 10 minutes. The browser and the terminal use the same engine, so they print the same result.

## You need

- A policy in `policies/` (see [Keep policies in git](https://mainsdk.dev/docs/guides/keep-policies-in-git)).
- A request as JSON, for example `request.json`.

```json title="request.json"
{
  "subject": { "type": "User", "id": "u_ana", "role": "editor" },
  "action": { "name": "orders.update" },
  "resource": { "type": "Order", "id": "o_1" },
  "context": { "amount": 12000 }
}
```

## 1. Decide in the terminal

```bash
npx mainsdk policy play policies --request request.json
```

You should see `decision: deny` and `decided by: … at policy.cedar:7`, the line of the rule that decided.

## 2. Run the tests

Put cases in `policies/orders.test.json` as `{ "tests": [{ "name": "…", "input": { … }, "expect": "allow" }] }`. The command prints each failing test and exits 1 when one fails.

## 3. See what a change would flip

```bash
npx mainsdk policy play policies --request request.json --replay .mainsdk/decisions.jsonl
```

Each line starting `FLIP allow -> deny` is a recorded decision the new policy would answer differently. A replay can hold up to 100,000 decisions.

## 4. Use the browser page

Open the playground in the docs. Paste the policy and request, press Run, and read the same result. The page runs entirely in your browser; nothing is sent until you press Share.

## 5. Share a state

Share makes a short getqr.id link that opens your policy, request and tests read-only. The state travels in the link itself. Open it and press Fork to get an editable copy; the original link never changes.

## Check it worked

The JSON from `mainsdk policy play --json` and the browser's result for the same input are identical. A tampered or unreadable link shows `MAIN-PLAY-0003` and leaves the page empty.
