+ {Array.from({ length: DOT_COUNT }).map((_, dotIndex) => {
+ const col = dotIndex % 2;
+ const row = Math.floor(dotIndex / 2);
+ // The snake sequence index for this dot: when is it the "head"?
+ const sequenceIndex = DOT_SEQUENCE.indexOf(dotIndex as (typeof DOT_SEQUENCE)[number]);
+ // Negative delay syncs the animation so this dot is the head at t=0 when sequenceIndex=0.
+ // At t=0, headIndex should be 0, meaning sequenceIndex=0 dot is the head.
+ // Each dot is shifted by sequenceIndex steps back in time.
+ const delayMs = -(sequenceIndex * STEP_MS);
+ return (
+
+ );
+ })}
+
- {[
- {
- title: "Self-hosted",
- description:
- "Agents run on your machine with your full dev environment. Use your tools, your configs and your skills.",
- icon: (
-
- ),
- },
- {
- title: "Multi-provider",
- description:
- "Claude Code, Codex, and OpenCode through the same interface. Pick the right model for each job.",
- icon: (
-
- ),
- },
- {
- title: "Voice control",
- description:
- "Dictate tasks or talk through problems in voice mode. Hands-free when you need it.",
- icon: (
-
- ),
- },
- {
- title: "Cross-device",
- description:
- "iOS, Android, desktop, web, and CLI. Start work at your desk, check in from your phone, script it from the terminal.",
- icon: (
-
- ),
- },
- ].map((feature, i) => (
-
+
+
+ {/* Agent response — always rendered to reserve space */}
+
+
+
+
+
+
+
+
+
+
+
);
}
@@ -849,94 +1184,131 @@ interface CLIExample {
const cliExamples: CLIExample[] = [
{
- title: "Launch and monitor",
+ title: "Run agents",
description:
- "Give an agent a task and watch it work. The --worktree flag spins up an isolated git branch so you can run multiple agents on the same repo without conflicts.",
- code: `paseo run --provider claude/opus-4.6 "implement user authentication"
-paseo run --provider codex/gpt-5.4 --worktree feature-x "implement feature X"
+ "Launch agents locally or on any remote host. The --worktree flag spins up an isolated git branch so you can run multiple agents on the same repo without conflicts.",
+ code: `paseo run "implement user authentication"
+paseo run --provider codex --worktree feature-x "implement feature X"
+paseo run --host devbox:6767 "run the full test suite"
paseo ls # list running agents
paseo attach abc123 # stream live output
paseo send abc123 "also add tests" # follow-up task`,
},
{
- title: "Orchestration",
+ title: "Loops",
description:
- "Agents can use the CLI too. Tell one agent to spawn others, split up the work, and pull everything together when they're done.",
- code: `# Spawn two agents in parallel, wait, then synthesize
-paseo run --detach "implement the frontend" --name frontend
-paseo run --detach "implement the API layer" --name api
+ "Have one agent do the work, another verify the result, and loop until it passes. Built-in, no shell scripting needed.",
+ code: `# Worker-verifier loop: fix tests until they pass
+paseo loop run "make all tests pass" \\
+ --verify "verify tests pass and the code is production-ready" \\
+ --verify-check "npm test" \\
+ --max-iterations 5
-paseo wait frontend api
-
-paseo run "review both branches and write an integration plan"`,
+paseo loop ls # list running loops
+paseo loop logs abc123 # stream loop output`,
},
{
- title: "Structured output",
+ title: "Schedules",
description:
- "Pass a JSON schema and get typed data back from any agent run. No output parsing, just the structured result you asked for.",
- code: `result=$(paseo run \\
- --output-schema '{
- "type": "object",
- "properties": {
- "severity": { "type": "string", "enum": ["low", "medium", "high"] },
- "issues": { "type": "array", "items": { "type": "string" } }
- },
- "required": ["severity", "issues"]
- }' \\
- "audit this codebase for security issues")
+ "Run agents on a cron schedule. Automate recurring tasks like dependency updates, security audits, or report generation.",
+ code: `# Run a security audit every Monday at 9am
+paseo schedule create --cron "0 9 * * 1" \\
+ "audit the codebase for security issues and open PRs for fixes"
-echo $result | jq '.severity' # "high"
-echo $result | jq '.issues[0]' # "SQL injection on line 42"`,
- },
- {
- title: "Remote",
- description:
- "Point at any daemon on your network or over the internet. Run agents on a beefy server from your laptop.",
- code: `# Set once for the session
-export PASEO_HOST=workstation.local:6767
-paseo run "run the full test suite"
-paseo ls
-
-# Or per-command
-paseo --host gpu-server:6767 run "train the model"
-paseo --host gpu-server:6767 attach abc123`,
- },
- {
- title: "Worker-judge loops",
- description:
- "Have one agent do the work and another judge the result. Loop until it passes. Good for test fixes, code review, or any task with clear acceptance criteria.",
- code: `while true; do
- paseo run "make all tests pass"
-
- verdict=$(paseo run \\
- --output-schema '{"type":"object","properties":{"passed":{"type":"boolean"}},"required":["passed"]}' \\
- "verify tests pass and the code is production-ready")
-
- echo "$verdict" | jq -e '.passed' && break
-done`,
+paseo schedule ls # list all schedules
+paseo schedule pause abc123 # pause a schedule
+paseo schedule delete abc123 # remove a schedule`,
},
];
-function MobileSection() {
+function PhoneShowcase() {
+ const containerRef = React.useRef(null);
+ const textInView = useInView(containerRef, { once: true, margin: "-80px" });
+
+ // Scroll-linked animation: track how far through the container the user has scrolled
+ const { scrollYProgress } = useScroll({
+ target: containerRef,
+ offset: ["start end", "center center"],
+ });
+
+ // Responsive slide distance
+ const [slideDistance, setSlideDistance] = React.useState(260);
+ React.useEffect(() => {
+ function update() {
+ setSlideDistance(window.innerWidth < 768 ? 140 : 260);
+ }
+ update();
+ window.addEventListener("resize", update);
+ return () => window.removeEventListener("resize", update);
+ }, []);
+
+ // Side phones start at x=0 (behind center) and slide out to final position
+ const sideOpacity = useTransform(scrollYProgress, [0.2, 0.6], [0, 1]);
+ const leftX = useTransform(scrollYProgress, [0.2, 0.6], [0, -slideDistance]);
+ const rightX = useTransform(scrollYProgress, [0.2, 0.6], [0, slideDistance]);
+
return (
-
-
-
Mobile-first
-
- The mobile app has full feature parity with desktop. Launch agents, review diffs, talk through problems with voice, all from your phone.
+
+ {/* Arrow + text */}
+
+
+
+ When you want to step away from your desk, you can.
-
-
-
+
+ The native mobile app has full feature parity with desktop.
+
+
+
+ {/* Phone trio — side phones are absolute, start behind center, slide outward with perspective rotation */}
+
+ {/* Left phone — rotated to face inward */}
+
-
+
+
+ {/* Center phone */}
+
+
+
+
+ {/* Right phone — rotated to face inward */}
+
+
+
-
+
);
}
@@ -945,20 +1317,10 @@ function CLISection() {
const active = cliExamples[activeIndex];
return (
-
-
-
CLI
-
- Everything you can do in the app, you can do from the terminal.
-