| name | uic |
| description | Use when automating browser interactions with a web app that has a manifest.json or data-agent-id attributes. Use when the agent needs to find, target, or interact with specific UI elements by name, label, or purpose. |
UI Contracts for Agent Automation
UI Contracts makes web app UIs machine-readable with stable hierarchical IDs, so agents can find, target, and interact with any interactive element by name instead of fragile selectors.
Quick Start
npx uicontract scan ./src -o manifest.json
npx uicontract name manifest.json -o manifest.json
npx uicontract find "login" --json
npx uicontract describe <agent-id> --json
npx uicontract list --type button --json
npx uicontract diff old.json new.json --json
Core Workflow
1. Discover
Check for an existing manifest.json in the project root. If none exists, generate one:
npx uicontract scan ./src -o manifest.json
npx uicontract name manifest.json -o manifest.json
2. Find
Search for elements by description. Fuzzy matching is enabled by default:
npx uicontract find "pause subscription" --json
npx uicontract find "pase subscribtion" --json
npx uicontract find "billing" --type button --json
3. Target
Use the agentId from the find result to target the element in the browser.
agent-browser:
agent-browser snapshot -s '[data-agent-id="settings.billing.pause-subscription.button"]'
agent-browser click @e1
CSS selector (any tool):
[data-agent-id="settings.billing.pause-subscription.button"]
Playwright MCP: Launch with --test-id-attribute=data-agent-id, then use ref values from the accessibility snapshot.
See references/browser-tool-bridge.md for all supported tools.
4. Verify
Compare the current manifest against a baseline to detect breaking changes:
npx uicontract diff baseline.json current.json --json
Exit code 1 means breaking changes were found.
Commands
Discovery
scan -- Discover interactive elements in source code.
npx uicontract scan <directory> -o manifest.json
| Flag | Description |
|---|
-o, --output <path> | Output file path (default: manifest.json) |
--framework <name> | Force a specific framework parser |
--json | Write raw JSON to stdout |
--verbose | Enable debug logging |
name -- Assign stable hierarchical IDs to discovered elements.
npx uicontract name manifest.json -o manifest.json
| Flag | Description |
|---|
-o, --output <path> | Output file path |
--ai | Use AI-assisted naming for ambiguous elements (experimental) |
--ai-provider <name> | AI provider: openai, anthropic, or google (auto-detected from env) |
--ai-model <model> | Override the default model for the AI provider |
--ai-timeout <ms> | Timeout for AI naming requests (default: 10000) |
annotate -- Insert data-agent-id attributes into source files.
npx uicontract annotate manifest.json --dry-run
npx uicontract annotate manifest.json --write
| Flag | Description |
|---|
--dry-run | Preview patches without modifying files |
--write | Apply patches to source files |
--backup-dir <path> | Directory for pre-annotation backups (default: .uic-backup/) |
Query
find -- Search for elements by description.
npx uicontract find <query> --json
| Flag | Description |
|---|
--manifest <path> | Path to manifest file (default: manifest.json) |
--type <type> | Filter by element type (button, input, a, etc.) |
--exact | Disable fuzzy matching, require exact substring |
--json | Output as JSON array |
describe -- Show detailed info for one element.
npx uicontract describe <agent-id> --json
| Flag | Description |
|---|
--manifest <path> | Path to manifest file (default: manifest.json) |
--json | Output as JSON object |
list -- List elements with optional filters.
npx uicontract list --json
| Flag | Description |
|---|
--manifest <path> | Path to manifest file (default: manifest.json) |
--type <type> | Filter by element type |
--route <route> | Filter by route prefix |
--component <name> | Filter by component name |
--routes | List all unique routes |
--components | List all unique component names |
--json | Output as JSON array |
Governance
diff -- Compare two manifests for breaking changes.
npx uicontract diff <old-manifest> <new-manifest> --json
| Flag | Description |
|---|
--allow-breaking | Exit 0 even when breaking changes are found |
--json | Output diff as JSON object |
Change categories:
- Breaking: removed elements, renamed agent IDs, changed element types.
- Informational: added elements, changed labels, moved source locations.
Selector Patterns
Use these CSS attribute selectors to target data-agent-id values:
| Pattern | Syntax | Use Case |
|---|
| Exact | [data-agent-id="id"] | Target one specific element |
| Prefix | [data-agent-id^="settings.billing."] | All elements in a section |
| Substring | [data-agent-id*="billing"] | Any element mentioning "billing" |
| Suffix | [data-agent-id$=".button"] | All buttons |
| Presence | [data-agent-id] | Any UI Contracts-annotated element |
Integration Example
UI Contracts + agent-browser, three steps:
Step 1 -- Find the element:
npx uicontract find "pause subscription" --json
Step 2 -- Navigate to the page:
agent-browser open http://localhost:3000/settings/billing
Step 3 -- Target and interact:
agent-browser snapshot -s '[data-agent-id="settings.billing.pause-subscription.button"]'
agent-browser click @e1
Key Rules
- Always use
--json for machine parsing. The JSON format is stable across versions.
- Never hardcode CSS selectors when an agent ID is available.
- Check
conditional: true elements -- they may not be in the DOM without the right app state.
- Check
dynamic: true elements -- their count depends on runtime data.
- Run
npx uicontract diff before and after changes to catch regressions.
- Run
npx uicontract scan after UI changes to keep the manifest current.
- Commit the baseline manifest to version control for CI diffing.
References