# Stay in Your Editor: The Hidden Efficiency of smooth AI Integration

> Discover how staying in your editor with AI agents eliminates context-switching, UI learning, and intent re-uploading for a smoother workflow.
> By Dave · 2026-07-16
> Source: https://otf-kit.dev/blog/never-leaving-your-editor

## The silent overhead of every sandbox hop

Every time you tab out to a sandbox, you pay three bills you don't see in the invoice. You re-derive context the model has to rebuild from a repo it didn't write. You re-learn a UI that has its own shortcuts, its own log pane, its own way of showing you a stack trace. And you re-upload intent — the thing in your head that knows why a `Card` sits where it sits, why the invite form mirrors the existing one, why the empty state matters more than the happy path. Sandbox tools are good at the first ten minutes of a project. They are expensive at minute one thousand.

The alternative is older than it sounds. Stay in your editor. Let the agent read the conventions you already wrote, the components you already shipped, the tests you already trust. Prompt, run, preview, commit, ship — five verbs, one window, no round trip.



![in-editor workflow (you stay in Cursor or Claude Code, the agent reads the kit's rules fro](https://cdn.otf-kit.dev/blog/never-leaving-your-editor/inline-1.png)



## What extending a kit actually looks like

Say you've installed the SaaS Dashboard kit. You own the code. The components ship with their own conventions written down. You want to add a `Team Invitations` page — a real feature, not a demo.

You open Cursor. You type:

> Add `/dashboard/team/invitations`. Owners can email invites; invites have a status (pending, accepted, expired) and can be revoked. Match the existing `Card`, `Table`, and `EmptyState` patterns. Wire a server action to the existing `workspace_memberships` table. Add a row to the sidebar nav.

Cursor reads `.cursorrules`. It knows the file structure. It reads `CLAUDE.md`. It knows which components exist and that it should not invent new ones. It greps `/dashboard/settings/members` because that page already does the closest thing. It drafts the route, the server action, the table columns, the empty state.

```ts
// app/dashboard/team/invitations/page.tsx
import { Card, Table, EmptyState, Badge, Button } from "@otfdashkit/ui"
import { sendInvite, revokeInvite } from "./actions"

export default async function InvitationsPage() {
  const invites = await db.invite.findMany({ where: { workspace_id } })

  return (
    <div className="space-y-6">
      <header className="flex items-center justify-between">
        <h1 className="text-2xl font-semibold">Invitations</h1>
        <Button onClick={sendInvite}>Send invite</Button>
      </header>

      {invites.length === 0 ? (
        <EmptyState
          title="No pending invites"
          body="Owners can email a teammate to join this workspace."
        />
      ) : (
        <Card>
          <Table
            columns={["Email", "Status", "Sent", ""]}
            rows={invites.map(i => [
              i.email,
              <Badge tone={statusTone(i.status)}>{i.status}</Badge>,
              i.created_at.toLocaleDateString(),
              <Button variant="ghost" onClick={() => revokeInvite(i.id)}>
                Revoke
              </Button>,
            ])}
          />
        </Card>
      )}
    </div>
  )
}
```

Notice what's missing: nothing. The agent didn't reach for a new icon set, didn't write a `<div className="card">` because it already saw the `Card` import everywhere else, didn't fabricate a column the table doesn't support. That's the kit doing the work, not the model being clever. The model is the verb. The kit is the noun.

## The two files that make the agent useful

`CLAUDE.md` and `.cursorrules` are the same idea in two homes. Both are short — 80 to 200 lines. Both are written for the agent, not the human. Both are tested: the kit ships with 20+ prompts in `ai/prompts/` that have been run against Cursor and Claude Code, and prompts that produce wrong output get fixed in the rules file, not the prompt library.

What goes in them:

- **The component inventory.** "Use `@otfdashkit/ui` for all primitives. Do not introduce new icon libraries. Do not create ad-hoc cards with raw divs."
- **The file layout.** "Routes live in `app/dashboard/<feature>/page.tsx`. Server actions in `app/dashboard/<feature>/actions.ts`. Reusable widgets in `components/widgets/`."
- **The naming conventions.** "Table columns are sentence case. Empty states lead with a verb, not a noun. Buttons in destructive flows are always `variant="danger"`."
- **The data shape.** "All timestamps are stored as UTC, rendered with `toLocaleDateString` at the edge of the component. Never store formatted strings."
- **The hard no's.** "Do not edit `tokens/`. Do not bypass the form primitive. Do not add a state library — server actions are enough."

A short slice of `CLAUDE.md`, for the curious:

```md
# Conventions
- Primitives: import from @otfdashkit/ui. Never from node_modules.
- Layout: every page has a <header> with a single h1 and one trailing action.
- Lists: always wrap in <Card>. Always render an <EmptyState> when the array is empty.
- Forms: use <Form> + a server action. Never raw <form>.
- Tokens: never hardcode color, spacing, radius, or font size.
- Destructive actions: <Button variant="danger"> + a confirmation step.
- Data: UTC in the DB, formatted at the render boundary.
```

That's the durable layer. The model changes every quarter. The conventions don't.

## The 24-item checklist that runs before you ship

Agents are confident. The fix isn't to argue with them — it's to grade them. Every kit ships with `scripts/preflight.ts`, a 24-item gate that runs against your diff:

1. No new direct imports from low-level framework packages.
2. All UI primitives come from `@otfdashkit/ui` or `@otfdashkit/ui-native`.
3. No hard-coded colors — every color reads from `tokens/`.
4. No hard-coded spacing — every spacing value is a token.
5. Server actions return a typed result, not a raw `Response`.
6. Every page exports a default async function with typed `params`.
7. No `useEffect` for data fetching — server components only.
8. Forms use the `Form` primitive, not raw `<form>`.
9. Destructive actions require a confirmation step.
10. Empty states are present on every list page.
11. Loading states use the `Skeleton` primitive, not custom spinners.
12. Errors are caught at the route boundary, not in the component.
13. Tables have a defined column order and width.
14. Buttons in list rows are `variant="ghost"`.
15. Modals are portaled and trap focus.
16. Every server action is auth-scoped to a workspace.
17. Every mutation is wrapped in a transaction.
18. Migrations have a down migration.
19. Tests cover the happy path and one error path per action.
20. No `TODO` comments left in shipped code.
21. No `console.log` left in shipped code.
22. `package.json` has no new top-level deps unless approved.
23. Bundle size delta is under 8kb.
24. Lighthouse score on the new route is above 90.

You don't read the list. You run:

```bash
pnpm preflight
# → 22/24 passed
# → ✗ [12] Errors must be caught at the route boundary (src/.../actions.ts:38)
# → ✗ [20] TODO comment in src/.../page.tsx:14
```

You paste the failure into the agent. The agent fixes it. You ship. The preflight is the spec the agent grades itself against — closer than a code review, faster than a style argument, and it never gets tired of your third re-prompt.

## Why the repo is the context

A sandbox tool's context is its own database of your project — a copy it keeps, a copy it renders, a copy you can't really own. Your editor's context is the repo. The repo has history. The repo has branches. The repo has tests that fail for real reasons. The repo has a CI that runs on your machine, in your CI, on your terms.

When the model gets the data wrong, you don't open a support ticket. You `git blame`. You read the failing test. You rerun the preflight. You commit the fix with a message that says what you actually changed. That's not a nostalgia argument — it's an auditability argument. Three months from now, when the invite rate-limit needs to change, you don't need to remember which cloud project you wrote it in. You need to remember a commit.

The deploy script closes the loop. One command, the same chain you already trust:

```bash
pnpm ship
# → builds web + mobile
# → runs preflight (24/24)
# → pushes to remote
# → wires custom domain + DNS + TLS
# → triggers iOS + Android build
# → done
```



![prompt to shipped — prompt, run, preview, commit, ship, all in one window, with the agent ](https://cdn.otf-kit.dev/blog/never-leaving-your-editor/inline-2.png)



## What this enables for a solo builder

The hidden gift of "never leave your editor" isn't speed. It's continuity. You can pick up a half-finished feature on a Tuesday at 11pm, prompt your way to a working branch, commit, and the next morning the only thing you need to remember is the prompt. The kit remembered the rest — the file layout, the component names, the token names, the table column widths, the empty state copy. You remembered the product decision. The kit remembered everything else.

It also means your tools compose. The editor has the terminal. The terminal has git. Git has your CI. CI has the deploy script. The deploy script has the custom domain, the DNS, the TLS, the mobile build. One chain, no glue. A sandbox tool breaks the chain in three places and gives you a pretty preview in return.

The model is going to change. Cursor is going to ship a new agent mode. Claude Code is going to get a new tool. Both are good. Use them today, swap them next quarter, the repo doesn't care which one wrote the diff. The kit is the part that doesn't change. The kit is the part that compounds.

## Closing

The point isn't that sandbox tools are bad. They're the fastest way to get a first draft, and a first draft is a real thing to want. The point is that a first draft is not a product, and the moment you need a real product — auth, billing, a real data model, a deploy, a real domain, a real mobile build — the second tool costs more than the first saved you.

Extend the kit. Stay in the editor. Ship from your own repo. The model is the verb. The kit is the noun. And the repo is the only context that survives the model change.