From 72c9b13289b27337bd65371b2be9fdf8a810f66d Mon Sep 17 00:00:00 2001 From: ZILECAO Date: Wed, 26 Aug 2026 15:28:30 -0400 Subject: [PATCH] Polish the AgentFormation README and animated demo --- README.md | 33 ++- assets/agentformation-demo.svg | 356 +++++++++++++++++++++++++-------- 2 files changed, 307 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index a0d5a5b..e9b618b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,20 @@ +
+ # AgentFormation -An AWS-native template for private, persistent remote coding environments. +**Private, persistent coding-agent workspaces in your AWS account.** + +

+ Checks + License: BSD 2-Clause + Security policy +

+ +

Each approved employee gets one private EC2 runtime and a persistent /workspace—with company SSO and no inbound SSH.

+ +

Quick start · Architecture · Documentation · Security · Contributing

+ +

Animated AgentFormation browser terminal showing Codex editing a project and running its checks @@ -18,12 +32,16 @@ password, or authenticator-app setting. An administrator normally assigns a dedicated AgentFormation access group to the app, and each assigned employee can create exactly one reviewed coding environment for themself. +| Company sign-in | Private by default | Persistent by design | +| --- | --- | --- | +| IAM Identity Center; no second app password | Private subnet, encrypted EBS, no public IP, and no inbound SSH | `/workspace` and `tmux` keep running after the browser disconnects | + > [!IMPORTANT] > The first complete deployment builds a runtime image and an App Runner service. > It commonly takes more than 30 minutes. This is normal for the AWS services used > by the template, not a frozen terminal. -## What it creates +## Architecture ```text assigned employee group @@ -169,6 +187,17 @@ upload restrictions, and status output. Do not commit a company hostname to the public repository. Leave `publicUrl` empty to keep using the generated App Runner address. +## Documentation + +| Guide | Use it for | +| --- | --- | +| [Workstation setup](docs/workstation-setup.md) | Installing the AWS CLI and Docker on macOS or Linux, including `amd64` and `arm64` differences | +| [IAM Identity Center setup](docs/identity-center-setup.md) | Creating the SAML application, attribute mappings, and assigned access group | +| [Configuration and upgrades](docs/configuration.md) | Choosing settings, moving a deployment, rebuilding images, and applying updates | +| [Remote CLI sign-in](docs/remote-cli-login.md) | Finishing `localhost` or `127.0.0.1` OAuth callbacks from a browser terminal | +| [Agent config migration](docs/migrating-local-agent-configs.md) | Moving approved Codex or Claude Code preferences and history into a runtime | +| [Security model](docs/security-model.md) and [privacy notes](docs/privacy.md) | Understanding trust boundaries, access, stored data, and operational responsibilities | + ## Daily administration ```bash diff --git a/assets/agentformation-demo.svg b/assets/agentformation-demo.svg index 9f3d110..3960d18 100644 --- a/assets/agentformation-demo.svg +++ b/assets/agentformation-demo.svg @@ -6,42 +6,31 @@ role="img" aria-labelledby="title description" > - AgentFormation browser terminal running Codex + A laptop using Codex in a remote AgentFormation workspace on AWS - An animated AgentFormation terminal where a developer asks Codex to add a - health check, Codex reads and edits files, runs tests, and reports success. + An animation showing a laptop opening an encrypted browser session to a + private, persistent EC2 workspace in the user's AWS account. The App Runner + web app starts an AWS Systems Manager Session Manager stream to a tmux + session on private EC2. The laptop and cloud show that same synchronized + AgentFormation session while Codex edits a project. The laptop then closes + while EC2, encrypted EBS, tmux, and Codex keep running. - - - - - - - - - - - - - - - - + @@ -51,36 +40,60 @@ "Liberation Mono", "Courier New", monospace; } + .laptop-lid { + animation: laptop-cycle 24s cubic-bezier(0.65, 0, 0.35, 1) infinite; + transform-box: view-box; + transform-origin: 290px 462px; + } + + .browser-connection { + animation: browser-connection-cycle 24s ease-in-out infinite; + } + + .closed-note, + .cloud-continues { + animation: show-closed-state 24s ease-in-out infinite; + opacity: 0; + } + + .connection-line { + animation: connection-dashes 1.8s linear infinite; + } + + .transfer-dot { + animation: transfer 2.4s ease-in-out infinite; + } + .conversation { - animation: conversation-cycle 18s ease-in-out -1.5s infinite; + animation: conversation-cycle 24s ease-in-out infinite; } .prompt-reveal { - animation: type-prompt 18s steps(32, end) -1.5s infinite; + animation: type-prompt 24s steps(32, end) infinite; } .thinking { - animation: show-thinking 18s ease -1.5s infinite; + animation: show-thinking 24s ease infinite; } .read-step { - animation: show-read 18s ease -1.5s infinite; + animation: show-read 24s ease infinite; } .edit-step { - animation: show-edit 18s ease -1.5s infinite; + animation: show-edit 24s ease infinite; } .test-step { - animation: show-test 18s ease -1.5s infinite; + animation: show-test 24s ease infinite; } .answer { - animation: show-answer 18s ease -1.5s infinite; + animation: show-answer 24s ease infinite; } .progress-bar { - animation: progress-width 18s cubic-bezier(0.2, 0.8, 0.2, 1) -1.5s infinite; + animation: progress-width 24s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; } .activity-dot { @@ -103,17 +116,80 @@ animation: blink 1s steps(1, end) infinite; } - .enter-glow { - animation: enter-glow 3s ease-in-out infinite; + @keyframes laptop-cycle { + 0%, + 50% { + transform: scaleY(1); + } + 59%, + 90% { + transform: scaleY(0.035); + } + 98%, + 100% { + transform: scaleY(1); + } } - @keyframes conversation-cycle { + @keyframes browser-connection-cycle { + 0%, + 50% { + opacity: 1; + } + 57%, + 92% { + opacity: 0; + } + 98%, + 100% { + opacity: 1; + } + } + + @keyframes show-closed-state { 0%, - 5% { + 55% { + opacity: 0; + transform: translateY(5px); + } + 61%, + 90% { + opacity: 1; + transform: translateY(0); + } + 96%, + 100% { + opacity: 0; + } + } + + @keyframes connection-dashes { + to { + stroke-dashoffset: -28; + } + } + + @keyframes transfer { + 0%, + 100% { + opacity: 0; + transform: translateX(0); + } + 15% { + opacity: 1; + } + 75% { + opacity: 1; + } + 90% { opacity: 0; + transform: translateX(120px); } - 9%, - 91% { + } + + @keyframes conversation-cycle { + 0%, + 94% { opacity: 1; } 100% { @@ -123,11 +199,11 @@ @keyframes type-prompt { 0%, - 5% { + 3% { width: 0; } - 18%, - 91% { + 16%, + 94% { width: 520px; } 100% { @@ -137,16 +213,16 @@ @keyframes show-thinking { 0%, - 19% { + 15% { opacity: 0; transform: translateY(6px); } - 23%, - 38% { + 19%, + 29% { opacity: 1; transform: translateY(0); } - 43%, + 33%, 100% { opacity: 0; transform: translateY(-4px); @@ -155,12 +231,12 @@ @keyframes show-read { 0%, - 30% { + 24% { opacity: 0; transform: translateY(7px); } - 34%, - 91% { + 29%, + 94% { opacity: 1; transform: translateY(0); } @@ -171,12 +247,12 @@ @keyframes show-edit { 0%, - 41% { + 38% { opacity: 0; transform: translateY(7px); } - 45%, - 91% { + 43%, + 94% { opacity: 1; transform: translateY(0); } @@ -187,12 +263,12 @@ @keyframes show-test { 0%, - 52% { + 59% { opacity: 0; transform: translateY(7px); } - 56%, - 91% { + 64%, + 94% { opacity: 1; transform: translateY(0); } @@ -203,12 +279,12 @@ @keyframes show-answer { 0%, - 63% { + 74% { opacity: 0; transform: translateY(8px); } - 68%, - 91% { + 79%, + 94% { opacity: 1; transform: translateY(0); } @@ -219,18 +295,18 @@ @keyframes progress-width { 0%, - 20% { + 16% { width: 0; opacity: 0; } - 24% { + 20% { opacity: 1; } - 57% { + 65% { width: 650px; opacity: 1; } - 62%, + 70%, 100% { width: 650px; opacity: 0; @@ -270,17 +346,20 @@ } } - @keyframes enter-glow { - 0%, - 100% { - opacity: 0.12; + @media (prefers-reduced-motion: reduce) { + .laptop-lid, + .browser-connection, + .closed-note, + .cloud-continues { + animation: none; + transform: none; } - 50% { - opacity: 0.28; + + .closed-note, + .cloud-continues { + display: none; } - } - @media (prefers-reduced-motion: reduce) { .conversation, .prompt-reveal, .read-step, @@ -288,8 +367,7 @@ .test-step, .answer, .activity-dot, - .cursor, - .enter-glow { + .cursor { animation: none; opacity: 1; transform: none; @@ -303,14 +381,98 @@ .progress-bar { display: none; } + + .connection-line, + .transfer-dot { + animation: none; + } } - - - + + + + + Your browser attaches to a persistent EC2 workspace + + + Session Manager reconnects to the same private tmux session. + + + + YOUR LAPTOP · BROWSER + + + + + + + + + + + + Laptop closed + + + + + PRIVATE + AWS + EC2 RUNTIME + + VPC · PRIVATE SUBNET + + + + + + tmux + Codex + /workspace + + + Encrypted EBS · no public IP · no inbound rules + + - + + + + + + + + + App Runner web app + + SSM Session Manager + + + + + The browser renders the App Runner web app; Systems Manager attaches it to tmux on private EC2. + + + Laptop closed. EC2, encrypted EBS, tmux, and Codex keep running. + + + + + @@ -413,7 +575,22 @@ - + + + + + + + + + + Tab @@ -421,22 +598,41 @@ Ctrl+C Ctrl+O Clear - New line - Select text - Copy + New Line + Select text + Copy - + + + - + Paste or type here — keystrokes go live… - - - Enter - + + + + + Enter + +