```yaml feature.yaml theme={null}
feature:
name: animated-terminal
product: docs
description: |
A mock terminal animation for our docs site.
It demonstrates how an AI agent uses the acai toolkit to work on a software project.
🥚 In the example, it is self-referentially building itself, from this very same spec.
components:
FRAME:
name: Terminal frame and container
description: UI container that looks like a terminal window on a Mac with a TUI instance running inside it
requirements:
1: Renders scrollable mock chat history
1-1: Does not auto-scroll unless user is already at the bottom of scroll container
2: Renders mock text input
2-1: Does not accept actual user inputs (no typing, no buttons)
STORY:
name: Rough storyboard for the animation
requirements:
1: Animation starts with user typing "I've made some changes to the spec @animated-terminal.feature.yaml - please run `acai skill` to learn spec-driven development."
2: Shows the agent run `acai skill`. Agent says "Got it. I will look to see what changed, then re-align the code to spec."
3: Concludes with user typing "Nice job. I'm looking at it right now. It's flawless. Go ahead and mark all requirements as accepted."
3-1: Agent runs `acai set-status` and marks all requirements as accepted.
4: The animation stops after the final step and does not loop.
constraints:
DEV:
requirements:
1: Must be a single, self-contained standalone react component (a single export, with no imports)
```
```tsx animated-terminal.jsx theme={null}
// animated-terminal.DEV.1 - No imports
export const AnimatedTerminal = () => {
const chatRef = useRef(null);
useEffect(() => {
// animated-terminal.FRAME.1-1 - autoscroll
const el = chatRef.current;
if (el) {
// Use a threshold to detect if the user is "near" the bottom
const isNearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 100;
if (isNearBottom) el.scrollTop = el.scrollHeight;
}
}, [messages]);
return (
{/* animated-terminal.FRAME.1 */}
{messages.map((msg, i) => renderMessage(msg, i))}
);
};
```
```ts animated-terminal.test.ts theme={null}
// When we tag tests with requirement IDs, the acai.sh dashboard automatically tracks coverage!
describe("Constraints", () => {
// animated-terminal.DEV.1 - Dev constraint
it("self-contained standalone component (no imports)", () => {});
});
describe("UI rendering", () => {
// animated-terminal.FRAME.1
it("renders scrollable mock chat history", () => {});
// animated-terminal.FRAME.1-1
it("auto-scrolls ONLY if user is at bottom threshold", () => {});
// animated-terminal.FRAME.2
it("renders mock text input", () => {});
// animated-terminal.FRAME.2-1
it("ignores user typing and button interactions", () => {});
});
```
As shown above, acai gives each requirement an ID that is unique, stable, and readable. These IDs should be referenced liberally (in tests, comments, and other specs), and are extracted from code with a single command.
The idea is when your spec changes, your code must change too.
## Why acai?