# Teampact > Teampact is a sprint planner that runs in the browser with no backend. It distributes story effort across team members by capacity. People and AI agents use it side by side: agents call the same plan operations as the UI, and every agent change shows in the app with an Undo. The plan is one JSON object: teams (effort categories such as Design and Development), allocation types (kinds of work), a sprint length, team members with available hours per sprint, sprints with user stories, per-team effort estimates on each story, allocations that assign story hours to a member, projects with hour budgets, and a timeline schedule of hours per day. The app keeps the plan in memory, backs it up in the browser, and saves it as a .json file. ## Use the open app Every page of the app exposes `window.teampact`. Run JavaScript in the page: - `teampact.help()`: operations, arguments and error codes. `teampact.help("add_story")`: one input schema. - `teampact.call(name, args)` or `teampact.(args)`: run one operation. Returns `{ ok: true, result, message }` or `{ ok: false, error: { code, message } }`. - `teampact.batch([{ op, args }, ...])`: run plan operations as one change and one undo step; all apply or none. `"$0.storyId"` in args is the storyId result of step 0. Where the browser supports WebMCP (`navigator.modelContext`), the same operations are registered as tools. Typical session: 1. `teampact.get_app_state()`: plan name, unsaved changes, open sprint, and whether a prompt waits for the person. 2. `teampact.describe_plan()`: teams, members, sprints and projects with their ids. 3. `teampact.describe_sprint({ sprintId })`: capacity per member, status per story, and `issues` to fix. 4. Change the plan with plan operations, then `teampact.describe_sprint()` again to check. 5. `teampact.save_plan()` downloads the plan file when the person wants it saved. Plan operations: describe_plan, describe_sprint, get_plan, validate_plan, add_member, rename_member, set_available_hours, remove_member, add_sprint, rename_sprint, remove_sprint, add_story, update_story, remove_story, move_story_to_next_sprint, create_next_step, add_allocation, update_allocation, remove_allocation, move_allocation_to_next_step, distribute_evenly, add_team, rename_team, remove_team, add_allocation_type, rename_allocation_type, remove_allocation_type, set_sprint_duration, add_project, update_project, remove_project, set_story_project, set_schedule_day, set_schedule_week. App actions: get_app_state, select_sprint, open_story, set_view, filter_by_members, undo, redo, open_plan, save_plan, resolve_backup_prompt. Rules: - Address everything by id. Get ids from describe_plan and describe_sprint; never guess them. - Team and allocation type names match without regard to case. Both lists are configurable; describe_plan shows them. - Each agent change is its own undo step, even when several calls run in one script. - Removals apply at once and also remove dependent data (a member's allocations, a story's timeline entries). The person can undo them; still confirm large removals with them first. - `open_plan` refuses to replace unsaved work unless `discardUnsavedChanges` is true. Ask the person first. - While the startup backup prompt is open, changes wait (`backup_prompt_open`). Ask the person, then call `resolve_backup_prompt`. Right after the page loads, changes may also wait (`starting`) for a moment. - `open_plan` refuses plans that fail validation, and names the first problem. ## Plan files - [Plan file JSON Schema](/plan.schema.json): the format of a saved plan. - Command line, from the repository: `node scripts/teampact.mjs ops | describe | validate | run '' | batch `. It runs the same operations and prints JSON. The app does not watch files: open the plan again after a change.