{"fileResults":[{"id":"a367f74a-1a73-11f1-91bf-42dde27851f2","url":"https://www.val.town/x/zyloxtube/untitled-619/code/main.ts","project_id":"a362ddaa-1a73-11f1-91bf-42dde27851f2","name":"main.ts","content":"import { Hono } from \"npm:hono@3.11.7\";\nimport { streamSSE } from \"npm:hono@3.11.7/streaming\";\nimport pngjs from \"npm:pngjs@7.0.0\";\nimport fetch from \"node-fetch\";\n\nconst { PNG } = pngjs;\n\n// ==================== دوال التشفير (بدون تغيير) ====================\nasync function loadForge() {\n  const forge = await import(\"npm:node-forge@1.3.1\");\n  return forge.default || forge;\n}\n\nfunction encryptPassword(\n  plainText: string,\n  publicKeyPem: string,\n  forge: any,\n): string {\n  console.log(\"   🔐 تشفير كلمة المرور...\");\n\n  const cleanPem = publicKeyPem.trim();\n\n  if (cleanPem.includes(\"BEGIN RSA PUBLIC KEY\")) {\n    const base64Content = cleanPem\n      .replace(\"-----BEGIN RSA PUBLIC KEY-----\", \"\")\n      .replace(\"-----END RSA PUBLIC KEY-----\", \"\")\n      .replace(/\\s/g, \"\");\n\n    const derBytes = forge.util.decode64(base64Content);\n    const asn1 = forge.asn1.fromDer(derBytes);\n    const publicKey = forge.pki.publicKeyFromAsn1(asn1);\n    const encrypted = publicKey.encrypt(plainText, \"RSAES-PKCS1-V1_5\");\n    return forge.util.encode64(encrypted);\n  } else {\n    const publicKey = forge.pki.publicKeyFromPem(cleanPem);\n    const encrypted = publicKey.encrypt(plainText, \"RSAES-PKCS1-V1_5\");\n    return forge.util.encode64(encrypted);\n  }\n}\n\nfunction generatePassword(): string {\n  const chars = [];\n  for (let i = 0; i < 8; i++) {\n    chars.push(Math.floor(Math.random() * 16).toString(16));\n  }\n  return \"Aa\" + chars.join(\"\") + \"1\";\n}\n\nfunction generateEmail(): string {\n  const chars = [];\n  for (let i = 0; i < 14; i++) {\n    chars.push(Math.floor(Math.random() * 36).toString(36));\n  }\n  return chars.join(\"\") + \"@gmail.com\";\n}\n\n// ==================== إنشاء حساب جديد ====================\nasync function createNewAccount() {\n  console.log(\"📋 جلب التذكرة...\");\n\n  const ticketRes = await fetch(\n    \"https://www.oreateai.com/passport/api/getticket\",\n    {\n      headers: {\n        \"Accept\": \"application/json, text/plain, */*\",\n        \"Accept-Language\": \"en-US,en;q=0.9\",\n        \"Client-Type\": \"pc\",\n        \"Locale\": \"en-US\",\n        \"Referer\": \"https://www.oreateai.com/home/vertical/aiImage\",\n        \"User-Agent\":\n          \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\",\n      },\n    },\n  );\n\n  const ticketData = await ticketRes.json();\n  const ticketID = ticketData.data.ticketID;\n  const publicKey = ticketData.data.pk;\n  const cookies = ticketRes.headers.getSetCookie?.() || [];\n\n  console.log(`✅ Ticket ID: ${ticketID}`);\n\n  console.log(\"📧 توليد بيانات الحساب...\");\n  const email = generateEmail();\n  const password = generatePassword();\n\n  console.log(`📧 البريد: ${email}`);\n  console.log(`🔑 كلمة المرور: ${password}`);\n\n  console.log(\"🔐 تحميل forge وتشفير كلمة المرور...\");\n  const forge = await loadForge();\n  const encryptedPassword = encryptPassword(password, publicKey, forge);\n  console.log(\"✅ تم التشفير\");\n\n  console.log(\"📝 إنشاء الحساب...\");\n  const cookieString = cookies.map((c) => c.split(\";\")[0]).join(\"; \");\n\n  const signupRes = await fetch(\n    \"https://www.oreateai.com/passport/api/emailsignupin\",\n    {\n      method: \"POST\",\n      headers: {\n        \"Accept\": \"application/json, text/plain, */*\",\n        \"Content-Type\": \"application/json\",\n        \"Cookie\": cookieString,\n        \"Locale\": \"en-US\",\n        \"Origin\": \"https://www.oreateai.com\",\n        \"Referer\": \"https://www.oreateai.com/home/vertical/aiImage\",\n        \"User-Agent\":\n          \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\",\n      },\n      body: JSON.stringify({\n        fr: \"GGSEMIMAGE\",\n        email,\n        ticketID,\n        password: encryptedPassword,\n        jt: \"\",\n      }),\n    },\n  );\n\n  const signupData = await signupRes.json();\n\n  if (signupData.status?.code !== 0) {\n    throw new Error(`فشل إنشاء الحساب: ${signupData.status?.msg}`);\n  }\n\n  const finalCookies = signupRes.headers.getSetCookie?.() || [];\n\n  const account: any = {\n    email,\n    password,\n    OUID: \"\",\n    i18n_locale: \"en-US\",\n    __bid_n: \"\",\n    g_state: \"\",\n    ouss: \"\",\n    sensorsdata2015jssdkcross: \"\",\n    cookies: finalCookies,\n  };\n\n  for (const cookie of finalCookies) {\n    if (cookie.includes(\"OUID=\")) {\n      account.OUID = cookie.match(/OUID=([^;]+)/)?.[1] || \"\";\n    } else if (cookie.includes(\"__bid_n=\")) {\n      account.__bid_n = cookie.match(/__bid_n=([^;]+)/)?.[1] || \"\";\n    } else if (cookie.includes(\"ouss=\")) {\n      account.ouss = cookie.match(/ouss=([^;]+)/)?.[1] || \"\";\n    } else if (cookie.includes(\"sensorsdata2015jssdkcross=\")) {\n      account.sensorsdata2015jssdkcross =\n        cookie.match(/sensorsdata2015jssdkcross=([^;]+)/)?.[1] || \"\";\n    }\n  }\n\n  account.g_state = JSON.stringify({\n    expiry: Date.now() + 86400000,\n    locale: \"en-US\",\n  });\n\n  console.log(\"✅✅✅ تم إنشاء الحساب بنجاح!\");\n\n  return account;\n}\n\n// ==================== إنشاء الهيدرز ====================\nfunction createHeaders(account: any) {\n  const cookieString = account.cookies.map((c: string) => c.split(\";\")[0]).join(\n    \"; \",\n  );\n\n  return {\n    \"Accept\": \"application/json, text/plain, */*\",\n    \"Content-Type\": \"application/json\",\n    \"Cookie\": cookieString,\n    \"Locale\": \"en-US\",\n    \"Origin\": \"https://www.oreateai.com\",\n    \"Referer\": \"https://www.oreateai.com/home/chat/aiImage\",\n    \"User-Agent\":\n      \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\",\n  };\n}\n\n// ==================== استخراج رابط الصورة ====================\nfunction extractImageUrl(result: string): string | null {\n  if (!result) return null;\n\n  console.log(\"🔍 محاولة استخراج الرابط من:\", result.substring(0, 200));\n\n  const parenMatch = result.match(/\\((https?:\\/\\/[^)]+)\\)/);\n  if (parenMatch) {\n    console.log(\"✅ تم استخراج الرابط بين قوسين:\", parenMatch[1]);\n    return parenMatch[1];\n  }\n\n  const urlMatch = result.match(\n    /(https?:\\/\\/[^\\s\"']+\\.(jpg|jpeg|png|gif|webp|bmp|svg))/i,\n  );\n  if (urlMatch) {\n    console.log(\"✅ تم استخراج رابط الصورة:\", urlMatch[1]);\n    return urlMatch[1];\n  }\n\n  const httpMatch = result.match(/(https?:\\/\\/[^\\s\"']+)/);\n  if (httpMatch) {\n    console.log(\"✅ تم استخراج رابط HTTP:\", httpMatch[1]);\n    return httpMatch[1];\n  }\n\n  if (result.startsWith(\"http\")) {\n    console.log(\"✅ النص نفسه هو الرابط:\", result);\n    return result;\n  }\n\n  console.log(\"❌ لم يتم العثور على رابط في النص\");\n  return null;\n}\n\n// ==================== تحويل الصورة إلى فريمات باستخدام PNG.js (بدون مشاكل SSL) ====================\nasync function downloadImageAsBuffer(url: string): Promise<Buffer> {\n  console.log(\"📥 تحميل الصورة...\");\n\n  // نحاول التحميل المباشر أولاً\n  try {\n    const response = await fetch(url, {\n      headers: {\n        \"User-Agent\":\n          \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\",\n        \"Accept\": \"image/webp,image/apng,image/*,*/*;q=0.8\",\n      },\n    });\n\n    if (response.ok) {\n      const arrayBuffer = await response.arrayBuffer();\n      return Buffer.from(arrayBuffer);\n    }\n  } catch (error) {\n    console.log(\"⚠️ فشل التحميل المباشر، نجرب طريقة بديلة...\");\n  }\n\n  // إذا فشل، نستخدم Google Viewer كثغرة لتجاوز SSL\n  try {\n    console.log(\"🔄 استخدام Google Viewer كبديل...\");\n    const googleViewerUrl =\n      `https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy?url=${\n        encodeURIComponent(url)\n      }&container=focus`;\n\n    const response = await fetch(googleViewerUrl, {\n      headers: {\n        \"User-Agent\":\n          \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\",\n      },\n    });\n\n    if (response.ok) {\n      const arrayBuffer = await response.arrayBuffer();\n      return Buffer.from(arrayBuffer);\n    }\n  } catch (error) {\n    console.log(\"⚠️ فشل Google Viewer...\");\n  }\n\n  // محاولة أخيرة مع WebArchive\n  try {\n    console.log(\"🔄 استخدام WebArchive...\");\n    const webArchiveUrl = `https://web.archive.org/web/2/${url}`;\n\n    const response = await fetch(webArchiveUrl, {\n      headers: {\n        \"User-Agent\":\n          \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\",\n      },\n    });\n\n    if (response.ok) {\n      const arrayBuffer = await response.arrayBuffer();\n      return Buffer.from(arrayBuffer);\n    }\n  } catch (error) {\n    console.log(\"⚠️ فشل WebArchive...\");\n  }\n\n  throw new Error(\"فشل تحميل الصورة من جميع المصادر\");\n}\n\nasync function imageToFrames(imageUrl: string) {\n  console.log(\"🖼️ تحويل الصورة إلى فريمات...\");\n\n  try {\n    // تحميل الصورة كـ Buffer\n    const imageBuffer = await downloadImageAsBuffer(imageUrl);\n\n    // محاولة فك تشفير الصورة كـ PNG\n    let png: any;\n    try {\n      png = PNG.sync.read(imageBuffer);\n    } catch (pngError) {\n      console.log(\"⚠️ الصورة ليست PNG، نحولها...\");\n\n      // إذا فشلت، نستخدم خدمة تحويل خارجية\n      const converterUrl = `https://images.weserv.nl/?url=${\n        encodeURIComponent(imageUrl)\n      }&output=png`;\n      const response = await fetch(converterUrl);\n      const convertedBuffer = await response.arrayBuffer();\n      png = PNG.sync.read(Buffer.from(convertedBuffer));\n    }\n\n    const width = png.width;\n    const height = png.height;\n    const data = png.data;\n\n    console.log(`📊 أبعاد الصورة: ${width} x ${height}`);\n\n    const frames = [];\n    const groupSize = 5; // كل 5 بيكسلات في نفس الصف = فريم واحد\n\n    for (let y = 0; y < height; y++) {\n      for (let x = 0; x < width; x += groupSize) {\n        let r = 0, g = 0, b = 0, count = 0;\n\n        // جمع الـ 5 بيكسلات\n        for (let i = 0; i < groupSize; i++) {\n          const px = x + i;\n          if (px >= width) break;\n\n          const idx = (y * width + px) * 4; // 4 لأن RGBA\n\n          r += data[idx];\n          g += data[idx + 1];\n          b += data[idx + 2];\n          // تجاهل alpha (data[idx + 3])\n          count++;\n        }\n\n        // حساب متوسط اللون\n        r = Math.round(r / count);\n        g = Math.round(g / count);\n        b = Math.round(b / count);\n\n        // تحويل إلى HEX\n        const color = `#${r.toString(16).padStart(2, \"0\")}${\n          g.toString(16).padStart(2, \"0\")\n        }${b.toString(16).padStart(2, \"0\")}`;\n\n        frames.push({\n          x,\n          y,\n          color,\n        });\n      }\n    }\n\n    console.log(\n      `✅ تم إنشاء ${frames.length} فريم (بدلاً من ${width * height} بيكسل)`,\n    );\n    return frames;\n  } catch (error: any) {\n    console.error(\"❌ خطأ في تحويل الصورة:\", error.message);\n\n    // إذا فشل كل شيء، نعيد مصفوفة فارغة مع محاولة بديلة\n    return [];\n  }\n}\n\n// ==================== توليد الصورة وتحويلها إلى فريمات ====================\nasync function generateImage(\n  prompt: string,\n  imageSize?: string,\n  style?: string,\n) {\n  let finalPrompt = prompt;\n\n  if (style) {\n    finalPrompt = `${finalPrompt}, ${style}`;\n  }\n\n  if (imageSize) {\n    finalPrompt = `${finalPrompt}\\nImage size: ${imageSize}`;\n  }\n\n  try {\n    console.log(\"🆕 إنشاء حساب جديد...\");\n    const account = await createNewAccount();\n    const headers = createHeaders(account);\n\n    console.log(`📝 البرومبت النهائي:`, finalPrompt);\n\n    console.log(\"   📝 إنشاء محادثة...\");\n    const chatRes = await fetch(\"https://www.oreateai.com/oreate/create/chat\", {\n      method: \"POST\",\n      headers,\n      body: JSON.stringify({ type: \"aiImage\", docId: \"\" }),\n    });\n\n    if (!chatRes.ok) {\n      throw new Error(\"فشل إنشاء المحادثة\");\n    }\n\n    const chatData = await chatRes.json();\n    const chatId = chatData.data?.chatId;\n\n    if (!chatId) throw new Error(\"لم يتم العثور على chatId\");\n\n    console.log(\"   ✅ Chat ID:\", chatId);\n\n    console.log(\"   🖼️ طلب الصورة...\");\n    const sseRes = await fetch(\"https://www.oreateai.com/oreate/sse/stream\", {\n      method: \"POST\",\n      headers: { ...headers, \"Accept\": \"text/event-stream\" },\n      body: JSON.stringify({\n        clientType: \"pc\",\n        type: \"chat\",\n        chatType: \"aiImage\",\n        chatId,\n        focusId: chatId,\n        from: \"home\",\n        isFirst: true,\n        messages: [{\n          role: \"user\",\n          content: finalPrompt,\n          attachments: [],\n        }],\n      }),\n    });\n\n    if (!sseRes.ok || !sseRes.body) {\n      throw new Error(\"فشل SSE\");\n    }\n\n    const reader = sseRes.body.getReader();\n    const decoder = new TextDecoder();\n    let buffer = \"\";\n    let fullResponse = \"\";\n    let imageUrl: string | null = null;\n\n    console.log(\"   ⏳ انتظار النتيجة...\");\n\n    while (true) {\n      const { done, value } = await reader.read();\n      if (done) break;\n\n      const chunk = decoder.decode(value, { stream: true });\n      buffer += chunk;\n      fullResponse += chunk;\n\n      const lines = buffer.split(\"\\n\");\n      buffer = lines.pop() || \"\";\n\n      for (const line of lines) {\n        if (!line.startsWith(\"data:\")) continue;\n\n        try {\n          const jsonStr = line.slice(5).trim();\n\n          if (jsonStr.includes(\"http\")) {\n            const extracted = extractImageUrl(jsonStr);\n            if (extracted) {\n              imageUrl = extracted;\n              break;\n            }\n          }\n\n          const json = JSON.parse(jsonStr);\n\n          if (json.data?.result) {\n            console.log(\"🎨 تم استلام result\");\n            const extracted = extractImageUrl(json.data.result);\n            if (extracted) {\n              imageUrl = extracted;\n              break;\n            }\n          }\n\n          if (json.data?.imageUrl) {\n            imageUrl = json.data.imageUrl;\n            break;\n          }\n\n          if (json.data?.url) {\n            imageUrl = json.data.url;\n            break;\n          }\n\n          if (json.event === \"error\") {\n            throw new Error(json.data?.msg || \"خطأ من السيرفر\");\n          }\n        } catch (e) {\n          // تجاهل أخطاء parsing\n        }\n      }\n\n      if (imageUrl) break;\n    }\n\n    if (!imageUrl) {\n      imageUrl = extractImageUrl(fullResponse);\n    }\n\n    if (imageUrl) {\n      console.log(\"✅ تم العثور على رابط الصورة:\", imageUrl);\n\n      // تحويل الصورة إلى فريمات\n      const frames = await imageToFrames(imageUrl);\n\n      const result: any = {\n        success: true,\n        metadata: {\n          width: imageSize || \"unknown\",\n          height: imageSize || \"unknown\",\n          frameCount: frames.length,\n          compression: `كل فريم يمثل 5 بيكسلات`,\n        },\n        account: {\n          email: account.email,\n          password: account.password,\n          OUID: account.OUID,\n        },\n      };\n\n      // إذا نجح التحويل، نضيف الفريمات\n      if (frames.length > 0) {\n        result.frames = frames;\n      } else {\n        // إذا فشل التحويل، نضيف رابط الصورة\n        result.imageUrl = imageUrl;\n        result.warning =\n          \"تم إرجاع رابط الصورة بدلاً من الفريمات بسبب مشكلة في التحويل\";\n      }\n\n      return result;\n    }\n\n    return {\n      success: false,\n      error: \"لم يتم العثور على صورة في الرد\",\n      fullResponse: fullResponse.substring(0, 500),\n    };\n  } catch (error: any) {\n    console.error(\"❌ خطأ:\", error.message);\n    return {\n      success: false,\n      error: error.message,\n    };\n  }\n}\n\n// ==================== API ====================\nconst app = new Hono();\n\n// نقطة نهاية POST\napp.post(\"/api/generate\", async (c) => {\n  try {\n    const body = await c.req.json();\n    const { prompt, imageSize, style } = body;\n\n    if (!prompt) {\n      return c.json({\n        success: false,\n        error: \"prompt مطلوب\",\n      }, 400);\n    }\n\n    const result = await generateImage(prompt, imageSize, style);\n\n    if (result.success) {\n      return c.json(result);\n    } else {\n      return c.json(result, 500);\n    }\n  } catch (error: any) {\n    return c.json({\n      success: false,\n      error: \"خطأ في معالجة الطلب: \" + error.message,\n    }, 500);\n  }\n});\n\n// نقطة نهاية GET\napp.get(\"/api/generate\", async (c) => {\n  try {\n    const prompt = c.req.query(\"prompt\");\n    const imageSize = c.req.query(\"imageSize\");\n    const style = c.req.query(\"style\");\n\n    if (!prompt) {\n      return c.json({\n        success: false,\n        error: \"prompt مطلوب\",\n      }, 400);\n    }\n\n    const result = await generateImage(prompt, imageSize, style);\n\n    if (result.success) {\n      return c.json(result);\n    } else {\n      return c.json(result, 500);\n    }\n  } catch (error: any) {\n    return c.json({\n      success: false,\n      error: \"خطأ في معالجة الطلب: \" + error.message,\n    }, 500);\n  }\n});\n\n// نقطة نهاية SSE\napp.get(\"/api/generate/stream\", async (c) => {\n  const prompt = c.req.query(\"prompt\");\n  const imageSize = c.req.query(\"imageSize\");\n  const style = c.req.query(\"style\");\n\n  if (!prompt) {\n    return c.json({ error: \"prompt مطلوب\" }, 400);\n  }\n\n  return streamSSE(c, async (stream) => {\n    try {\n      await stream.writeSSE({\n        data: JSON.stringify({\n          status: \"starting\",\n          message: \"بدء إنشاء حساب...\",\n        }),\n        event: \"status\",\n      });\n\n      const account = await createNewAccount();\n\n      await stream.writeSSE({\n        data: JSON.stringify({\n          status: \"account_created\",\n          email: account.email,\n          message: \"✅ تم إنشاء الحساب\",\n        }),\n        event: \"status\",\n      });\n\n      const headers = createHeaders(account);\n\n      await stream.writeSSE({\n        data: JSON.stringify({\n          status: \"creating_chat\",\n          message: \"إنشاء محادثة...\",\n        }),\n        event: \"status\",\n      });\n\n      const chatRes = await fetch(\n        \"https://www.oreateai.com/oreate/create/chat\",\n        {\n          method: \"POST\",\n          headers,\n          body: JSON.stringify({ type: \"aiImage\", docId: \"\" }),\n        },\n      );\n\n      const chatData = await chatRes.json();\n      const chatId = chatData.data?.chatId;\n\n      await stream.writeSSE({\n        data: JSON.stringify({ status: \"chat_created\", chatId }),\n        event: \"status\",\n      });\n\n      let finalPrompt = prompt;\n      if (style) finalPrompt = `${finalPrompt}, ${style}`;\n      if (imageSize) finalPrompt = `${finalPrompt}\\nImage size: ${imageSize}`;\n\n      await stream.writeSSE({\n        data: JSON.stringify({ status: \"generating\", prompt: finalPrompt }),\n        event: \"status\",\n      });\n\n      const sseRes = await fetch(\"https://www.oreateai.com/oreate/sse/stream\", {\n        method: \"POST\",\n        headers: { ...headers, \"Accept\": \"text/event-stream\" },\n        body: JSON.stringify({\n          clientType: \"pc\",\n          type: \"chat\",\n          chatType: \"aiImage\",\n          chatId,\n          focusId: chatId,\n          from: \"home\",\n          isFirst: true,\n          messages: [{\n            role: \"user\",\n            content: finalPrompt,\n            attachments: [],\n          }],\n        }),\n      });\n\n      const reader = sseRes.body?.getReader();\n      const decoder = new TextDecoder();\n\n      if (reader) {\n        while (true) {\n          const { done, value } = await reader.read();\n          if (done) break;\n\n          const chunk = decoder.decode(value);\n\n          const imageUrl = extractImageUrl(chunk);\n          if (imageUrl) {\n            await stream.writeSSE({\n              data: JSON.stringify({\n                status: \"image_received\",\n                message: \"✅ تم استلام الصورة، جاري تحويلها إلى فريمات...\",\n              }),\n              event: \"status\",\n            });\n\n            // تحويل الصورة إلى فريمات\n            const frames = await imageToFrames(imageUrl);\n\n            const result: any = {\n              account: {\n                email: account.email,\n                password: account.password,\n                OUID: account.OUID,\n              },\n            };\n\n            if (frames.length > 0) {\n              result.success = true;\n              result.frames = frames;\n              result.metadata = {\n                frameCount: frames.length,\n                compression: \"كل فريم يمثل 5 بيكسلات\",\n              };\n            } else {\n              result.success = true;\n              result.imageUrl = imageUrl;\n              result.warning = \"تم إرجاع رابط الصورة بدلاً من الفريمات\";\n            }\n\n            await stream.writeSSE({\n              data: JSON.stringify(result),\n              event: \"result\",\n            });\n            break;\n          }\n        }\n      }\n    } catch (error: any) {\n      await stream.writeSSE({\n        data: JSON.stringify({ error: error.message }),\n        event: \"error\",\n      });\n    }\n  });\n});\n\n// الصفحة الرئيسية\napp.get(\"/\", (c) =>\n  c.json({\n    status: \"online\",\n    message: \"OreateAI Image Generator API - مع تحويل الصور إلى فريمات\",\n    endpoints: {\n      \"POST /api/generate\": \"JSON body: { prompt, imageSize?, style? }\",\n      \"GET /api/generate\": \"Query params: ?prompt=...&imageSize=...&style=...\",\n      \"GET /api/generate/stream\": \"SSE stream لنفس المعاملات\",\n    },\n    example:\n      \"GET /api/generate?prompt=قطة%20صغيرة&imageSize=1024x1024&style=realistic\",\n  }));\n\nexport default app.fetch;","updated_at":"2026-03-07T22:40:49.759Z","project_name":"untitled-619","project_url":"https://www.val.town/x/zyloxtube/untitled-619/code/","username":"zyloxtube","description":null,"image_url":null,"matchedLines":[{"lineNumber":763,"lineContent":"      \"GET /api/generate/stream\": \"SSE stream لنفس المعاملات\",","isMatch":false},{"lineNumber":764,"lineContent":"    },","isMatch":false},{"lineNumber":765,"lineContent":"    example:","isMatch":true},{"lineNumber":766,"lineContent":"      \"GET /api/generate?prompt=قطة%20صغيرة&imageSize=1024x1024&style=realistic\",","isMatch":false},{"lineNumber":767,"lineContent":"  }));","isMatch":false}],"totalMatches":1},{"id":"91fddad8-1a4b-11f1-aa18-42dde27851f2","url":"https://www.val.town/x/ktreilly/my-first-val/code/04_email.ts","project_id":"91e099fa-1a4b-11f1-aa18-42dde27851f2","name":"04_email.ts","content":"// This code is triggered when an email is sent to its unique address.\n// Click \"Run\", copy and paste the email address and send an email to it.\n// This example will log the email details received.\nexport default async function emailHandler(email: Email){\n  console.log(\"Email received!\", email.from, email.subject, email.text);\n  for (const file of email.attachments) {\n    console.log(`Filename: ${file.name}`);\n    console.log(`Content Type: ${file.type}`);\n    console.log(`Content: ${await file.text()}`);\n  }\n}","updated_at":"2026-03-07T17:32:09.930Z","project_name":"my-first-val","project_url":"https://www.val.town/x/ktreilly/my-first-val/code/","username":"ktreilly","description":null,"image_url":null,"matchedLines":[{"lineNumber":1,"lineContent":"// This code is triggered when an email is sent to its unique address.","isMatch":false},{"lineNumber":2,"lineContent":"// Click \"Run\", copy and paste the email address and send an email to it.","isMatch":false},{"lineNumber":3,"lineContent":"// This example will log the email details received.","isMatch":true},{"lineNumber":4,"lineContent":"export default async function emailHandler(email: Email){","isMatch":false},{"lineNumber":5,"lineContent":"  console.log(\"Email received!\", email.from, email.subject, email.text);","isMatch":false}],"totalMatches":1},{"id":"91f6257c-1a4b-11f1-aa18-42dde27851f2","url":"https://www.val.town/x/ktreilly/my-first-val/code/03_cron.ts","project_id":"91e099fa-1a4b-11f1-aa18-42dde27851f2","name":"03_cron.ts","content":"// This cron runs on a schedule (e.g. every hour, day).\n// Configure the timer with the 🕒 icon in the top right.\n// This example just logs the current time.\nexport function scheduledHandler() {\n  const timestamp = new Date().toISOString();\n  console.log(`Cron val executed at: ${timestamp}`);\n  return `Executed at ${timestamp}`;\n}","updated_at":"2026-03-07T17:32:09.879Z","project_name":"my-first-val","project_url":"https://www.val.town/x/ktreilly/my-first-val/code/","username":"ktreilly","description":null,"image_url":null,"matchedLines":[{"lineNumber":1,"lineContent":"// This cron runs on a schedule (e.g. every hour, day).","isMatch":false},{"lineNumber":2,"lineContent":"// Configure the timer with the 🕒 icon in the top right.","isMatch":false},{"lineNumber":3,"lineContent":"// This example just logs the current time.","isMatch":true},{"lineNumber":4,"lineContent":"export function scheduledHandler() {","isMatch":false},{"lineNumber":5,"lineContent":"  const timestamp = new Date().toISOString();","isMatch":false}],"totalMatches":1},{"id":"91e44bae-1a4b-11f1-aa18-42dde27851f2","url":"https://www.val.town/x/ktreilly/my-first-val/code/README.md","project_id":"91e099fa-1a4b-11f1-aa18-42dde27851f2","name":"README.md","content":"# Welcome to Your First Val! 👋\n\nExplore our examples on the left:\n*   **01_script.tsx**: A simple script that returns a fun fact.\n*   **02_http.tsx**: An HTTP endpoint that greets you.\n*   **03_cron.tsx**: A cron that logs the time based on a schedule.\n*   **04_email.tsx**: An email handler that processes incoming email details.\n\nFeel free to edit these examples or add new files to your project.\n\nFor inspiration, check out our [Docs](https://docs.val.town/), [Templates](https://www.val.town/explore/use-cases), [Showcase](https://www.val.town/explore/community-showcase) and [Discord](https://discord.val.town/)!\n\nStay as long as you'd like in this project, or head to your main [dashboard](/dashboard) to keep exploring the rest of Val Town.","updated_at":"2026-03-07T17:32:09.762Z","project_name":"my-first-val","project_url":"https://www.val.town/x/ktreilly/my-first-val/code/","username":"ktreilly","description":null,"image_url":null,"matchedLines":[{"lineNumber":1,"lineContent":"# Welcome to Your First Val! 👋","isMatch":false},{"lineNumber":2,"lineContent":"","isMatch":false},{"lineNumber":3,"lineContent":"Explore our examples on the left:","isMatch":true},{"lineNumber":4,"lineContent":"*   **01_script.tsx**: A simple script that returns a fun fact.","isMatch":false},{"lineNumber":5,"lineContent":"*   **02_http.tsx**: An HTTP endpoint that greets you.","isMatch":false},{"lineNumber":7,"lineContent":"*   **04_email.tsx**: An email handler that processes incoming email details.","isMatch":false},{"lineNumber":8,"lineContent":"","isMatch":false},{"lineNumber":9,"lineContent":"Feel free to edit these examples or add new files to your project.","isMatch":true},{"lineNumber":10,"lineContent":"","isMatch":false},{"lineNumber":11,"lineContent":"For inspiration, check out our [Docs](https://docs.val.town/), [Templates](https://www.val.town/explore/use-cases), [Showcase](https://www.val.town/explore/community-showcase) and [Discord](https://discord.val.town/)!","isMatch":false}],"totalMatches":2},{"id":"cb8235ce-1a3c-11f1-becb-42dde27851f2","url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/posts/proposal.md","project_id":"972467e0-e985-11ef-b2c8-e6cdfca9ef9f","name":"proposal.md","content":"---\ntitle: I proposed to my girlfriend in Quordle\ntags: personal\ndate: 2025-02-17\n---\n\n# I proposed to my girlfriend in Quordle\n\n![Emilrdle screenshot](https://stevekrouse-blob_admin.web.val.run/api/public/emilrdle1.png)\n\nEmily loves puzzles. Every day she plays Wordle, the New York Times Mini, Connections, Spelling Bee, LinkedIn Tango and Queens, and Quordle, in that order.\n\nI thought it'd be fun to propose in one of her favorite games. It's appropriate, after all, because Wordle itself was created for love. But which game would work?\n\nAt the end of the day you have to say \"Will you marry me?\" so that ruled out many options. How can you fit that into Wordle or Connections? I tried my hand at a crossword, but damn those are hard!\n\nEventually I realized the question would fit inside Quordle, but with extra letters. For context, [Quordle](https://www.merriam-webster.com/games/quordle/#/) is four Wordles that you're playing at the same time. I'd deal with the extra letters by having them fall away at the end, leaving the big question. The first set of words I came up with were \"Willy\", \"Youth\", \"Marry\", and \"Meaty\", but I eventually changed \"Meaty\" to \"Meter\" because Emily *loves* when words end with \"er\".\n\nEnter AI. I work at [Val Town](https://val.town), and we make a website for programmers to build apps. [Townie](https://val.town/townie) is our AI-assistant that writes Val Town apps for you. I started with a very simple prompt and a screenshot of Quordle.\n\nOn a cold December night at Betaworks in Chelsea, I cozied up and worked with Townie for 90 minutes. It was one of David Bieber's wonderful hack nights, so the atmosphere was perfect. By the end of the night, it was done. I remember it being a lot of fun.\n\nLooking back at the chat history, I see that there are [91 versions](https://www.val.town/v/stevekrouse/emilrdle/versions), which means I was averaging about one edit per minute. It takes Townie, powered by Claude 3.5 Sonnet, about 30-60 seconds to rewrite a couple hundred lines of code, so that would account for the speed. I think most of those edits were through Townie, but I also made some manual edits to the code for smaller changes.\n\nThe basic mechanics of Quordle were more complicated than I'd realized. For example, the keys on the on-screen keyboard need to be colored appropriately, green, yellow, gray, and black, representing whether that letter is in the right spot, wrong spot, not in the word, or not played yet, respectively, and in four quadrants, for the four different Wordle boards on-screen. Also each of the attempts on each Wordle board needs to be colored appropriately, with subtle rules governing various end states.\n\nBut after I got the basic mechanics working, the game felt flat somehow. I pulled up the original and noticed all sorts of tiny micro interactions that gave the game life. When you press on a letter on the keyboard, it moves up and turns another color. When a letter shows up on the screen, it animates in. When you get a word correct, it animates in in a flipboard style.\n\nI also wanted to copy how Quordle highlights invalid words in red, but for that I needed a list of valid words. It was suprisingly easy to find the list that Quordle itself was using. I popped open the Chrome Network tab, navigated to Quordle, and hit Cmd+F to get the Search across everything. There I just put a random word that I knew to be on the list, \"youth\", and voila. I found it interesting to see the lists, broken up into a `wordBank`, `blacklist`, and `allowed`. I went with the `allowed` list.\n\nI later realized that the letters-falling-away animation at the end happened quite quickly, so I needed some way to slow it down, and get her attention. I could imagine her looking away right when she gets the last word, and she'd miss it. So I had Townie add a modal when she won, asking her if she's ready for the next level.\n\n<script src=\"https://cdn.jsdelivr.net/npm/@mux/mux-player\"></script>\n<div style=\"height: 500px\">\n  <mux-player\n    playback-id=\"VWFLATfcYjHM3UCi8RWwqrGEGi8FbfrUUiu01QzXhclM\"\n    metadata-video-title=\"Emilrdle proposal\"\n    primary-color=\"#ffffff\"\n    secondary-color=\"#000000\"\n    accent-color=\"#fa50b5\"\n    controls\n    autoplay\n    muted\n    loop\n  ></mux-player>\n</div>\n\nThe morning I decided to do it, we first started with her normal word games. Then I announced that I made her a word game. She was excited. She enjoyed the Quordle, but was a bit confused why all the words were so random. The only one that had any significance was \"meter\", because it ended in \"er\", but even that significance was weak. Safe to say she had no clue what was coming. She got to the win screen and was ready for the next level. The letters fell away and she turned to me and said, \"What?\"\n\nThe rest happened in a blur, but I did get down on one knee and pull out a ring. She said yes.\n\n<img style=\"max-height: 500px; width: auto; display: block; margin: 0 auto\" src=\"https://stevekrouse-blob_admin.web.val.run/api/public/emilIMG_3220.JPG\" />\n\nYou can play [Emilrdle here](https://stevekrouse-emilrdle.web.val.run/). The next level is reserved for Emily.\n","updated_at":"2026-03-07T15:46:23.973Z","project_name":"stevekrouse_dot_com","project_url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/","username":"stevekrouse","description":"The personal site of Steve Krouse, stevekrouse.com","image_url":null,"matchedLines":[{"lineNumber":23,"lineContent":"Looking back at the chat history, I see that there are [91 versions](https://www.val.town/v/stevekrouse/emilrdle/versions), which means I was averaging about one edit per minute. It takes Townie, powered by Claude 3.5 Sonnet, about 30-60 seconds to rewrite a couple hundred lines of code, so that would account for the speed. I think most of those edits were through Townie, but I also made some manual edits to the code for smaller changes.","isMatch":false},{"lineNumber":24,"lineContent":"","isMatch":false},{"lineNumber":25,"lineContent":"The basic mechanics of Quordle were more complicated than I'd realized. For example, the keys on the on-screen keyboard need to be colored appropriately, green, yellow, gray, and black, representing whether that letter is in the right spot, wrong spot, not in the word, or not played yet, respectively, and in four quadrants, for the four different Wordle boards on-screen. Also each of the attempts on each Wordle board needs to be colored appropriately, with subtle rules governing various end states.","isMatch":true},{"lineNumber":26,"lineContent":"","isMatch":false},{"lineNumber":27,"lineContent":"But after I got the basic mechanics working, the game felt flat somehow. I pulled up the original and noticed all sorts of tiny micro interactions that gave the game life. When you press on a letter on the keyboard, it moves up and turns another color. When a letter shows up on the screen, it animates in. When you get a word correct, it animates in in a flipboard style.","isMatch":false}],"totalMatches":1},{"id":"f264fbf0-1a3b-11f1-a11c-42dde27851f2","url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/posts/model.md","project_id":"972467e0-e985-11ef-b2c8-e6cdfca9ef9f","name":"model.md","content":"---\ntitle: Find a model\ntags: advice, creativity\ndate: 2025-03-24\n---\n\n# Find a model\n\n![a woman painting a landscape](https://stevekrouse-blob_admin.web.val.run/api/public/model.jpeg)\n*\"a woman painting a landscape\" by [Fal Demo App](https://www.val.town/v/stevekrouse/falDemoApp)*\n\nOne of the most common pieces of advice I give to mentees is to \"find a model.\" It's a stupid-simple technique, but can transform how you work. It will let you do things faster, better, and with more confidence. It's a mystery that everybody doesn't use it all the time.\n\nThe core of the technique is to find a model artifact to keep an eye on while you work on your artifact, which could be a coding project, a song, a painting, an email, a social media post, an essay like this one, etc.\n\nThe are three important benefits to this technique.\n\n## A north star\n\nA model gives you a north star; something to shoot to; something you can visually compare your work to, and see what's missing; a yardstick by which you can measure how \"done\" your artifact is. Without a model, how do you even know what kind of thing you're making? How can you tell its shape? A model is like a hyper-specific template that lets you stay focused on the end goal.\n\nThere are many related principles: [Backward Chaining](https://en.wikipedia.org/wiki/Backward_chaining), [Top-down design](https://en.wikipedia.org/wiki/Bottom-up_and_top-down_design), [The XY Problem](https://en.wikipedia.org/wiki/XY_problem), and Amazon's principle to \"Write the Press Release First\". These all get at the idea that you don't want to lose sight of the end goal. Without a model, you risk getting lost in the details. Losing the forest for the trees. A model helps you keep the whole forest in sight, so you actually create what you set out to.\n\nHowever, it's important to remember that \"Plans are useless, but planning is indispensable.\" In other words, you shouldn't feel compelled to stick to your model so closely. Use the parts that you want, and forget about the rest. A model is high up on [The Ladder of Abstraction](), but that doesn't mean you can't change it. If you realize that you chose the wrong model or that your goals have changed, excellent. Time to find a better model.\n\nThe fact that you have a model is what allows you to realize when you have the wrong model. Imagine you're a ship captain navigating by a star that you thought was the north star, but then later realized was just Venus. The time you wasted navigating by Venus would've been equally wasted if you were navigating without reference to any star. At least when you're navigating by Venus one of your fellow sailors can come over your shoulder and say, \"Hey captain, I think that's Venus.\" If you're navigating by nothing, then you're truly lost at sea.\n\n## Un-stuck-ing yourself\n\nAnother reason to have model is that it's very helpful when you get stuck. Don't know how to do something? See how your model does it.\n\nFor this essay I felt stuck on the first line. This essay's model is [Do things that don't scale](https://www.paulgraham.com/ds.html), because it's an essay that explains a cognitive technique. Its first sentence isn't the prettiest, but it gets the idea across and it's a hook: \"One of the most common types of advice we give at Y Combinator is to do things that don't scale.\"\n\nNow go back and read my first line. Is it deritive? Yes. Would literally anyone have noticed if I didn't draw your attention to it? No. There's something profoundly true about the line oft-attributed to Picasso, \"Good artists borrow. Great artists steal.\" I didn't truly believe this quote until I read [The Elements of Eloquence](https://en.wikipedia.org/wiki/The_Elements_of_Eloquence), wherein he shows examples of Shakespeare lifting whole sentences out of other books and plays, only changing a couple words.\n\nIn school, they call this behavior cheating, which is probably why this technique isn't practiced more often. I think it's an important lesson to unlearn. Why reinvent the wheel? Save time so you can focus on your unique contribution. Just be sure to give attribution and credit where it's due.\n\n## Maybe someone already did it, so you don't have to\n\nHow many times have you built something only later to realize someone else already built it? Chances are that if an idea occurs to you, likely it has occured to someone like you. So many people don't even take a second to google around before embarking on a project. Instead of wasting your time reinventing the wheel, see if someone already invented it. Then stop. Just use their thing.\n\n## How to find a model\n\nOne reason \"finding a model\" isn't more common is that it can be quite difficult to find a good model. I call that technique [\"surveying the space\"](./survey).\n","updated_at":"2026-03-07T15:44:04.248Z","project_name":"stevekrouse_dot_com","project_url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/","username":"stevekrouse","description":"The personal site of Steve Krouse, stevekrouse.com","image_url":null,"matchedLines":[{"lineNumber":32,"lineContent":"For this essay I felt stuck on the first line. This essay's model is [Do things that don't scale](https://www.paulgraham.com/ds.html), because it's an essay that explains a cognitive technique. Its first sentence isn't the prettiest, but it gets the idea across and it's a hook: \"One of the most common types of advice we give at Y Combinator is to do things that don't scale.\"","isMatch":false},{"lineNumber":33,"lineContent":"","isMatch":false},{"lineNumber":34,"lineContent":"Now go back and read my first line. Is it deritive? Yes. Would literally anyone have noticed if I didn't draw your attention to it? No. There's something profoundly true about the line oft-attributed to Picasso, \"Good artists borrow. Great artists steal.\" I didn't truly believe this quote until I read [The Elements of Eloquence](https://en.wikipedia.org/wiki/The_Elements_of_Eloquence), wherein he shows examples of Shakespeare lifting whole sentences out of other books and plays, only changing a couple words.","isMatch":true},{"lineNumber":35,"lineContent":"","isMatch":false},{"lineNumber":36,"lineContent":"In school, they call this behavior cheating, which is probably why this technique isn't practiced more often. I think it's an important lesson to unlearn. Why reinvent the wheel? Save time so you can focus on your unique contribution. Just be sure to give attribution and credit where it's due.","isMatch":false}],"totalMatches":1},{"id":"1395c7c4-f948-11f0-9da0-42dde27851f2","url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/posts/request-for-school.md","project_id":"972467e0-e985-11ef-b2c8-e6cdfca9ef9f","name":"request-for-school.md","content":"---\ntitle: Request for School\ntags: education, parenting\ndate: 2026-02-19\n---\n\n# Request for School\n\n_Location: Brooklyn, NY_\n\nEver since I went to a magical after-school program\n([IMACS](https://www.imacs.org/)) that helped me go from hating to falling in\nlove with math, I've been extremely passionate about education. To learn about\neducation, I've read dozens of books, visited schools, did a lot of tutoring and\nteaching, and eventually started my own after-school computer science program\nhere in NY, [The Coding Space](https://www.thecodingspace.com/).\n\nMy biggest educational influences are Seymour Papert, The Sudbury Valley School,\nBlake Boles, John Holt, and John Taylor Gatto.\n\nI believe that humans learn best at their own pace, voluntarily,\nself-directedly, so they have a chance to develop an intimate, positive\nemotional relationship with the material.\n\nI believe that a lot of what traditional schools do is actively harmful to\nchildren: large classrooms, curriculum, lectures, tests, homework, etc. These\none-sized-fits-all tools are useful for school systems to manage mass-education\nat scale, but they are woefully worse than more humane and tailored approaches.\n\nFor example,\n[Bloom's Two Sigma Problem](https://en.wikipedia.org/wiki/Bloom%27s_2_sigma_problem)\nshows that literally all students can get A's in all subjects if instead of\ngetting lectured at, they get a personalized tutor. Erik Hoel writes at length\nabout how\n[we used to produce Einsteins through what he calls Aristocratic Tutoring](https://www.theintrinsicperspective.com/p/why-we-stopped-making-einsteins).\nEspecially with modern technology, such as the internet, computers, google,\nwikipedia, not even including recent advances in AI, there are definitely\ncost-effective ways to get every child the attention they deserve. For starters,\nthe flipped classroom model works wonders; that's what I experienced 20 years\nago at IMACS. Secondly, if you remove the overhead of paying for extensive\nadministration of a school, then you can much more affordably scale 1:4 teacher\nto student ratios.\n\nThis is why homeschooling is on the rise. It's growing at an insane rate right\nnow!\n\nYet, it feels depressing to keep a child alone at home all day, learning with\njust mom, and on the computer by themselves.\n\nIt feels like there should be another option that's a vibrant, social place for\nchildren to go that's a culturally rich environment to learn, be creative, make\nfriends, go on adventures, do projects, play make-believe, have fun, learn\nlessons, have space for academic rigor and play, silliness and serious\nproductive fun, time to run around outside and focus time inside, time to read\nwhatever you want, time to go on a walk with friends.\n\nGiven how much I care about this, I fear that I might have to create this\n\"school\" myself: provide this vision, recruit the leaders, teachers, other\nparents and students, to help get it off the ground. If this sounds like your\nlife's work, please reach out!\n\nHowever, I'd be much happier to find that a school close enough to my dream,\nclose enough to where we want to live, and just get to send our kids there,\nwithout having to start it ourselves! **Would you know of such a school?**\n\nIs a Montessori school close enough to what I'm looking for? What about Waldorf?\nAre there any other good pre-existing options in my area?\n\nMy fiancé Emily and I are planning to raise a family in Brooklyn, NY. We\ncurrently live in Prospect Heights. We plan to have 2-3 kids.","updated_at":"2026-03-07T15:33:07.771Z","project_name":"stevekrouse_dot_com","project_url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/","username":"stevekrouse","description":"The personal site of Steve Krouse, stevekrouse.com","image_url":null,"matchedLines":[{"lineNumber":28,"lineContent":"at scale, but they are woefully worse than more humane and tailored approaches.","isMatch":false},{"lineNumber":29,"lineContent":"","isMatch":false},{"lineNumber":30,"lineContent":"For example,","isMatch":true},{"lineNumber":31,"lineContent":"[Bloom's Two Sigma Problem](https://en.wikipedia.org/wiki/Bloom%27s_2_sigma_problem)","isMatch":false},{"lineNumber":32,"lineContent":"shows that literally all students can get A's in all subjects if instead of","isMatch":false}],"totalMatches":1},{"id":"a5c2ca32-0921-11f1-a57c-42dde27851f2","url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/posts/abstraction.md","project_id":"972467e0-e985-11ef-b2c8-e6cdfca9ef9f","name":"abstraction.md","content":"---\ntitle: Delegation & management is what you do when you lack proper tools & abstractions\ntags: ai, programming, philosophy\ndate: 2025-03-01\n---\n\n# Delegation & management is what you do when you lack proper tools & abstractions\n\nIn other words, AI Agents are NOT the future of software development.\n\nBut it's no surprise everyone is confused.\n\n## New media mimics old media\n\nNew media always initially resembles old media. Early television resembled film and radio. Early web pages looked like newspapers. \n\nIt took decades for tv, movies, tiktok, and algorithmic feeds to emerge. And to move from banner ads to google ads.\n\nAI is the same. Our closest analogue is the software engineering employee, so of course we're delegating to it. And to scale up, we think we need to scale up our employees, and all the sudden, we are managers.\n\nBut management sucks. We should all want to be superpowerful craftspeople (think Iron Man), not managers of armies of minions.\n\nIf you're thinking about managing your swarm of 20 AI agents, stop! You've gone too far! This is the equivalent of wondering how in 1910 you'll hitch 20 horses to a wagon to achieve 60mph speeds. You're in the wrong paradigm entirely.\n\nOr like thinking that the way to replace a room full of human accountants is a swarm of digital accountants. No! It's a spreadsheet and a single human. The fact that calculations are happening under the hood is transparent to the user.\n\n## Agents are an implementation detail\n\nAI Agents are an incredible *implementation detail*. You can dramatically increase the effectiveness of AI, when you put it in a feedback loop with its environment. This is undeniable.\n\nThis does NOT mean that we humans have to INTERFACE with agents. Back to a car analogy: whether it's an internal combustion engine or an electric motor, the interface to a car is the same steering wheel and pedals. Nobody has to MANAGE the firing of the pistons.\n\nThe same should be true for human programmers. We should not tie ourselves to the interface of delegating to agents.\n\nWhy? Because delegation & management are the worst possible ways of increasing ones leverage. \n\nYou should only succumb to delegation & management when all other methods fail you.\n\nAny use of delegation & management is a cry for a better abstraction or tool.\n\nFor example, booking a flight. We used to call travel agents. Now we have web interfaces that are better. You can express your preferences more quickly and precisely. You can use your monkey eyes to quickly take in all the options and trade-offs.\n\nYet, people still hate booking flights and often do delegate it to their assistants. Why?\n\nBecause the interface still isn't good enough! It still takes a way too many unnecessary clicks. \n\nThink about ecommerce before amazon & shopify optimized the checkout flows. I know very few people who delegate buying stuff on amazon. The interface has minimized incidental complexity.\n\nBut what about when you don't care about the details and just want something to work? For example, \n@pete_millspaugh\n told me about how his car has an issue. He tried to solve it himself, but he just doesn't have the time to learn about cars and how to fix them. Ultimately, he just wants a working car, not an understanding of cars. Thus, he delegates to a mechanic.\n\nThis is fine, but we should acknowledge that it's still the lack of sufficient tools that makes this delegation necessary. In this particular case, a big part of the problem seems to be a lack of observability.\n\n## Observability: a case study\n\nThis is similar to web servers that lack good observability. You would need to delegate to humans to ssh into various servers and read log streams, hunting for what could be going wrong. \n\nOr you could invest in observability tooling. When an issue comes up, one human at a once glance can see exactly where the problem is. If your observability is good enough, you can even automate remediation measures\n\nLet's pause and meditate on the distinction between delegating to your 4 human teammates to ssh around to find the issue vs an observability + remediation tool that automatically detects issues (like a ddos) and blocks the proper ip addresses. The second case may superficially appear like delegation, but it is in fact a TOOL at the right level of ABSTRACTION.\n\nThe same thing is happening in code. Humans are delegating the writing of code to AI agents. Humans are not reading this code. (You can call this \"vibe code\" or \"write-only code\".) People say that this is just the next step up in higher-level programming languages.\n\nYes, it's true that \"code nobody reads\" is not new. When we compile C to Assembly, nobody reads the Assembly. (Unless it's a leaky abstraction.) So isn't English the newest high-level programming language?\n\n## English is not a programming language\n\nNo! English is a very bad interface for expressing programming ideas.\n\nAs Dijkstra said, \"The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise.\"\n\nEnglish is vague. Programming requires precision. The whole point of higher-level languages is to let you be precise at the right level — not to let you be imprecise.\n\nAs Bertrand Russel said, \"Everything is vague to a degree you do not realize till you have tried to make it precise.\"\n\nOr as Dijkstra said, \"Instead of regarding the obligation to use formal symbols as a burden, we should regard the convenience of using them as a privilege: thanks to them, school children can learn to do what in earlier days only genius could achieve.... When all is said and told, the \"naturalness\" with which we use our native tongues boils down to the ease with which we can use them for making statements the nonsense of which is not obvious.\"\n\nBut then why does prompt-to-app work so well? \n\nFor example, the last couple of days, I vibe coded a couple of small apps, barely looking at the code. It was super fun and useful! (Guys, I promise, I'm not a hater. I LOVE AI. Just ask my teammates or my fiancée.)\n\nThe code was meh, but that didn't matter. This does superficially seem similar to how we don't care that compiled bytecode is impossible to maintain.\n\nBut alas we get to the heart of the matter: an abstraction is a transparent tool. Unless something goes very wrong (ie abstraction leakage), when you use Python to describe something, you know exactly what's happening under the hood and how to steer it. This is similar to the controls of a car. You don't have to know anything about how the engine works to drive. These are good abstractions.\n\nThe same is true for no-code and low-code tools, like Wix, Squarespace, Zapier, Retool. These are very precise tools at a higher-level of abstraction. You know exactly what they are doing and how to make them do what you want.\n\nAn important property of a tool is the feedback it gives to the human about what is possible. You make a precise change and get immediate feedback. This is getting your hands wet in the clay. English-as-programming language does a very poor job at this. Especially when you're waiting minutes for any feedback.\n\nVibe coding (coding without looking at the code) is very similar to using a website builder like Squarespace. The generated code really does not matter. Until you want to do something complex. Then you're in trouble.\n\nUltimately, in my opinion, there is irreducible complexity in building software, and thinking that we can paper over it with english and smarter agents is wrong. It's not having enough respect for the underlying complexity, and how hard it is to build better abstractions.\n\nI've spent years of my life trying to build better abstractions and programming languages, ie improvements over react or http to make it easier for folks to build web apps. It's hard! At the end of the day, the state of the art is complex React, plus a hand-rolled server, and a lot of hard engineering work to make it all work.\n\nDon't you think if there were better abstractions available us programmers would use them?\n\nNo matter how smart AI gets, AI will be subject to the same laws of intelligence that humans are. Good code will be just as – if not more – important for AIs to write than it is for humans to write, and for the same reasons.\n\nThinking that understandable code doesn't matter is like thinking that it doesn't matter how heavy the materials we build buildings out of in the future because we can just build robots that are strong enough to carry it. Sure, but why waste the power? \n\nWe can put genius programmers on a shitty codebase and they can figure it out, but they'll be 100x more productive if you let them pay down the tech debt, and work in a beautiful codebase. The same will be true for AI.\n\n## The future of programming\n\nSo what is the future of coding with AI?\n\nThat's the wrong question. \n\nThe right question is: what is the future of programming we want? What is the dream programming experience 10 years from now to build some specific piece of software?\n\nThe fact that we'll have faster, cheaper, smarter AI is a given, in the same way that we'll have faster and cheaper cpus and gpus.\n\nAlan Kay invented the personal computer by buying his way into the future, in the 70s, spending millions on what would be commodity hardware in the 90s.\n\nBret Victor showed what a dream Learnable Programming environment would look like in 2012, which we still haven't been able to implement. There was no AI involved, simply because it wasn't the limiting factor for making programming more learnable.\n\nSoftware creation should be a transparent tool, with amazing abstractions, that removes all drudgery from programming, that lets you get even closer to the problem domain than before, lets you use your brain maximally, learn maximally, stay in a flow state, complete tasks quickly, manage lots of complexity, maintain and refactor large brownfield apps over long periods of time joyfully\n\nThis is the future we should be shooting for. Agents will certainly play a part, but in the same way that pistons play a part in internal combustion engines. Humans should use a steering wheel or pick their precise desired location on a map.","updated_at":"2026-03-07T15:33:06.405Z","project_name":"stevekrouse_dot_com","project_url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/","username":"stevekrouse","description":"The personal site of Steve Krouse, stevekrouse.com","image_url":null,"matchedLines":[{"lineNumber":39,"lineContent":"Any use of delegation & management is a cry for a better abstraction or tool.","isMatch":false},{"lineNumber":40,"lineContent":"","isMatch":false},{"lineNumber":41,"lineContent":"For example, booking a flight. We used to call travel agents. Now we have web interfaces that are better. You can express your preferences more quickly and precisely. You can use your monkey eyes to quickly take in all the options and trade-offs.","isMatch":true},{"lineNumber":42,"lineContent":"","isMatch":false},{"lineNumber":43,"lineContent":"Yet, people still hate booking flights and often do delegate it to their assistants. Why?","isMatch":false},{"lineNumber":47,"lineContent":"Think about ecommerce before amazon & shopify optimized the checkout flows. I know very few people who delegate buying stuff on amazon. The interface has minimized incidental complexity.","isMatch":false},{"lineNumber":48,"lineContent":"","isMatch":false},{"lineNumber":49,"lineContent":"But what about when you don't care about the details and just want something to work? For example, ","isMatch":true},{"lineNumber":50,"lineContent":"@pete_millspaugh","isMatch":false},{"lineNumber":51,"lineContent":" told me about how his car has an issue. He tried to solve it himself, but he just doesn't have the time to learn about cars and how to fix them. Ultimately, he just wants a working car, not an understanding of cars. Thus, he delegates to a mechanic.","isMatch":false},{"lineNumber":79,"lineContent":"But then why does prompt-to-app work so well? ","isMatch":false},{"lineNumber":80,"lineContent":"","isMatch":false},{"lineNumber":81,"lineContent":"For example, the last couple of days, I vibe coded a couple of small apps, barely looking at the code. It was super fun and useful! (Guys, I promise, I'm not a hater. I LOVE AI. Just ask my teammates or my fiancée.)","isMatch":true},{"lineNumber":82,"lineContent":"","isMatch":false},{"lineNumber":83,"lineContent":"The code was meh, but that didn't matter. This does superficially seem similar to how we don't care that compiled bytecode is impossible to maintain.","isMatch":false}],"totalMatches":3},{"id":"027672b6-f4a4-11f0-be9a-42dde27851f2","url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/posts/advice.md","project_id":"972467e0-e985-11ef-b2c8-e6cdfca9ef9f","name":"advice.md","content":"---\ntitle: Advice to college students in 2026\ntags: advice, education, startups, legibility\ndate: 2026-01-01\n---\n\n# Advice to college students in 2026\n\nOn Friday, a group of students will be visiting by my office as part of \"Penn\nTech Trek\", a program where Penn students visit tech companies. I went on two\namazing Tech Treks, one in NY and one in SF, so I am really excited to get to\npay it forward for the next generation.\n\nSo I sat down and thought about:\n\n- What I wish someone would've told me when I was in college\n- What I learned since I graduated\n- What advice I'd give to a college graduate in 2026\n\n### AI\n\nI feel like in 2026 you have to start with AI. It's just in the air, so much\nexcitement and fear. What jobs will be left? It's a wild time to be joining the\nworkforce!\n\nI've been thinking a lot about workout classes. For most of human history,\nworking out was a part of life, farming, cleaning, etc. But then we automated\n99% of physical labor, which is why it seems like there's a gym or yoga studio\non every block. If you told a farmer in the year 1800 that 99% of people\nwouldn't farm in the future, he'd be very confused. What are these muscles for?\nWhat jobs will there be?\n\nThe same may be true for us. Maybe brains won't be required for work. Maybe\nwe're about to automate thinking.\n\nWhat's left? The human touch. Take solace in the fact that we don't watch robots\nplay basketball or chess, or make art.\n\nAlso: if there's no job for you because a robot can do anything you can do\nbetter, then that also _necessarily_ means there's _incredible_ abundance in\nsociety. Maybe we all become like trust-fund kids looking to make life\nmeaningful. There's always teaching or art.\n\nBut most importantly, I want to share a lesson about bubbles. A very smart\nfriend called me frantically about how they feel like they need to quit their\njob and join a company to get in while it's good, because this is a\nonce-in-a-lifetime new industry being born. I told her she should take a deep\nbreath. Hype cycles come and go. It's hard to have historical perspective on\nyour first one. She didn't believe me. But that wasn't even AI! That was crypto.\nThat's how all-consuming bubbles are. I know this one feels different, but\nthat's how they all feel. So we should all take a deep breath.\n\n## Legibility\n\nLegibility means giving the world affordances for how they can interact with you\nand fit you into their lives – for jobs, romance (have you heard of\n[Date Me Docs](https://dateme.directory/)?), friends, collaborators, vendors,\netc. You can think of it as your \"interface\", like your own personal API. Or as\nHenrik says,\n\"[A blog post is a very long and complex search query to find fascinating people and make them route interesting stuff to your inbox](https://www.henrikkarlsson.xyz/p/search-query)\".\n\nBy default, you're invisible to the world. At the other end of the spectrum are\ntruly famous people. I'm talking about this secret third thing where you put a\nlot of stuff about yourself and what you're interested in, working on, thinking\nabout, etc, online so that you are a visible person.\n\nWhen I started the Future of Coding podcast & community and blogged super\npublicly, I thought about creating a lighthouse to attract my people and\ncollaborators. I walked into an empty room and started talking at the walls and\nyou'll never guess what happened next. People came into the room! And they're\nstill there! (Even though I left!)\n\nLegibility is how I found some of my best friends, investors, employees and\nsolutions to my problems. Unfortunately Twitter is not what it was, but find a\nplace where you can post online – a link is all that matters – and do as much of\nit as you can. Quantity over quality, excluding slop, of course.\n\nA well-phrased problem is a problem half solved. In framing it, you sometimes\nsolve it. Now that it's written down you can email it to friends, tweet it, ask\nAI. I had incredible back pain and was complaining about it to a friend who had\na super kooky solution that worked out.\n\nHowever, don't let illegibility stop you from doing things, especially in the\nearliest days. When I started my independent researcher / podcaster phase,\neveryone in my life thought I was crazy, and it was hard to explain to folks\nwhat I was doing. I just kept talking about it online in whatever way I could,\nand it got more legible over time. Henrik does a great job explaining the\nimportance of illegibility in\n[Looking for Alice](https://www.henrikkarlsson.xyz/p/looking-for-alice).\n\n## People\n\nLikely, the best work you'll ever do will be with people. Either you choose\nthem, or they'll be chosen for you. (Either you'll hire them or you'll join a\nteam.) Take this incredibly seriously. Your job is to cultivate your\nrelationships and future coworkers, employers, and employees.\n\nTreating people super well is such an amazing hack, and it's easy to justify all\nthe way up and down the value chain.\n\nFigure out (and continually refine) what your values are so you can spot when\nyour partners don't share them and end things earlier, saving yourself\nheartache. For example, I value reading, writing, honesty, integrity, kindness,\nself-awareness, legibility, nerdiness, personal projects.\n\n## Reading\n\nReading is important.\n\nMy strategy is to stop reading or listening whenever I'm bored. Don't let the\nwrong book stop you from reading the right one. Boring books will become\ninteresting when the timing is right. I mostly do audiobooks. It's important to\nplay with speed to keep you engaged. Fiction counts.\n\nThe solutions to a lot of your problems exist, and someone took the time to\nwrite them down. Don't be stupid - read the solutions. For example, if you want\nto start a startup and you don't read The Lean Startup, The Mom Test, Paul\nGraham's essays, and watch the Startup School videos, you're playing guitar\nhero, not guitar.\n\n## Goals\n\nGoals are tricky, because the stupidest and least informed version of yourself\nis the one setting them for smarter future versions of you. Still, containers\nand targets are powerful.\n\nI think it's super useful to point yourself at concrete examples. This is the\npoint of role models and heroes. The same is true in startups. A startup pitch\nis a lot about which company you want to be like. For example, Val Town wants to\nbe like Vercel or GitHub or Cloudflare. This is also relevant in selling and\npositioning.\n\nSeek out role models and role model companies, and as you \"meet your heroes\"\nfind increasingly better role models. Nobody is perfect.\n\n## Random startup tips\n\nFocus is your biggest weapon. Jealousy is the guard. Do fewer things better. The\nrewards to scale make this exponentially true.\n\nStay until your cliff date if there's a good chance the company will make good.\n\nDon't try to save money on corporate lawyers. Just use Nick Harley (or someone\nelse strongly recommended) and don't worry about it.\n\nVCs are pretty good at recommending startups. Once you realize you need to\nunderwrite the startup you join as if you were a VC, you can kinda outsource it\nto VC firms. But it's even better if you can talk to the VC who's on the board,\nnot just read press clippings.\n\nVCs and other wise folks have so much wisdom, but also so much anti-wisdom.\nThey're often biased by what worked for them at a specific moment in time, ie\nthey convinced me in 2013-2019 that devtools was not an investable category.\nJoke's on them!\n\nPre-seed investing is mostly about people. Ignore the market and product, except\nas signals about the people. Only invest in people you've known for years and\ntrust implicitly. That way you can underwrite their trajectory, judgment, taste,\nand integrity. If they have those, they'll fix any bad product or market faster\nthan you ever could. As PG says, a startup idea must seem like a bad idea in\norder to succeed, so don't judge ideas, judge people.\n\nA really great path to starting a startup is to get a job somewhere cool and\nlearn all their problems. It's really hard to get jazzed about solving a B2B\nenterprise's problem. It's really easy to get jazzed about your own problems. So\njoin a B2B enterprise and get yourself some valuable problems.\n\nOnce you work at a company, you can often find the role you want by navigating\nthe company. It's easier to walk in the easy door, and then work your way over\nthan to try to get the job you want when you don't know anyone there.\n\nIt's really hard to apply for jobs without knowing what it's like to be on the\nother side, reviewing candidates and hiring. VC is the same. It's awesome to be\non both sides, the \"buy side\" and the \"sell side\". It makes things less mystical\nand makes you more empowered. College admissions teaches the wrong lessons. Life\nis a lot more hackable and personal.\n\nIf you want to work somewhere, make it your mission and target them relentlessly\n– respectfully, without being a stalker. Nobody goes for the love offensive, but\nit's the best. I know a bunch of stories about super successful people walking\nin the side-door to their dream job by simply being persistent, resourceful, and\nshameless.\n\nWorking at a VC firm early in your career is a great way to kickstart things.\nIt's like you're sitting at the top of a hill, getting to look out over the\nwhole industry. I recommend First Round Capital. Thrive also seems hot right\nnow. Probably others are good too.\n\n## Emotional tips\n\nIf you have a bad habit you can't quit, don't shame yourself. Get curious.\nThere's probably a good reason it exists. Escapism. Learning leadership.\nSomething else.\n\nThe Landmark Forum is a three-day motivational course that I recommend with\ncaveats. It was key to starting my first company. Yet it's also a bit cult-y in\nhow they try to get you to sell their course for them. Still, I'd recommend it\nheartily if you find yourself stuck.\n\nIf you're upset about someone else and pointing a finger, you're probably upset\nabout something in yourself that you're not acknowledging yet and need some\nself-soothing. Any time you're upset, it's usually not about them. It's about an\nemotional need in yourself you have to meet. Non-Violent Communication is a\ngreat book. I made [this mobile-friendly worksheet](/nvc) I use every 6 weeks or\nso during emotional conversations.\n\n## Seek out mentors\n\nEmail me with questions. I love giving advice. Most people do.\n\nAsk for money or a job or intros, get advice.\n\nAsk for advice, get money or a job or intros.\n\nI'm steve@val.town.","updated_at":"2026-03-07T15:33:05.071Z","project_name":"stevekrouse_dot_com","project_url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/","username":"stevekrouse","description":"The personal site of Steve Krouse, stevekrouse.com","image_url":null,"matchedLines":[{"lineNumber":101,"lineContent":"Figure out (and continually refine) what your values are so you can spot when","isMatch":false},{"lineNumber":102,"lineContent":"your partners don't share them and end things earlier, saving yourself","isMatch":false},{"lineNumber":103,"lineContent":"heartache. For example, I value reading, writing, honesty, integrity, kindness,","isMatch":true},{"lineNumber":104,"lineContent":"self-awareness, legibility, nerdiness, personal projects.","isMatch":false},{"lineNumber":105,"lineContent":"","isMatch":false},{"lineNumber":114,"lineContent":"","isMatch":false},{"lineNumber":115,"lineContent":"The solutions to a lot of your problems exist, and someone took the time to","isMatch":false},{"lineNumber":116,"lineContent":"write them down. Don't be stupid - read the solutions. For example, if you want","isMatch":true},{"lineNumber":117,"lineContent":"to start a startup and you don't read The Lean Startup, The Mom Test, Paul","isMatch":false},{"lineNumber":118,"lineContent":"Graham's essays, and watch the Startup School videos, you're playing guitar","isMatch":false},{"lineNumber":125,"lineContent":"and targets are powerful.","isMatch":false},{"lineNumber":126,"lineContent":"","isMatch":false},{"lineNumber":127,"lineContent":"I think it's super useful to point yourself at concrete examples. This is the","isMatch":true},{"lineNumber":128,"lineContent":"point of role models and heroes. The same is true in startups. A startup pitch","isMatch":false},{"lineNumber":129,"lineContent":"is a lot about which company you want to be like. For example, Val Town wants to","isMatch":true},{"lineNumber":130,"lineContent":"be like Vercel or GitHub or Cloudflare. This is also relevant in selling and","isMatch":false},{"lineNumber":131,"lineContent":"positioning.","isMatch":false}],"totalMatches":4},{"id":"f77b43da-10d9-11f1-ac03-42dde27851f2","url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/posts/intelligence.md","project_id":"972467e0-e985-11ef-b2c8-e6cdfca9ef9f","name":"intelligence.md","content":"---\ntitle: Intelligence Buying Intelligence\ntags: ai, startups, philosophy\ndate: 2026-02-01\n---\n\n# Intelligence Buying Intelligence\n\n[Nnamdi Iregbulem recently wrote](https://whoisnnamdi.substack.com/p/tokens-arent-fungible)\nabout how users stick with expensive and slow closed models (ie Opus 4.6)\ndespite cheaper OSS alternatives.\n\nWhy aren't we using cheaper models?\n\nSonnet 4.6 is right there, faster, almost 2x cheaper, and about as good as Opus\n4.5, which we were all obsessed with five minutes ago – not to mention OSS\nmodels which are 10x cheaper. It's crazy that I'm always reaching for the\nslowest and most expensive model!\n\nFor me, there's extra cognitive dissonance, because not only do I care (like\neveryone else) about saving money, but I care especially about being in a flow\nstate. Waiting longer for a maybe-smarter response is the opposite of that. Back\nwhen Sonnet 3.5 was the best model, I couldn't wait to get my hands on something\nas smart as it but 10x faster and cheaper. Now we have that. Yet I never reach\nfor it.\n\nNow, I daydream of Opus 4.6 at Taalas's 17k tokens-per-second (Opus 4.6 is ~70\ntps, so 250x slower), yet I'm realizing that by the time we get there – say in a\nyear or two – will we even want to use it vs Opus 6.6?\n\nHere's my best explanation for why we keep reaching for the most expensive and\nslow models, even when cheaper and faster ones are available. There are four\nforces at play that make intelligence a weird thing to buy:\n\n1. The returns to intelligence are **nonlinear**\n2. Intelligence is **hard to measure**.\n3. Intelligence is **competitive**.\n4. Intelligence is a **commodity**. (You can always turn incremental capital into incremental intelligence.)\n\n## 1. The returns to intelligence are nonlinear\n\nThere's a new question tripping up most LLMs right now. It's the new \"how many\nr's in strawberry\":\n\n> The car wash is 50 meters away. Do you walk or drive?\n\nSonnet 4.6 and ChatGPT 5.2 tell you to walk.\n\nOpus 4.6 is the only model I know of that correctly tells you to drive (\"because\nyou'll need the car\"). Once you've seen a model make a mistake like that, it's\nreally hard to look it in the eyes and trust it with anything important.\n\nThis is because we know deep down that returns to intelligence are spiky and\ndiscontinuous. A tiny increase in intelligence can unlock a perspective that\nsimply doesn't exist at the level below it. The losses from insufficient\nintelligence are basically unbounded: someone who is fundamentally confused in\none seemingly small way can end up in the catastrophically wrong place. And the\nconverse is true too. Intelligence builds on itself. One correct insight early\non compounds into a totally different trajectory.\n\nConsider Warren Buffett as the poster child for this. He has a few key insights\nthat are basically invisible to most people, but those insights compound into a\ncompletely different trajectory. The difference between Buffett and the average\ninvestor may be a 0.001% difference in intelligence, but that can lead to\nmassively different outcomes.\n\nIntelligence isn't about exerting more effort. It's about seeing what's right in\nfront of you more clearly: finding the shortcut, the hidden door, the structural\nsimplification that was invisible a moment ago.\n\nIt's also about course-correcting as fast as possible when you realize you're on\nthe wrong path. Feedback loops dominate. Learning compounds.\n\nIntelligence might actually be unique in its nonlinearity. In a\n[David Deutsch](https://en.wikipedia.org/wiki/David_Deutsch) sense, it's the\nonly process that creates new explanatory knowledge, the creation of which is\ninherently unpredictable.\n\n## 2. Intelligence is hard to measure\n\nAnd here's what makes this extra tricky: we don't have good evals.\n\nThis is true for human evals too: SATs only goes up to 1600. If you have a room\nfull of 1600s, you'd have future Nobel laureates sitting next to future\ndeadbeats. And many Nobel laureates and future self-made billionaires and\ngeneration-defining-artists don't even get 1600s! Our tests literally don't\nmeasure the intelligence that matters most.\n\nLLMs keep exceeding our benchmarks, so we keep making harder ones. We're finally\ntaking teaching intelligence and measuring it seriously. I wish we were\nsimilarly ambitious about human intelligence: \"Oh damn, 40% of kids are getting\n1600s these days, gotta make SATs harder.\"\n\nWithout great evals, we default to vibes, reputation, brand loyalty, and price\nsignals. Which, honestly, is rational when you can't measure what matters.\n\nThe best eval I heard about recently is\n[Demis Hassabis's \"Einstein test\"](https://x.com/rohanpaul_ai/status/2025274123560362347):\ntrain an LLM on all human knowledge up to 1911, then see if it can independently\ndiscover general relativity. We need more evals like that.\n\n## 3. Intelligence is competitive\n\nThere's a third reason to always reach for the most expensive intelligence: in\nmany domains, intelligence is a race.\n\nI used to think that once we get models as smart as my CTO, Tom MacWright, we\ncan basically stop there and then work on compressing that intelligence down to\n8b parameters and making it faster and cheaper. Give me a country of Tom's in a\ndatacenter.\n\nBut in some domains, even if a model (or model + harness) is 0.001% smarter,\nthat could be the difference between winning and losing. In a competitive\ndomain, you don't just need to be good enough. You need to be better than\neveryone else.\n\nMy dad likes to tell the story of two hikers who see a bear. One hiker starts\nrunning, and the other says \"you can't outrun a bear!\" The first hiker says:\n\n> \"I don't have to outrun the bear, I just have to outrun you.\"\n\nIf someone could give you a consistent edge in the stock market, even a small\none, that edge could be worth a trillion dollars. But only if nobody else has\nit. The moment everyone has the same insight, it's priced-in and worthless. For\nthe stock market, you don't just need intelligence – you need _more_\nintelligence than everyone else.\n\nI'm not sure to what extent this is true in startups – classic YC advice is to\nignore competition. But in the attention economy, you definitely need to be\nbetter than everyone else. If your content is 0.01% better than the next best\nthing, that could be the difference between going viral and being ignored.\n\n## 4. You can always spend incremental dollars to get incremental intelligence\n\nRight now the most expensive models aren't actually that expensive. A few bucks\nper conversation. But that's changing fast.\n\nWe keep finding ways to spend more money for more intelligence: longer chains of\nthought, parallel reasoning, models that loop and self-correct for hours instead\nof seconds. Each of these multiplies the compute bill – on purpose.\n\nThere's a great example of this called the\n[Ralph Wiggum loop](https://ghuntley.com/ralph/), coined by Geoffrey Huntley.\nThe idea is simple: keep running an AI agent in a loop, feeding failures back\nin, until it succeeds. You're literally turning compute dollars into results\nthrough brute-force persistence. It's not elegant, but it works – and it means\nthat if the stakes are high enough, you can always throw more money at a\nproblem.\n\nWe're not just going to make intelligence cheaper. We're going to make it _more\nexpensive on purpose_ – because we'll keep finding ways to spend more compute on\nharder problems. The ceiling on what you can pay for intelligence is going to go\nway up. And if the returns are nonlinear, people will pay it. Gladly.\n\n## Nobody ever went bankrupt spending too much on good counsel\n\nA very-well-paid consiglieri once told me:\n\n> Nobody ever went bankrupt spending too much on good counsel, but plenty did\n> trying to save on it.\n\nWhy are lawyers so expensive? Why doesn't competition drive down the price?\n\nBecause all four forces are at play.\n\n1. The returns are **nonlinear**: you're paying for the one sentence that changes\n   the contract, the one clause that closes a loophole. \n   \n2. It's **hard to measure** the quality of legal counsel until you end up in\n   court, and by then it's too late. So you rely on vibes, reputation, and price\n   signals.\n\n3. It's directly **competitive** – you need counsel at least as good as the other\n   side's.\n\n4. Legal intelligence is a **commodity** – you can always throw more at the problem:\n   more associates, more partners, outside specialists. There's basically no ceiling.\n\nPut another way: you're not paying for the hours. You're paying for the\npossibility of unlocking a secret.\n\nOnce you have this perspective, you realize that law firms already run a _model\nrouter_ internally. When you email your law firm, they route your request to the\nbest-priced and fastest (ie someone with available capacity) intelligence for\nyour problem. Simple incorporation? Junior associate. Routine contract review?\nMid-level. Bet-the-company litigation? Senior partner.\n\n## The flippening\n\nWhen a new tool is weaker than you, you use it like a full-time employee. You\ngive it bounded tasks. You double-check its work. You keep the real decisions\nfor yourself. That's how we use LLMs today, and it works great.\n\nBut this only makes sense in a world where intelligence is both cheaper and\nworse than yours. And that world is temporary.\n\nNow imagine models + harnesses that are smarter than you. Not just faster, not\njust more encyclopedic, but actually better at reasoning, better at synthesis,\nbetter at seeing structure.\n\nAs discussed above, they've also become more expensive and slower than you. You\nwon't treat them like interns anymore. You have to treat them like partners. You\nhave to give them only the hardest problems, the ones that actually require\nintelligence, and let them do their thing.\n\nI've been thinking about this as **the Lawyer Flippening**.\n\nRight now most people use AI like middle managers. Tools like\n[Devin](https://devin.ai/) spin up sub-agents in parallel.\n[Gastown](https://block.github.io/goose/blog/2026/02/19/gastown-explained-goosetown/)\norchestrates 20-30 Claude Code instances on the same codebase. You assign\ntickets, let them grind, check their work, assign more tickets.\n\nBut the future looks different. The frontier model will be the most expensive\n\"employee\" in the room, even more expensive and slower than you, the human. This\nsuper expensive model will be sitting at the top of the pyramid, with a swarm of\ncheaper agents – and humans – beneath it.\n\nThis is kinda how companies already work. The CEO isn't even the top. The CEO is\njust the highest-paid full-time employee. Above them are all the sources of\nintelligence you can't afford at full-time rates, but that are still crucial:\nconsultants, advisors, board members, investors.\n\nAs the CEO of Val Town, a small startup, I try to push work towards the\nintelligence that can do it most efficiently (and honestly, joyfully, because\nthese are humans, not clankers), either on my team or of our advisors, lawyers,\ninvestors, etc.\n\nStructurally, this will be true as LLM intelligence gets better. We'll all want\npartner-level intelligence, but because it's so expensive, we'll have to route\nwork to it strategically. The model router will be more important than ever.\n\n## The LLM that pays for its own inference: how much should you spend on intelligence?\n\nHere's a thought experiment I can't stop turning over. Imagine giving an LLM a\n$100k bank account. Its only job: earn enough to pay for its own\ninference and generate a return. It's basically a hedge fund of one. And\nsuddenly it's facing the exact optimization problem we all face: how much of\nyour capital do you burn on intelligence vs. keep as returns?\n\nHedge funds charge \"2 and 20\" – 2% management fee, 20% of profits. Should our\nLLM hedge fund do the same? Allocating 2% of its capital under management to its\nown inference? But is that actually optimal, or just convention?\n\nWhat is the optimal ratio of sharpening the axe to chopping wood? How much\nshould you spend on thinking vs. doing?\n\nThe returns to intelligence are so nonlinear that investing in meta-work –\nbetter tools, better systems, better agent harnesses – can feel incredibly\njustified. And sometimes it _is_ justified. But if you take it too seriously,\nyou enter a cognitive black hole where you spend all your time becoming smarter\nfor an application stage that never comes. It's yak-shaving all the way down.\n\nOur self-supporting LLM _can't_\nyak-shave forever, because its inference costs are real and its returns are\nmeasurable. Every hour it spends upgrading itself is an hour it's not earning.\nThat pricing mechanism – having to internalize the cost of your own intelligence\nand improving that intelligence vs the opportunity cost of earning more money\nwith our current intelligence – is exactly what's missing when a human\ndisappears into tool configuration for weeks. Nobody is billing you for your own\nthinking time, so there's no natural brake.\n\nBut sometimes sharpening the axe _is_ the point. Douglas\nEngelbart spent his entire career on this. He called it \"bootstrapping\": using\nyour current tools to build better tools, which you then use to build even\nbetter tools. It's the original intelligence-buying-intelligence loop that\nkicked off the information age. The highest-leverage use of intelligence is\nbuilding tools that make intelligence more effective.\n\nThis is what I've spent my career on. Like Notion, Val Town is a tool for making tools. The whole \"tools for thought\" tradition is\nreally just the tradition of intelligence investing in itself at the societal\nlevel. (Not every company in the world could or should be in the tools for\nthought space, but _some_ meaningful percentage should!)\n\nHere's the fun part: watch what this self-supporting LLM would  independently re-invent.\n\nIt would want more money under management to amortize the fixed costs of its own\nthinking, so it reinvents fundraising so it can manage other people's money too\n(collect more management fees).\n\nIt has to decide what insights to share vs. gate-keep – it reinvents marketing vs proprietary\nresearch.\n\nIt might want to recruit other LLMs or humans for specialized tasks – it\nreinvents the firm.\n\nIntelligence generates capital. Capital buys more intelligence. More\nintelligence generates more capital. The loop compounds.\n\nThis is the big loop that Anthropic and OpenAI and all frontier labs are running\nright now: use capital to build intelligence, use the resulting\ncapital and intellgience to buy more compute, build even more intelligence.\n\nSam Altman has said that intelligence and energy are the two assets that matter,\nand really intelligence is primary because intelligence is what gets you more\nenergy. In this system, capital is just a proxy for energy. The more capital you\nhave, the more energy you can buy, and the more intelligence you can build. The\nintelligence-capital loop is the fundamental economic engine of our time.\n\nI love that with this single constraint – the LLMs gotta eat – you can see how\nall institutions we've already built (hedge funds, law firms, startups, venture\ncapital) are just different shapes this loop naturally takes.","updated_at":"2026-03-07T15:33:03.751Z","project_name":"stevekrouse_dot_com","project_url":"https://www.val.town/x/stevekrouse/stevekrouse_dot_com/code/","username":"stevekrouse","description":"The personal site of Steve Krouse, stevekrouse.com","image_url":null,"matchedLines":[{"lineNumber":140,"lineContent":"of seconds. Each of these multiplies the compute bill – on purpose.","isMatch":false},{"lineNumber":141,"lineContent":"","isMatch":false},{"lineNumber":142,"lineContent":"There's a great example of this called the","isMatch":true},{"lineNumber":143,"lineContent":"[Ralph Wiggum loop](https://ghuntley.com/ralph/), coined by Geoffrey Huntley.","isMatch":false},{"lineNumber":144,"lineContent":"The idea is simple: keep running an AI agent in a loop, feeding failures back","isMatch":false}],"totalMatches":1}],"projectResults":[{"id":"8470604a-1a26-11f1-a495-42dde27851f2","url":"https://www.val.town/x/sistrall/tanstackReactHonoExample/code/","name":"tanstackReactHonoExample","username":"sistrall","description":null,"image_url":null,"forked_branch_id":"d5b52a4e-628e-11f0-a7b6-0224a6c84d84","updated_at":"2026-03-07T13:06:55.778Z","user_id":"75e35405-1466-4543-bff5-1b566e657400","matchCount":1},{"id":"6b133688-1993-11f1-a5f0-42dde27851f2","url":"https://www.val.town/x/newenquiry/reactHonoExample/code/","name":"reactHonoExample","username":"newenquiry","description":"Example with client-side React & Hono server","image_url":null,"forked_branch_id":"41ef5540-f2f5-11ef-891c-569c3dd06744","updated_at":"2026-03-06T19:34:37.034Z","user_id":"019cb856-0e21-7146-ba5b-0fad2420e157","matchCount":1},{"id":"68dc4a20-187c-11f1-bb27-42dde27851f2","url":"https://www.val.town/x/clouds/threejs-starter/code/","name":"threejs-starter","username":"clouds","description":"Minimal Three.js starter example","image_url":"https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/bd6ac0ed-4810-4df6-10f3-55192a701c00/square512","forked_branch_id":"8b6efcaa-1705-11f0-afb8-569c3dd06744","updated_at":"2026-03-05T10:16:43.897Z","user_id":"019cbd66-6529-727c-a65b-c6c70b564b27","matchCount":1},{"id":"008209de-1533-11f1-aa5e-42dde27851f2","url":"https://www.val.town/x/n1ck9/BabList/code/","name":"BabList","username":"n1ck9","description":"Example with client-side React & Hono server","image_url":null,"forked_branch_id":"41ef5540-f2f5-11ef-891c-569c3dd06744","updated_at":"2026-03-03T10:48:32.519Z","user_id":"019ca7f2-6e63-76d8-9993-9700c5c563ce","matchCount":1},{"id":"dfd7fa50-0ff0-11f1-8777-42dde27851f2","url":"https://www.val.town/x/stevekrouse/react-router-hello-world/code/","name":"react-router-hello-world","username":"stevekrouse","description":"Minimal hello world example using @valtown/react-router","image_url":null,"forked_branch_id":null,"updated_at":"2026-02-22T13:21:21.253Z","user_id":"a0bf3b31-15a5-4d5c-880e-4b1e22c9bc18","matchCount":1}],"userResults":[],"docResults":[],"totalFileResults":1262,"totalProjectResults":12,"totalUserResults":0,"totalDocResults":0,"page":1,"pageSize":10,"totalPages":127,"resultType":"files","executionTimeMs":608}