Give your agent a typed skill.

A skill is a list of instructions. An anchor is a class: the properties and behaviors of a feature, typed and hosted for your agents.

Skill

A markdown file on your PC

SKILL.md ~/game/.claude/skills/platformer

2D platformer: Celeste-grade movement

Use this when building any 2D side-view platformer. A plain build almost always works but feels stiff or floaty.

Constants

Gravity 900, MaxFall 160, JumpSpeed −105, VarJumpTime 0.2, JumpGraceTime 0.1, JumpBufferTime 0.08, HalfGravThreshold 40, …

Jump

if (onGround) p.jumpGrace = C.JumpGraceTime;
else if (p.jumpGrace > 0) p.jumpGrace -= dt;
if (p.varJumpTimer > 0) p.varJumpTimer -= dt;

Pitfalls

  • grounded = vel.y === 0 is true at the apex of every jump.
  • Variable dt physics changes the jump height with the frame rate.
  • A camera locked to the player is nauseating on every jump.

Camera

Celeste’s camera eases toward its target with a framerate-independent lerp, plus a forward focus of about 24px in the facing direction.

Wall jump

Allowed when a solid is within 3px to that side, not only when touching. Holding into the wall can’t cancel the kick for 0.16s.

Tests to write

  • approach() never overshoots, in both directions.
  • A held jump rises higher than a tapped jump.
  • Pressing jump up to 0.1s after walking off a ledge still jumps.
Anchor

A typed skill, hosted

anchor.et/anchors/5fbf51e5-82e6-4a1e-9636-d0e791527b2c
class 2DPlatformerAnchor {
overview: Markdown
# 2D platformer: Celeste-grade movement and game feel
Use this anchor when building any 2D side-view platformer. It exists because a plain build almost always *works* but feels stiff or floaty …
principles: Markdown
## Principles
1. **The player is always right.** Every rule here exists to do what the player *meant* …
2. **Fixed timestep, pixel units.** Simulate at exactly 60 steps/s with dt = 1/60 …
constants: Json
{ "Gravity": 900, "MaxFall": 160, "JumpSpeed": -105,
"VarJumpTime": 0.2, "JumpGraceTime": 0.1, "JumpBufferTime": 0.08,
"HalfGravThreshold": 40, "UpwardCornerCorrection": 4, … }
tech: {… }
loop: Markdown
## Game loop (Fiedler, *Fix Your Timestep!*)
const STEP = 1 / 60;
let acc = 0, last = performance.now(); …
physics: Markdown
## Physics: Actors and Solids (Thorson, *Celeste and TowerFall physics*)
There is no physics engine and no general collision resolution …
run: Code
const mult = onGround ? 1 : C.AirMult; // 0.65: turning in the air is slower
p.speed.x = approach(p.speed.x, C.MaxRun * moveX, C.RunAccel * mult * dt); …
gravity: Code
const mult = Math.abs(p.speed.y) < C.HalfGravThreshold && input.jumpHeld ? 0.5 : 1;
p.speed.y = approach(p.speed.y, max, C.Gravity * mult * dt); …
jump: Code
if (onGround) p.jumpGrace = C.JumpGraceTime; // coyote time
else if (p.jumpGrace > 0) p.jumpGrace -= dt;
if (p.varJumpTimer > 0) p.varJumpTimer -= dt; …
corner_correction: Code
function onCollideV() {
if (p.speed.y < 0) {
if (p.speed.x <= 0) for (let i = 1; i <= C.UpwardCornerCorrection; i++) …
wall: Code
// Wall jump is allowed when a solid is within 3px to that side (not only when touching)
const wallJumpCheck = (dir: 1 | -1) => collidesAt(p.x + dir * C.WallJumpCheckDist, p.y); …
input: Markdown
## Input
- Map keys by `KeyboardEvent.code`: arrows and WASD to move, **Space, C, Z, K or Up** to jump …
camera: Markdown
## Camera (Celeste and Keren, *Scroll Back*)
cam.x += (target.x - cam.x) * (1 - Math.pow(0.01, dt)); …
}
feel: {… }
squash: Markdown
## Squash, stretch and dust (Celeste values)
| Jump and wall jump | (0.6, 1.4) | 4 dust puffs from the feet … |
juice: Markdown
## Juice (Jonasson and Purho, *Juice it or lose it*; Vlambeer)
- **Death**: freeze the simulation for about 0.1s (hitstop) …
}
level: Markdown
## Level design and data
- Store levels as arrays of strings with one char per 8px tile …
art: Markdown
## Art without assets
- Use a fixed small palette, for example PICO-8's 16 colours …
svelte: Markdown
## Embedding as a Svelte 5 component
- `Game.svelte` fills its parent (`width: 100%; height: 100%`) …
build_order: string[]
"constants.ts with the values above; approach() and lerp() helpers",
"Fixed-step loop, 320x180 buffer, integer-scaled canvas that fills the parent",
… 10 more
tests_to_write: string[]
"approach() never overshoots, in both directions",
"A held jump rises higher than a tapped jump (variable jump height)",
… 9 more
pitfalls: Markdown
## Pitfalls plain builds hit
- **Variable dt physics** (`pos += vel * frameDt`): the jump height changes with the frame rate …
adapt: Markdown
## Adapting
- **Different resolution**: scale every constant by the ratio of your tile size to 8 …
}

Anchors and skills

A skill, typed and hosted.

If you already write skills, nothing changes about what goes in. What changes is the shape it takes and where it lives.

Same as a skillSKILL.md

  • Instructions, written once. Pitfalls, examples, and the order to build in.
  • Any harness. Claude Code, Codex, Cursor, and any MCP client read it.
  • Agents write them. Point one at a codebase and it does the work.
  • Plain text. Nothing you can’t read in full whenever you like.

Differentanchor

  • Typed blocks, not one file. Constants are JSON, code is code, tests are a list. Your agent sees every path first, then reads the blocks it needs in one call.
  • One URL, not a copy per repo. Nothing to paste into checkouts or keep in sync. Cloud and CI agents read it too.
  • One source, versioned. Edit once and every agent reads the fix on its next call. Past revisions stay readable.
  • Readable by people. Blocks read like a spec sheet, so you spot the stale constant or the thin tests and fix just that.
  • One command. Add the server once. Every anchor in the workspace is there from then on.

For teams

Share anchors across your team.

Every anchor lives in your organization’s workspace, hosted, so nobody manages files. Everyone’s agents build from the same anchors, and one fix reaches every build.

  • One anchor, every teammate

    Anchor a feature once and every agent on your team can build from it.

  • Fix one block

    A teammate corrects one block, in the web app or through any agent. Every agent gets it on the next call.

  • Full history

    Every edit is a new revision you can read back. Edits from people and agents never silently overwrite each other.

  • Private by default

    Only your organization can read your anchors. Roles, SSO, and directory sync included.

FAQ

Questions, answered.

How anchors relate to skills, where they come from, and who can see them.

What is an anchor?

A typed skill, hosted for your agents. It holds everything an agent needs to build one feature well: the code that matters, the exact values, the reasons behind them, the pitfalls, tests to write, and links to the sources, each as its own block. Agents read just the blocks they need, and every edit is a new revision.

I already write skills. What changes?

What goes in stays the same. The shape changes: one file becomes typed blocks your agent reads by path. The place changes: one hosted URL instead of a copy in every repo. To bring a skill over, point your agent at the SKILL.md and ask it to anchor it, then tidy the blocks in the web app.

How do I make one?

Ask your agent. Point it at a feature in an open source project or your own repo, for example “Study the chat composer in github.com/pingdotgg/t3code and anchor it.” It reads the code and writes the anchor to your workspace. You can read and correct it in the web app whenever you like.

Is this copying other people’s code?

An anchor captures how a feature works so your agent can build its own version, the way you would study a codebase before writing yours. Where an anchor quotes code, that code’s license still applies, so anchor projects whose licenses fit how you will use them. Every anchor links to its sources. The platformer anchor draws on Celeste’s player code, which its developers published under the MIT license.

How does my agent find the right anchor?

Your agent searches your workspace with Anchor’s tools when a task calls for it, then reads the anchor it needs. You can also point it at one by name, like “use the 2D platformer anchor”.

Who can see my anchors?

Only members of your organization. Access is checked on every request, for people and agents alike, and is revoked as soon as someone leaves.

Which agents work with Anchor?

Any client that supports remote MCP servers with sign-in, including Claude Code, Codex, and Cursor.

Write your first typed skill.

Add Anchor to your agent with one command, then sign in in the browser that opens. New here? That creates your account.

claude mcp add --transport http --scope user anchor https://anchor.et/mcp

Then type /mcp in Claude Code and sign in. After that, ask it: Study the chat composer in github.com/pingdotgg/t3code and anchor it.