Tinqs Studio blog: 6 posts, 5 skills, landing page
Engineering blog and AI agent skills from Tinqs Studio — an agent harness for game development. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
Creative Commons Attribution 4.0 International (CC BY 4.0)
|
||||||
|
|
||||||
|
Copyright (c) 2026 Tinqs Ltd
|
||||||
|
|
||||||
|
You are free to:
|
||||||
|
- Share: copy and redistribute the material in any medium or format
|
||||||
|
- Adapt: remix, transform, and build upon the material for any purpose, even commercially
|
||||||
|
|
||||||
|
Under the following terms:
|
||||||
|
- Attribution: You must give appropriate credit, provide a link to the license,
|
||||||
|
and indicate if changes were made.
|
||||||
|
|
||||||
|
Full license text: https://creativecommons.org/licenses/by/4.0/legalcode
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Tinqs Studio Blog
|
||||||
|
|
||||||
|
Engineering blog from [Tinqs Studio](https://tinqs.com) --- a game development platform built on a Gitea fork with 3D asset preview, LFS-first workflows, AI agent tools, and creative pipelines for game teams.
|
||||||
|
|
||||||
|
We're building Tinqs Studio while using it to make our own game --- a survival colony sim in Godot 4. These posts cover what we've learned along the way.
|
||||||
|
|
||||||
|
## Posts
|
||||||
|
|
||||||
|
- [How a Small Game Studio Runs on AI Agents](posts/agentic-workflow.md) (2026-03-06)
|
||||||
|
- [One Binary to Rule Them All: Building a Studio CLI](posts/studio-cli.md) (2026-05-18)
|
||||||
|
- [Why We Forked Gitea and Built Tinqs Studio](posts/forking-gitea.md) (2026-05-20)
|
||||||
|
- [Streaming a 12km Archipelago in Godot 4](posts/godot-optimisation.md) (2026-05-22)
|
||||||
|
- [AI Art at Scale: Using fal.ai Flux for Game Asset Generation](posts/fal-image-generation.md) (2026-05-25)
|
||||||
|
- [Tinqs Studio Is an Agent Harness for Game Dev](posts/agent-harness.md) (2026-05-25)
|
||||||
|
|
||||||
|
## Skills
|
||||||
|
|
||||||
|
Reusable AI agent playbooks. Each skill is a markdown file that teaches an AI agent (Cursor, Claude Code, etc.) a specific workflow. Drop them into your `.cursor/skills/` directory.
|
||||||
|
|
||||||
|
- [Image Generation with fal.ai](skills/image-generation.md) --- Generate game art using Flux models with structured prompts
|
||||||
|
- [Concept Art Pipeline](skills/concept-art-pipeline.md) --- End-to-end 2D concept art to 3D model workflow
|
||||||
|
- [Sora 2 Video Generation](skills/sora2-video.md) --- Generate trailer clips and game footage with OpenAI Sora 2
|
||||||
|
- [3D Model Generation with Tripo](skills/tripo-browser-workflow.md) --- Text-to-3D and image-to-3D via Tripo Studio
|
||||||
|
- [Blog Authoring](skills/blog.md) --- Write and publish markdown blog posts
|
||||||
|
|
||||||
|
## What are skills?
|
||||||
|
|
||||||
|
Skills are structured markdown files that give AI coding assistants step-by-step procedures for complex workflows. Instead of explaining the same process every session, you write it once and the agent follows it. Think of them as runbooks for AI agents.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Content is [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). Use it, adapt it, credit us.
|
||||||
+401
@@ -0,0 +1,401 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Tinqs Studio Blog — Agent Harness for Game Dev</title>
|
||||||
|
<meta name="description" content="Engineering blog and AI agent skills from Tinqs Studio — a game development platform with git hosting, 3D preview, and creative AI pipelines.">
|
||||||
|
<meta property="og:title" content="Tinqs Studio Blog">
|
||||||
|
<meta property="og:description" content="Posts and AI agent skills from the team building Tinqs Studio — an agent harness for game dev.">
|
||||||
|
<meta property="og:image" content="https://www.tinqs.com/img/og-cover.jpg">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<style>
|
||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--bg: #0e0e10;
|
||||||
|
--surface: #18181b;
|
||||||
|
--surface-hover: #1e1e22;
|
||||||
|
--border: #2a2a2e;
|
||||||
|
--text: #e4e4e7;
|
||||||
|
--text-muted: #a1a1aa;
|
||||||
|
--accent: #f59e0b;
|
||||||
|
--accent-dim: #b45309;
|
||||||
|
--link: #60a5fa;
|
||||||
|
--tag-bg: #27272a;
|
||||||
|
--tag-text: #d4d4d8;
|
||||||
|
--skill-accent: #34d399;
|
||||||
|
--font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
|
||||||
|
--font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
line-height: 1.6;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
a { color: var(--link); text-decoration: none; transition: color 0.15s; }
|
||||||
|
a:hover { color: var(--accent); }
|
||||||
|
|
||||||
|
/* --- Header --- */
|
||||||
|
.header {
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
padding: 2rem 0;
|
||||||
|
}
|
||||||
|
.header-inner {
|
||||||
|
max-width: 860px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
||||||
|
.logo {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent);
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
.logo span { color: var(--text-muted); font-weight: 400; }
|
||||||
|
.nav-links {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
gap: 1.5rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
.nav-links a { color: var(--text-muted); }
|
||||||
|
.nav-links a:hover { color: var(--text); }
|
||||||
|
|
||||||
|
/* --- Hero --- */
|
||||||
|
.hero {
|
||||||
|
max-width: 860px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 3.5rem 1.5rem 2.5rem;
|
||||||
|
}
|
||||||
|
.hero h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.hero h1 em {
|
||||||
|
font-style: normal;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.hero p {
|
||||||
|
font-size: 1.05rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
max-width: 640px;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
.hero p + p { margin-top: 0.75rem; }
|
||||||
|
|
||||||
|
/* --- Harness diagram --- */
|
||||||
|
.harness {
|
||||||
|
max-width: 860px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1.5rem 2.5rem;
|
||||||
|
}
|
||||||
|
.harness-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
.harness-item {
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1rem 1.1rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.harness-item .icon {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.harness-item .label {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--accent);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
}
|
||||||
|
.harness-item .desc {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Sections --- */
|
||||||
|
.section {
|
||||||
|
max-width: 860px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1.5rem 3rem;
|
||||||
|
}
|
||||||
|
.section-title {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Post cards --- */
|
||||||
|
.post-list { display: flex; flex-direction: column; gap: 0.5rem; }
|
||||||
|
.post-card {
|
||||||
|
display: block;
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1.1rem 1.3rem;
|
||||||
|
transition: background 0.15s, border-color 0.15s;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.post-card:hover {
|
||||||
|
background: var(--surface-hover);
|
||||||
|
border-color: var(--accent-dim);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.post-card .post-title {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
.post-card .post-excerpt {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.post-card .post-date {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Skill cards --- */
|
||||||
|
.skill-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
.skill-card {
|
||||||
|
display: block;
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1.1rem 1.3rem;
|
||||||
|
transition: background 0.15s, border-color 0.15s;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.skill-card:hover {
|
||||||
|
background: var(--surface-hover);
|
||||||
|
border-color: #065f46;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.skill-card .skill-name {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--skill-accent);
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
.skill-card .skill-desc {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- What are skills --- */
|
||||||
|
.callout {
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-left: 3px solid var(--accent);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1.25rem 1.5rem;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
.callout h3 {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
}
|
||||||
|
.callout p {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.callout code {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background: var(--tag-bg);
|
||||||
|
padding: 0.15em 0.4em;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Footer --- */
|
||||||
|
.footer {
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
padding: 2rem 0;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
.footer-inner {
|
||||||
|
max-width: 860px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.75rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
.footer a { color: var(--text-muted); }
|
||||||
|
.footer a:hover { color: var(--text); }
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.hero h1 { font-size: 1.5rem; }
|
||||||
|
.harness-grid { grid-template-columns: repeat(2, 1fr); }
|
||||||
|
.skill-grid { grid-template-columns: 1fr; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="header">
|
||||||
|
<div class="header-inner">
|
||||||
|
<div class="logo">TINQS STUDIO <span>/ blog</span></div>
|
||||||
|
<nav class="nav-links">
|
||||||
|
<a href="https://tinqs.com">Platform</a>
|
||||||
|
<a href="#posts">Posts</a>
|
||||||
|
<a href="#skills">Skills</a>
|
||||||
|
<a href="https://tinqs.com/tinqs/blog">Source</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="hero">
|
||||||
|
<h1>An <em>agent harness</em> for game development</h1>
|
||||||
|
<p>Tinqs Studio is a game development platform built on a Gitea fork. It gives AI agents identity, memory, skills, and tools — so a small team can build games at scale.</p>
|
||||||
|
<p>This repo contains our engineering blog and the AI agent skill files that power our creative pipeline. Everything is open, CC BY 4.0.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="harness">
|
||||||
|
<div class="harness-grid">
|
||||||
|
<div class="harness-item">
|
||||||
|
<span class="icon">≡</span>
|
||||||
|
<div class="label">Identity</div>
|
||||||
|
<div class="desc">Soul files give agents persistent values and context</div>
|
||||||
|
</div>
|
||||||
|
<div class="harness-item">
|
||||||
|
<span class="icon">◗</span>
|
||||||
|
<div class="label">Memory</div>
|
||||||
|
<div class="desc">Cross-session knowledge in markdown, versioned in git</div>
|
||||||
|
</div>
|
||||||
|
<div class="harness-item">
|
||||||
|
<span class="icon">⚙</span>
|
||||||
|
<div class="label">Skills</div>
|
||||||
|
<div class="desc">Teachable playbooks for art, video, 3D, and more</div>
|
||||||
|
</div>
|
||||||
|
<div class="harness-item">
|
||||||
|
<span class="icon">〉</span>
|
||||||
|
<div class="label">CLI Tools</div>
|
||||||
|
<div class="desc">Screenshots, vision, health checks, identity loading</div>
|
||||||
|
</div>
|
||||||
|
<div class="harness-item">
|
||||||
|
<span class="icon">◫</span>
|
||||||
|
<div class="label">Git + 3D</div>
|
||||||
|
<div class="desc">LFS-first hosting with in-browser 3D asset preview</div>
|
||||||
|
</div>
|
||||||
|
<div class="harness-item">
|
||||||
|
<span class="icon">◆</span>
|
||||||
|
<div class="label">Guardrails</div>
|
||||||
|
<div class="desc">Human-in-the-loop approval for merges and deploys</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section" id="posts">
|
||||||
|
<div class="section-title">Posts</div>
|
||||||
|
<div class="post-list">
|
||||||
|
<a class="post-card" href="posts/agent-harness.md">
|
||||||
|
<div class="post-date">2026-05-25</div>
|
||||||
|
<div class="post-title">Tinqs Studio Is an Agent Harness for Game Dev</div>
|
||||||
|
<div class="post-excerpt">An agent harness gives AI agents identity, memory, tools, and guardrails. Tinqs Studio is one built for game development.</div>
|
||||||
|
</a>
|
||||||
|
<a class="post-card" href="posts/fal-image-generation.md">
|
||||||
|
<div class="post-date">2026-05-25</div>
|
||||||
|
<div class="post-title">AI Art at Scale: Using fal.ai Flux for Game Asset Generation</div>
|
||||||
|
<div class="post-excerpt">We generate concept art, trailer frames, and UI icons with fal.ai Flux at $0.01 per image. The 4-layer prompt pattern that makes it work.</div>
|
||||||
|
</a>
|
||||||
|
<a class="post-card" href="posts/godot-optimisation.md">
|
||||||
|
<div class="post-date">2026-05-22</div>
|
||||||
|
<div class="post-title">Streaming a 12km Archipelago in Godot 4</div>
|
||||||
|
<div class="post-excerpt">Four streaming layers, async resource loading, memory-safe caches, and zero leaks. A 12km open world in Godot 4 with C#.</div>
|
||||||
|
</a>
|
||||||
|
<a class="post-card" href="posts/forking-gitea.md">
|
||||||
|
<div class="post-date">2026-05-20</div>
|
||||||
|
<div class="post-title">Why We Forked Gitea and Built Tinqs Studio</div>
|
||||||
|
<div class="post-excerpt">GitHub doesn't understand game dev. We forked Gitea for 3D asset preview, LFS-first workflows, and project management for game teams.</div>
|
||||||
|
</a>
|
||||||
|
<a class="post-card" href="posts/studio-cli.md">
|
||||||
|
<div class="post-date">2026-05-18</div>
|
||||||
|
<div class="post-title">One Binary to Rule Them All: Building a Studio CLI</div>
|
||||||
|
<div class="post-excerpt">A single Go binary that gives AI agents context about who you are, what machine you're on, and what services are reachable.</div>
|
||||||
|
</a>
|
||||||
|
<a class="post-card" href="posts/agentic-workflow.md">
|
||||||
|
<div class="post-date">2026-03-06</div>
|
||||||
|
<div class="post-title">How a Small Game Studio Runs on AI Agents</div>
|
||||||
|
<div class="post-excerpt">Soul files, skill playbooks, and markdown as the universal API. How a 4-person indie studio operates at 10x scale.</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section" id="skills">
|
||||||
|
<div class="section-title">AI Agent Skills</div>
|
||||||
|
<div class="skill-grid">
|
||||||
|
<a class="skill-card" href="skills/image-generation.md">
|
||||||
|
<div class="skill-name">image-generation</div>
|
||||||
|
<div class="skill-desc">Generate game art with fal.ai Flux models. 4-layer prompt pattern, model comparison, API examples.</div>
|
||||||
|
</a>
|
||||||
|
<a class="skill-card" href="skills/concept-art-pipeline.md">
|
||||||
|
<div class="skill-name">concept-art-pipeline</div>
|
||||||
|
<div class="skill-desc">End-to-end workflow from design brief through 2D concept art to 3D model export.</div>
|
||||||
|
</a>
|
||||||
|
<a class="skill-card" href="skills/sora2-video.md">
|
||||||
|
<div class="skill-name">sora2-video</div>
|
||||||
|
<div class="skill-desc">Generate trailer clips and cinematics with OpenAI Sora 2. API workflow and cost management.</div>
|
||||||
|
</a>
|
||||||
|
<a class="skill-card" href="skills/tripo-browser-workflow.md">
|
||||||
|
<div class="skill-name">tripo-3d</div>
|
||||||
|
<div class="skill-desc">Text-to-3D and image-to-3D model generation via Tripo Studio. Export, retopo, rigging tips.</div>
|
||||||
|
</a>
|
||||||
|
<a class="skill-card" href="skills/blog.md">
|
||||||
|
<div class="skill-name">blog</div>
|
||||||
|
<div class="skill-desc">Write markdown blog posts with YAML frontmatter. Format, structure, and SEO checklist.</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="callout">
|
||||||
|
<h3>What are skills?</h3>
|
||||||
|
<p>Skills are markdown playbooks that teach AI agents specific workflows. Drop them into your <code>.cursor/skills/</code> directory and your agent can follow them. Think of them as runbooks where the reader is an LLM, not a human.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="footer-inner">
|
||||||
|
<span>© 2026 Tinqs Ltd · <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a></span>
|
||||||
|
<span><a href="https://tinqs.com">tinqs.com</a></span>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
After
|
@@ -0,0 +1,151 @@
|
|||||||
|
---
|
||||||
|
title: "Tinqs Studio Is an Agent Harness for Game Dev"
|
||||||
|
slug: agent-harness
|
||||||
|
date: "2026-05-25"
|
||||||
|
description: "An agent harness gives AI agents identity, memory, tools, and guardrails. Tinqs Studio is one built specifically for game development --- git, 3D preview, image generation, and a CLI that makes every session a warm start."
|
||||||
|
og_description: "Tinqs Studio is an agent harness for game dev --- identity, skills, vision, git, and creative tools in one platform."
|
||||||
|
og_image: "https://www.tinqs.com/img/og-cover.jpg"
|
||||||
|
excerpt: "An agent harness gives AI agents identity, memory, tools, and guardrails. Tinqs Studio is one built for game development."
|
||||||
|
author: "Ozan Bozkurt"
|
||||||
|
author_initials: "OB"
|
||||||
|
author_role: "CTO & Developer, Tinqs"
|
||||||
|
---
|
||||||
|
An agent harness is the layer between a raw AI model and a useful team member. It gives the agent identity, memory, tools, and guardrails. Tinqs Studio is an agent harness built specifically for game development.
|
||||||
|
|
||||||
|
## What Is an Agent Harness?
|
||||||
|
|
||||||
|
A raw AI model --- Claude, GPT, Gemini --- is powerful but stateless. It doesn't know who you are, what project you're working on, what tools are available, or what happened yesterday. Every session is a cold start. Every conversation begins with "let me explain the project..."
|
||||||
|
|
||||||
|
An agent harness solves this. It wraps around the model and provides:
|
||||||
|
|
||||||
|
- **Identity** --- who the agent is, what it values, how it should behave
|
||||||
|
- **Memory** --- what happened in previous sessions, what was decided, what failed
|
||||||
|
- **Tools** --- what the agent can actually do beyond generating text
|
||||||
|
- **Context** --- what project this is, who's asking, what infrastructure exists
|
||||||
|
- **Guardrails** --- what the agent must never do, what requires human approval
|
||||||
|
|
||||||
|
Without a harness, you have a chatbot. With one, you have a team member.
|
||||||
|
|
||||||
|
## Why Game Dev Needs Its Own Harness
|
||||||
|
|
||||||
|
Generic agent harnesses exist --- LangChain, CrewAI, AutoGen. They're built for web apps, data pipelines, and customer support. Game development has different problems:
|
||||||
|
|
||||||
|
**Assets are binary.** A web developer's PR is a text diff. A game developer's PR is a 150MB GLB file. Generic harnesses don't know how to preview 3D models, manage LFS bandwidth, or review binary assets.
|
||||||
|
|
||||||
|
**The pipeline is visual.** Game dev goes from concept art to 3D model to rigged character to in-engine asset. Each step uses different tools --- image generators, 3D modellers, auto-riggers, game engines. An agent harness for game dev needs to orchestrate this entire chain.
|
||||||
|
|
||||||
|
**Scale is physical.** A web app's complexity is in business logic. A game's complexity is in geometry --- 12km worlds, 155 vegetation prototypes, 576 terrain regions, 2000 crowd instances. The agent needs to understand spatial systems, GPU memory, and frame budgets.
|
||||||
|
|
||||||
|
**The team is small and cross-functional.** A 4-person game studio has no dedicated DevOps, no dedicated artist, no dedicated PM. The harness needs to fill all those gaps, not just one.
|
||||||
|
|
||||||
|
## How Tinqs Studio Works as a Harness
|
||||||
|
|
||||||
|
Tinqs Studio is a platform built on a [Gitea fork](forking-gitea) with game-specific features layered on top. But the git platform is just the foundation. The harness is everything around it.
|
||||||
|
|
||||||
|
### Identity: Soul Files
|
||||||
|
|
||||||
|
Every agent session starts by loading a soul file --- a markdown document that defines the agent's persistent identity. Not just "you are a helpful assistant" but specific values, knowledge scope, and behavioural rules.
|
||||||
|
|
||||||
|
The soul file means the agent behaves consistently whether it's triaging bugs at 9am or generating concept art at midnight. It knows what repos exist, who the team members are, what the game is about, and what decisions have been made. Identity isn't cosmetic --- it's the difference between an agent that asks "what project is this?" and one that says "I see the vegetation grid was updated yesterday, want me to check the cache eviction?"
|
||||||
|
|
||||||
|
### Memory: Markdown Files in Git
|
||||||
|
|
||||||
|
Agent memory is plain markdown files in a git repository. No vector databases, no proprietary stores. The agent reads its memory on session start, updates it during work, and commits changes back.
|
||||||
|
|
||||||
|
This is deliberately low-tech. Markdown in git gives you version history, branching, merge conflict resolution, and human readability for free. When memory goes wrong --- and it will --- you can `git log` to see what changed and `git revert` to fix it.
|
||||||
|
|
||||||
|
### Tools: The CLI
|
||||||
|
|
||||||
|
A [single Go binary](studio-cli) gives every agent access to:
|
||||||
|
|
||||||
|
- **Identity loading** --- full project context in 100ms
|
||||||
|
- **Screenshots** --- capture any window from outside the process
|
||||||
|
- **Cloud vision** --- send screenshots to a vision model, get structured descriptions
|
||||||
|
- **Health checks** --- verify services, repos, and tools are working
|
||||||
|
- **Service status** --- which URLs are live, what's reachable
|
||||||
|
|
||||||
|
The CLI is the agent's hands and eyes. Without it, the agent can only read and write text. With it, the agent can see the game running, photograph bugs, and verify infrastructure.
|
||||||
|
|
||||||
|
### Skills: Teachable Workflows
|
||||||
|
|
||||||
|
Skills are markdown playbooks that teach agents specific procedures. Instead of hoping the model figures out how to generate concept art or create a 3D model, you write the steps once:
|
||||||
|
|
||||||
|
- [Image Generation](../skills/image-generation.md) --- generate game art with fal.ai Flux using a [4-layer prompt pattern](fal-image-generation)
|
||||||
|
- [Concept Art Pipeline](../skills/concept-art-pipeline.md) --- from design brief through 2D art to 3D model export
|
||||||
|
- [3D Model Generation](../skills/tripo-browser-workflow.md) --- Tripo Studio text-to-3D and image-to-3D
|
||||||
|
- [Video Generation](../skills/sora2-video.md) --- trailer clips with OpenAI Sora 2
|
||||||
|
|
||||||
|
Skills compound. Every playbook you write makes the agent more capable. After six months, our agents handle art generation, competitive research, video production, project management, and code review --- all from markdown files.
|
||||||
|
|
||||||
|
### Git Platform: 3D Preview and LFS
|
||||||
|
|
||||||
|
The [Gitea fork](forking-gitea) underneath handles the game-specific git problems:
|
||||||
|
|
||||||
|
- **3D asset preview** --- rotate GLB/FBX/STL files in the browser during code review
|
||||||
|
- **LFS-first workflows** --- auto-tracking for game file extensions, storage dashboards
|
||||||
|
- **OAuth2 SSO** --- one login for git, tools, and the game
|
||||||
|
- **22 format support** --- GLB, FBX, OBJ, STL, 3DS, PLY, and more via O3DV
|
||||||
|
|
||||||
|
### Guardrails: Human-in-the-Loop
|
||||||
|
|
||||||
|
The harness defines what agents can and cannot do:
|
||||||
|
|
||||||
|
- Agents can file issues, draft announcements, generate assets, write code
|
||||||
|
- Agents **cannot** merge code, deploy builds, push to public repos, or post to external channels without human approval
|
||||||
|
- The [public blog repo](https://tinqs.com/tinqs/blog) requires human-approved merge requests --- agents can propose changes but a person must review
|
||||||
|
|
||||||
|
This isn't a limitation --- it's a feature. The agent handles volume; the human handles judgement.
|
||||||
|
|
||||||
|
## The Cold Start Problem
|
||||||
|
|
||||||
|
The biggest problem with AI agents in production isn't capability --- it's context. Every new session is blank. The agent doesn't know what happened yesterday, what's in progress, or what tools are available.
|
||||||
|
|
||||||
|
Most teams solve this with long system prompts. That works until your context is 200 markdown files, 15 skills, and 3 years of project history. You can't paste all of that into a system prompt.
|
||||||
|
|
||||||
|
The harness solves this with **staged loading**:
|
||||||
|
|
||||||
|
1. **CLI identity call** (100ms) --- loads soul file, company context, machine info, service status
|
||||||
|
2. **Memory file** (instant) --- loads cross-session context
|
||||||
|
3. **Skills** (on demand) --- loaded only when the task matches a skill name
|
||||||
|
4. **Repo context** (on demand) --- read files as needed, not all upfront
|
||||||
|
|
||||||
|
The agent goes from cold to fully contextual in under a second. No "let me explain..." No re-reading the same onboarding doc. Just start working.
|
||||||
|
|
||||||
|
## What Makes This Different from LangChain
|
||||||
|
|
||||||
|
LangChain, CrewAI, and similar frameworks are **code-first**. You define agents in Python, chain them with function calls, and deploy them as services. They're powerful for building AI products.
|
||||||
|
|
||||||
|
Tinqs Studio is **file-first**. Agents are defined in markdown. Skills are markdown. Memory is markdown. Identity is markdown. Everything is in git, readable by humans, editable without code changes, and version-controlled.
|
||||||
|
|
||||||
|
This matters for game teams because:
|
||||||
|
|
||||||
|
- **Non-engineers can contribute.** The designer writes a skill for concept art. The PM writes a skill for sprint planning. No Python required.
|
||||||
|
- **Everything is auditable.** `git log` shows who changed what, when, and why. Memory changes are commits. Skill updates are diffs.
|
||||||
|
- **It works with any AI tool.** The same soul files and skills work in Cursor, Claude Code, or any tool that reads markdown. You're not locked into one framework.
|
||||||
|
|
||||||
|
## The Stack
|
||||||
|
|
||||||
|
| Layer | What | How |
|
||||||
|
|-------|------|-----|
|
||||||
|
| **Identity** | Soul files, company context | Markdown in git, loaded via CLI |
|
||||||
|
| **Memory** | Cross-session context | Markdown in git, updated by agents |
|
||||||
|
| **Skills** | Teachable workflows | Markdown playbooks, loaded on demand |
|
||||||
|
| **Tools** | CLI, screenshots, vision | Go binary, one install per machine |
|
||||||
|
| **Git** | 3D preview, LFS, SSO | Gitea fork with game-specific features |
|
||||||
|
| **Creative** | Image gen, 3D models, video | fal.ai, Tripo, Sora 2 via skills |
|
||||||
|
| **Guardrails** | Human approval gates | Branch protection, MR requirements |
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
If you want to build your own agent harness for game dev:
|
||||||
|
|
||||||
|
1. **Start with a soul file.** Write 50 words about your project's identity, values, and scope. Put it in your repo root as `SOUL.md`.
|
||||||
|
2. **Write one skill.** Pick the workflow you repeat most --- concept art generation, bug triage, build verification --- and write the steps as markdown.
|
||||||
|
3. **Build a CLI identity command.** Even a shell script that prints "project name, repos, services" gives your agent a warm start.
|
||||||
|
4. **Put everything in git.** Not a database, not a SaaS tool. Git. You already have it.
|
||||||
|
|
||||||
|
The rest --- 3D preview, LFS management, OAuth SSO, creative pipelines --- you can add as you need it. Or use [Tinqs Studio](https://tinqs.com), where we've already built it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
An agent harness isn't a product category yet. But it should be. The gap between "I have an AI model" and "I have an AI team member" is infrastructure --- identity, memory, tools, context, guardrails. For game development, that infrastructure needs to understand binary assets, visual pipelines, and spatial systems. That's what we're building.
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
title: "How a Small Game Studio Runs on AI Agents"
|
||||||
|
slug: agentic-workflow
|
||||||
|
date: "2026-03-06"
|
||||||
|
description: "Soul files, skill playbooks, and markdown as the universal API. How we built an agentic workflow that lets a 4-person indie studio operate at 10x scale."
|
||||||
|
og_description: "Soul files, skill playbooks, and markdown as the universal API for AI agents in game dev."
|
||||||
|
og_image: "https://www.tinqs.com/blog/img/agentic-workflow-architecture.png"
|
||||||
|
excerpt: "Soul files, skill playbooks, and markdown as the universal API. How we built an agentic workflow that lets a 4-person indie studio operate at 10x scale."
|
||||||
|
author: "Ozan Bozkurt"
|
||||||
|
author_initials: "OB"
|
||||||
|
author_role: "CTO & Developer, Tinqs"
|
||||||
|
---
|
||||||
|
We gave our AI agents persistent identities, skill playbooks, and access to our entire knowledge base. This is how a 4-person game studio built an agentic workflow that punches above its weight.
|
||||||
|
|
||||||
|
## The Problem Every Small Studio Knows
|
||||||
|
|
||||||
|
When you're four people building a game, there's no room for a dedicated DevOps person, a full-time PM tool chain, or someone whose job it is to "keep things organised." Everyone wears five hats. Documentation drifts. Issues pile up. The left hand doesn't know what the right hand shipped.
|
||||||
|
|
||||||
|
We tried the usual tools --- Notion, Trello, shared Google Docs. They all had the same problem: they're passive. They sit there and wait for a human to update them. In a team of four where the lead developer is also the CTO, that human never has time.
|
||||||
|
|
||||||
|
So we built something different. We gave AI agents persistent identities, connected them to our entire knowledge base, and let them become working members of the team.
|
||||||
|
|
||||||
|
## The Architecture: Agents with Identity
|
||||||
|
|
||||||
|
Our primary AI agent runs inside the IDE and has access to the full documentation repository --- the game design document, backlog, meeting notes, company operations, everything. It's not a chatbot. It's a persistent team member with a **soul file** that defines its values and operating principles, and a **memory file** that persists context across sessions.
|
||||||
|
|
||||||
|
The key insight: **all knowledge lives in markdown files in one repo**. No databases, no SaaS dashboards, no proprietary formats. Plain text, version-controlled, readable by humans and agents alike. When anyone on the team opens the docs repo, the agent wakes up with full context of who they are, what machine they're on, and what's been happening.
|
||||||
|
|
||||||
|
### What the agent actually does
|
||||||
|
|
||||||
|
- Triages and grooms the issue backlog
|
||||||
|
- Keeps documentation in sync with the game state
|
||||||
|
- Processes bug reports from testers and creates structured issues
|
||||||
|
- Drafts team announcements, reviews PRs, manages cross-repo coordination
|
||||||
|
- Generates concept art, trailer frames, and UI assets using integrated API skills
|
||||||
|
- Conducts competitive research --- analysing Steam pages, player reviews, pricing strategies
|
||||||
|
|
||||||
|
The team talks to the agent through voice. The IDE's built-in microphone transcribes and auto-translates (multilingual team). The agent is trained to interpret messy voice-to-text artifacts and act on intent, not grammar.
|
||||||
|
|
||||||
|
## Background Automation
|
||||||
|
|
||||||
|
The interactive agent only runs when someone opens the IDE. But a studio doesn't sleep --- bugs get reported at midnight, issues go stale, and the team chat fills up while everyone's away.
|
||||||
|
|
||||||
|
A background daemon runs 24/7, ticking every 15 minutes. It uses a three-tier model strategy --- cheap models for routine checks, medium for analysis, and premium only when it needs deep reasoning. The whole thing costs about $15/day.
|
||||||
|
|
||||||
|
### What it handles
|
||||||
|
|
||||||
|
- **Chat monitoring** --- polls team chat, responds to commands, acknowledges messages
|
||||||
|
- **Bug intake** --- when a tester reports a bug in chat, creates a structured issue automatically
|
||||||
|
- **Stale issue detection** --- flags issues that haven't been touched, nudges the team
|
||||||
|
- **Daily summaries** --- posts a morning digest of what happened overnight
|
||||||
|
- **Self-learning** --- creates its own skill files when it discovers better approaches
|
||||||
|
|
||||||
|
The two agents coordinate through the docs repo itself. One writes, the other reads. No API calls between them, no message queue. Just git.
|
||||||
|
|
||||||
|
## The Skill System
|
||||||
|
|
||||||
|
Agents don't just have instructions --- they have **skills**. Each skill is a markdown file that teaches the agent a specific workflow: how to generate concept art through a pipeline, how to use image generation APIs, how to conduct competitive research, how to create 3D models from concept art.
|
||||||
|
|
||||||
|
When someone asks the agent to do something that matches a skill, it reads the skill file and follows the procedure. This means you can teach the agent new capabilities without changing any code --- just write a new markdown file.
|
||||||
|
|
||||||
|
We've open-sourced several of our skills in this repo:
|
||||||
|
|
||||||
|
- [Image Generation with fal.ai](../skills/image-generation.md)
|
||||||
|
- [Concept Art Pipeline](../skills/concept-art-pipeline.md)
|
||||||
|
- [3D Model Generation with Tripo](../skills/tripo-browser-workflow.md)
|
||||||
|
- [Video Generation with Sora 2](../skills/sora2-video.md)
|
||||||
|
|
||||||
|
## Soul Files: Why Identity Matters
|
||||||
|
|
||||||
|
Giving the agent a persistent identity isn't theatre. It creates consistency across sessions. The soul file defines:
|
||||||
|
|
||||||
|
- **Values** --- what the agent prioritises (e.g., "never break the build," "always verify before acting")
|
||||||
|
- **Knowledge scope** --- what repos, services, and team members exist
|
||||||
|
- **Behavioural rules** --- how to handle ambiguity, when to ask vs act, what requires human approval
|
||||||
|
|
||||||
|
The agent remembers what it learned, adapts to who's asking, and maintains the same principles whether it's triaging bugs or drafting a Steam page description. The soul file is the agent's constitution.
|
||||||
|
|
||||||
|
## What We've Learned
|
||||||
|
|
||||||
|
**Plain text is the universal API.** Every tool, every agent, every human can read a markdown file. We store everything --- design documents, meeting notes, agent memory, team contacts --- as .md files in one repository. This sounds almost too simple, but it eliminates an entire class of integration problems.
|
||||||
|
|
||||||
|
**Cheap models for routine, expensive models for thinking.** Most of what an autonomous agent does is pattern matching and text formatting --- you don't need the most expensive model for that. Save the premium tokens for decisions that actually require reasoning.
|
||||||
|
|
||||||
|
**The human stays in the loop for decisions.** The agents can file issues, draft announcements, and generate assets --- but they don't merge code, deploy builds, or post to public channels without explicit approval. The workflow is designed so the AI handles the grunt work while humans make the calls that matter.
|
||||||
|
|
||||||
|
**Voice input changes everything.** When you can describe a bug while looking at the game screen, and the agent transcribes, interprets, and files an issue --- that's a workflow that collapses the distance between noticing a problem and tracking it.
|
||||||
|
|
||||||
|
**Skills compound.** Every skill file you write makes the agent more capable. After 6 months, our agents have 15+ skills covering art generation, competitive research, video production, and project management. Each one took 30 minutes to write and saves hours every week.
|
||||||
|
|
||||||
|
## The Numbers
|
||||||
|
|
||||||
|
- **Team size:** 4 humans + AI agents
|
||||||
|
- **Background agent cost:** ~$15/day (~$450/month)
|
||||||
|
- **Knowledge files:** 200+ markdown documents
|
||||||
|
- **Skills:** 15+ agent skill files and growing
|
||||||
|
- **Infrastructure:** Multiple machines, self-hosted git, zero DevOps engineers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
We're not claiming this is how every studio should work. But for a small team trying to build something ambitious, having AI agents that actually understand the project --- not just answer questions about it --- has been transformative. The agents don't replace anyone on the team. They make it possible for four people to do the work of forty.
|
||||||
|
|
||||||
|
We're building all of this as part of [Tinqs Studio](https://tinqs.com) --- a game development platform that brings git hosting, AI tools, and team workflows together. The blog posts and skills in this repo are part of that journey.
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
---
|
||||||
|
title: "AI Art at Scale: Using fal.ai Flux for Game Asset Generation"
|
||||||
|
slug: fal-image-generation
|
||||||
|
date: "2026-05-25"
|
||||||
|
description: "How we use fal.ai Flux models to generate concept art, trailer frames, and UI assets for our game --- with a 4-layer prompt pattern that actually works."
|
||||||
|
og_description: "fal.ai Flux for game art: 4-layer prompts, $0.01/image, and a pipeline that replaced our concept art bottleneck."
|
||||||
|
og_image: "https://www.tinqs.com/img/og-cover.jpg"
|
||||||
|
excerpt: "We generate concept art, trailer frames, and UI icons with fal.ai Flux models at $0.01 per image. Here's the prompt engineering pattern that makes it work for game dev."
|
||||||
|
author: "Ozan Bozkurt"
|
||||||
|
author_initials: "OB"
|
||||||
|
author_role: "CTO & Developer, Tinqs"
|
||||||
|
---
|
||||||
|
We're a small indie studio building a survival colony sim. We don't have a concept artist on staff. Every piece of character art, trailer frame, and UI icon in our game was generated with fal.ai Flux models --- at roughly a penny per image.
|
||||||
|
|
||||||
|
## The Problem with AI Art for Games
|
||||||
|
|
||||||
|
Most AI image generators produce beautiful images that are completely useless for game development. They look great on social media but fall apart when you need consistency: the same character from four angles, a UI icon that reads at 64x64, a trailer frame that matches your game's art style rather than whatever the model defaults to.
|
||||||
|
|
||||||
|
The issue isn't the models --- Flux is genuinely good. The issue is prompting. When you write "warrior on a beach," you get a different art style every time. Different skin tones, different proportions, different lighting. You can't build a game from that.
|
||||||
|
|
||||||
|
We spent three months iterating on prompt patterns before we found something that works consistently. The result is a 4-layer system that anchors the model to your art direction and produces images you can actually ship.
|
||||||
|
|
||||||
|
## Why fal.ai
|
||||||
|
|
||||||
|
We evaluated Midjourney, DALL-E 3, Stable Diffusion (self-hosted), and fal.ai:
|
||||||
|
|
||||||
|
**API-first.** Midjourney is Discord-only. DALL-E's API works but the model makes everything look like a stock photo. Self-hosted SD means maintaining GPU infrastructure. fal.ai gives you Flux models behind a simple REST API --- POST a prompt, GET an image URL.
|
||||||
|
|
||||||
|
**Cost.** $0.01 per image with `flux-2-pro`. $0.004 with `schnell` for rapid iteration. A full character design session --- 12 variants across 3 rounds of refinement --- costs $0.12. A 20-frame trailer storyboard costs $0.20. At these prices, the bottleneck is creative direction, not budget.
|
||||||
|
|
||||||
|
**Speed.** `flux/schnell` returns an image in 4 seconds. `flux-2-pro` in 15 seconds. Fast enough that an AI agent can generate, display, get feedback, and regenerate in a single conversation turn.
|
||||||
|
|
||||||
|
**No subscription.** Pay per image. No monthly fee, no credit packs that expire, no tier-gated features.
|
||||||
|
|
||||||
|
## The 4-Layer Prompt Pattern
|
||||||
|
|
||||||
|
This is the pattern that made AI art actually usable for our game. Each layer adds specificity, and the combination anchors the model to a consistent output.
|
||||||
|
|
||||||
|
### Layer 1: Design Context
|
||||||
|
|
||||||
|
The most important layer and the one most people skip. It sets the overall art direction:
|
||||||
|
|
||||||
|
```
|
||||||
|
Art direction: stylized 3D render for a survival colony sim. Warm earthy
|
||||||
|
palette --- browns, tans, dark reds, cream, ocean blues. Carved wood
|
||||||
|
textures, traditional patterns, woven natural fibres. Game engine quality,
|
||||||
|
not photorealistic.
|
||||||
|
```
|
||||||
|
|
||||||
|
This paragraph appears at the start of every prompt. Same paragraph whether you're generating a character, a landscape, or an icon. It anchors the model to your art style.
|
||||||
|
|
||||||
|
**The key insight:** write this once, paste it everywhere. It's your art bible compressed into 50 words. Every time we skipped it --- "just a quick test" --- the output drifted into generic fantasy art.
|
||||||
|
|
||||||
|
### Layer 2: Scene Description
|
||||||
|
|
||||||
|
Describe exactly what should appear, element by element:
|
||||||
|
|
||||||
|
```
|
||||||
|
Full body character in T-pose, front view. Young woman, mid-20s.
|
||||||
|
Wearing a woven wrap skirt (mid-thigh length) and a fitted cloth top.
|
||||||
|
Shell necklace with a carved bone pendant. Single bone bracelet on
|
||||||
|
left wrist. Hair swept back over right shoulder. Bare feet.
|
||||||
|
Matte skin, warm brown tones. Neutral confident expression ---
|
||||||
|
not smiling, not angry. Dark grey background.
|
||||||
|
```
|
||||||
|
|
||||||
|
Not "tribal clothing" but "woven wrap skirt." Not "jewelry" but "shell necklace with a carved bone pendant." Vague prompts produce vague results. Specific prompts produce usable assets.
|
||||||
|
|
||||||
|
### Layer 3: Negative Prompt
|
||||||
|
|
||||||
|
Always include what you don't want:
|
||||||
|
|
||||||
|
```
|
||||||
|
Do not include: cartoon style, anime style, photorealistic render,
|
||||||
|
extra text or taglines, watermark, deformed elements, modern or
|
||||||
|
sci-fi. No extra fingers, no merged limbs, no floating accessories.
|
||||||
|
```
|
||||||
|
|
||||||
|
Extend per-subject. For characters: "no stereotypical elements, no overly shiny materials." The negative prompt is as important as the positive one.
|
||||||
|
|
||||||
|
### Layer 4: Reference Images
|
||||||
|
|
||||||
|
When you need consistency --- the same character from different angles, or a new character matching an existing one --- pass a reference image:
|
||||||
|
|
||||||
|
```python
|
||||||
|
result = fal_client.subscribe("fal-ai/flux-2-pro", arguments={
|
||||||
|
"prompt": "Same character, side view, same clothing and accessories...",
|
||||||
|
"image_url": "https://your-approved-front-view.png",
|
||||||
|
"image_size": "square_hd",
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The first approved image becomes the reference for all subsequent views. Without it, you get a different person every time.
|
||||||
|
|
||||||
|
## The Model Lineup
|
||||||
|
|
||||||
|
| Model | Cost | Speed | When |
|
||||||
|
|-------|------|-------|------|
|
||||||
|
| `flux-2-pro` | $0.01 | ~15s | Final art. Default for anything you'll ship. |
|
||||||
|
| `flux/schnell` | $0.004 | ~4s | Exploration and iteration. |
|
||||||
|
| `ideogram/v2` | $0.008 | ~5s | Anything with readable text --- logos, UI, posters. |
|
||||||
|
| `flux-pro/v1.1-ultra` | $0.015 | ~8s | Highest quality, but can hang. |
|
||||||
|
|
||||||
|
The workflow: explore with `schnell`, refine with `flux-2-pro`, add text with `ideogram/v2`.
|
||||||
|
|
||||||
|
## How This Fits Our Pipeline
|
||||||
|
|
||||||
|
fal.ai is the first step in a pipeline from idea to in-game asset:
|
||||||
|
|
||||||
|
```
|
||||||
|
Brief --> fal.ai (2D concept art) --> Tripo Studio (3D model) --> Blender (decimate) --> Godot (in-game)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **Brief.** The designer describes the character or asset.
|
||||||
|
2. **2D generation.** Generate 3 variants with `flux-2-pro`, score each on a rubric (style match, cultural accuracy, silhouette, expression, animatability), pick the best.
|
||||||
|
3. **Reference sheet.** Generate front, side, three-quarter, and head closeup views using the winner as reference.
|
||||||
|
4. **3D model.** Approved concept art goes into Tripo Studio for image-to-3D. Outputs ~1.5M faces with full PBR textures.
|
||||||
|
5. **Decimation.** Blender CLI decimates to 25,000 faces.
|
||||||
|
6. **Rigging.** Auto-rig the body (hair separated first if large).
|
||||||
|
7. **In-game.** Import into the engine, set up materials, done.
|
||||||
|
|
||||||
|
The entire pipeline from "I want a character" to "character walking around in the game" takes about 2 hours. The quality isn't AAA, but for an indie game with a stylised art style, it's more than good enough.
|
||||||
|
|
||||||
|
## What We Learned
|
||||||
|
|
||||||
|
**The design context layer is everything.** Without it, every image is a one-off. With it, every image belongs to the same game. The 50-word context block is worth more than the rest of the prompt combined.
|
||||||
|
|
||||||
|
**Negative prompts prevent drift.** AI models have strong defaults --- they want to make things shiny, symmetrical, and photorealistic. If your game isn't those things, say so explicitly.
|
||||||
|
|
||||||
|
**Score and iterate, don't accept the first output.** Generate 3 variants, score on 5 criteria, approve only 8+/10. Three attempts at $0.01 each is $0.03 --- cheaper than working around a mediocre image.
|
||||||
|
|
||||||
|
**Reference images are the consistency mechanism.** Without them, every generation is independent. With them, every generation builds on the last approved output. This is how you get a roster of characters that look like they belong in the same game.
|
||||||
|
|
||||||
|
**Fast models for exploration, quality models for output.** `schnell` at 4 seconds is for "what if..." iterations. `flux-2-pro` at 15 seconds is for "yes, this is the one."
|
||||||
|
|
||||||
|
**Let the AI agent handle prompt engineering.** We encode the 4-layer pattern, art style guide, and cultural guardrails in a [skill file](../skills/image-generation.md). The agent writes the full prompt, generates images, displays them, and asks for scores. The human's job is creative direction.
|
||||||
|
|
||||||
|
## The Numbers
|
||||||
|
|
||||||
|
- **Characters designed:** 10 (full roster for early access)
|
||||||
|
- **Total images generated:** ~400 across all iterations
|
||||||
|
- **Total cost:** ~$6 in fal.ai credits
|
||||||
|
- **Time per character:** ~30 minutes from brief to approved reference sheet
|
||||||
|
- **Pipeline time:** ~2 hours from concept art to in-game model
|
||||||
|
- **Models used:** flux-2-pro (80%), schnell (15%), ideogram/v2 (5%)
|
||||||
|
|
||||||
|
## Open-Source Skills
|
||||||
|
|
||||||
|
We've published the skill files that power this workflow. A skill is a markdown document that teaches an AI agent a specific procedure --- like a runbook, but the reader is an LLM.
|
||||||
|
|
||||||
|
- **[Image Generation](../skills/image-generation.md)** --- fal.ai API, 4-layer prompt pattern, model comparison
|
||||||
|
- **[Concept Art Pipeline](../skills/concept-art-pipeline.md)** --- full 2D-to-3D character workflow
|
||||||
|
- **[3D Model Generation](../skills/tripo-browser-workflow.md)** --- Tripo Studio text-to-3D and image-to-3D
|
||||||
|
- **[Video Generation](../skills/sora2-video.md)** --- trailer clip generation with OpenAI Sora 2
|
||||||
|
|
||||||
|
Drop any of these into your `.cursor/skills/` directory and your AI agent can follow them. Adapt the design context block to your game's art style and you're good to go.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
AI image generation isn't magic and it isn't free. But at a penny per image, with the right prompt structure, it eliminates the most expensive bottleneck in indie game development: the gap between "I know what this should look like" and "I have an image I can actually use."
|
||||||
|
|
||||||
|
We're building all of this as part of [Tinqs Studio](https://tinqs.com) --- a game development platform that brings together git hosting, AI tools, and creative workflows for game teams.
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
title: "Why We Forked Gitea and Built Tinqs Studio"
|
||||||
|
slug: forking-gitea
|
||||||
|
date: "2026-05-20"
|
||||||
|
description: "Game studios need git hosting that understands large files, 3D assets, and team workflows. We forked Gitea and built Tinqs Studio --- here's why and how."
|
||||||
|
og_description: "Game studios need git that understands LFS, 3D previews, and team workflows. We built Tinqs Studio."
|
||||||
|
og_image: "https://www.tinqs.com/img/og-cover.jpg"
|
||||||
|
excerpt: "GitHub doesn't understand game dev. We forked Gitea to build Tinqs Studio --- with 3D asset preview, LFS-first workflows, and project management for game teams."
|
||||||
|
author: "Ozan Bozkurt"
|
||||||
|
author_initials: "OB"
|
||||||
|
author_role: "CTO & Developer, Tinqs"
|
||||||
|
---
|
||||||
|
GitHub is built for web developers. Game studios need something different --- LFS that works, 3D asset previews in the browser, and project management that understands sprints and milestones. So we forked Gitea and built Tinqs Studio.
|
||||||
|
|
||||||
|
## The Problem with GitHub for Game Dev
|
||||||
|
|
||||||
|
We used GitHub for two years. It was fine for docs --- small files, text diffs, pull requests. But the game repo was a different story.
|
||||||
|
|
||||||
|
A single character model with textures and animations is 50--200MB. A terrain heightmap is 16MB. An island's vegetation data is another 10MB. Our game repo was 12GB in LFS alone, growing every week. GitHub's LFS bandwidth limits, slow clone times, and $5/50GB pricing made it untenable.
|
||||||
|
|
||||||
|
More importantly, nobody on the team could **see** what changed. A PR that modifies a GLB file shows a binary diff. You can't preview it. You can't compare before and after. The artist pushes a model, the developer approves it blindly, and three days later someone notices the normals are inverted.
|
||||||
|
|
||||||
|
## Why Self-Host, and Why Gitea
|
||||||
|
|
||||||
|
We evaluated GitLab, Forgejo, Gogs, and Gitea. The decision came down to:
|
||||||
|
|
||||||
|
- **Single binary.** Gitea compiles to one Go binary with SQLite support. No PostgreSQL, no Redis, no Docker compose with 7 services. Just copy the binary, write an app.ini, and run it.
|
||||||
|
- **Resource usage.** Our instance runs on a single EC2 instance alongside other services. It uses about 200MB RAM. GitLab needs 4GB minimum.
|
||||||
|
- **LFS built-in.** Gitea includes a full LFS server. No external LFS store, no S3 configuration for basic use. Files are stored locally. We added S3 backend later, but it works out of the box.
|
||||||
|
- **Forkable.** Gitea is MIT-licensed, written in Go, with a clean codebase. We can modify it without worrying about license restrictions or CLA headaches.
|
||||||
|
|
||||||
|
We ran vanilla Gitea for six months. It solved the cost and bandwidth problems immediately. But the UX gaps for game development were still there.
|
||||||
|
|
||||||
|
## What We Built: Tinqs Studio
|
||||||
|
|
||||||
|
[Tinqs Studio](https://tinqs.com) is our fork. It tracks upstream Gitea on the `main` branch and keeps all customisations on a separate branch. We rebase onto upstream releases periodically, fix conflicts, and deploy.
|
||||||
|
|
||||||
|
### 3D Asset Preview
|
||||||
|
|
||||||
|
The headline feature. When you open a PR that contains a `.glb`, `.gltf`, or `.fbx` file, you see a 3D viewer directly in the browser. Rotate, zoom, check materials. No downloads, no external tools. We integrated Online 3D Viewer (O3DV), which supports 22 file formats including STL, OBJ, 3DS, and PLY.
|
||||||
|
|
||||||
|
This changes the review process fundamentally. The artist pushes a model, the lead rotates it in the browser, leaves a comment about the UV seam on the shoulder, and the artist fixes it --- all without leaving the git platform.
|
||||||
|
|
||||||
|
### LFS-First Workflows
|
||||||
|
|
||||||
|
Vanilla Gitea treats LFS as an afterthought. You configure `.gitattributes` manually. There's no dashboard showing LFS usage, no way to see which files are tracked, no warnings when someone commits a large file without LFS.
|
||||||
|
|
||||||
|
Tinqs Studio adds auto-LFS tracking on repository creation. Game file extensions (`.fbx`, `.glb`, `.png`, `.wav`, `.ogg`, `.tscn`, `.tres`) are tracked by default. An API endpoint exposes LFS storage stats per repo. The goal: LFS should be invisible. It should just work.
|
||||||
|
|
||||||
|
### Platform Integration
|
||||||
|
|
||||||
|
Tinqs Studio integrates project management --- issues, sprints, time tracking --- and OAuth2 SSO. One login for git, the game tools, and the team dashboard.
|
||||||
|
|
||||||
|
## The Branching Strategy
|
||||||
|
|
||||||
|
Staying close to upstream is critical. We don't want to maintain a fork that diverges forever:
|
||||||
|
|
||||||
|
- `main` tracks upstream `go-gitea/gitea`. We never commit to it directly.
|
||||||
|
- Our production branch holds all customisations.
|
||||||
|
- Feature branches merge into production.
|
||||||
|
- When upstream releases a new version, we merge, resolve conflicts, test, deploy.
|
||||||
|
|
||||||
|
We deliberately limit what we touch. We modify templates, locale strings, CSS variables, and a handful of Go packages. We **never** touch the database models --- schema is owned by upstream, and we ride their migrations. This keeps rebasing manageable.
|
||||||
|
|
||||||
|
## What We Learned
|
||||||
|
|
||||||
|
**Self-hosting git is surprisingly easy.** The hard part isn't running Gitea --- it's convincing yourself that you're allowed to. After years of GitHub being the default, it feels transgressive to host your own git. But a single Go binary on a $10/month server handles a small team with room to spare.
|
||||||
|
|
||||||
|
**LFS changes everything for game repos.** Our clone times went from 45 minutes to 3 minutes. Developers only download the LFS objects they need. CI only pulls what changed. The bandwidth savings alone paid for the server.
|
||||||
|
|
||||||
|
**Forking is maintenance, not rebellion.** The romantic version is "we forked Gitea and built our own platform." The reality is we changed 200 lines of Go, 50 template strings, and a CSS file. 99.5% of the code is upstream's. We're just customising the last half-percent for our use case.
|
||||||
|
|
||||||
|
**3D preview is a game changer.** We expected it to be a nice-to-have. It turned out to be the feature that made the rest of the team actually use git. When the artist can see their work rendered in the browser, they stop asking the developer to "check if it looks right."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[Tinqs Studio](https://tinqs.com) is built for game teams that are tired of paying GitHub for LFS bandwidth and reviewing binary diffs blind. We're building it for ourselves first --- dogfooding it on our own game --- but the plan is to make it available as a platform for other studios. If you're a game team that self-hosts or wants to, we'd love to hear what features you need.
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
---
|
||||||
|
title: "Streaming a 12km Archipelago in Godot 4"
|
||||||
|
slug: godot-optimisation
|
||||||
|
date: "2026-05-22"
|
||||||
|
description: "How we built four streaming layers, async resource loading, and memory-safe caches to run a 12km open world in Godot 4 with C#."
|
||||||
|
og_description: "Four streaming layers, async loading, and zero memory leaks --- optimising Godot for a large open world."
|
||||||
|
og_image: "https://www.tinqs.com/img/og-cover.jpg"
|
||||||
|
excerpt: "Four streaming layers, async resource loading, memory-safe caches, and zero leaks. How we built a 12km open world in Godot 4 with C#."
|
||||||
|
author: "Ozan Bozkurt"
|
||||||
|
author_initials: "OB"
|
||||||
|
author_role: "CTO & Developer, Tinqs"
|
||||||
|
---
|
||||||
|
Godot has no built-in asset streaming. Our game is a 12km x 12km archipelago with 9 islands, thousands of trees, hundreds of buildings, and an ocean that never ends. Here's how we made it run.
|
||||||
|
|
||||||
|
## The Problem
|
||||||
|
|
||||||
|
We're building a survival colony sim set across 9 islands. The total world is roughly 12km x 12km. Each island is 4km across with its own terrain heightmap, biome textures, vegetation prototypes, and building grids. The player can travel between islands by canoe.
|
||||||
|
|
||||||
|
Godot 4 is a fantastic engine, but it wasn't designed for this scale. There's no terrain streaming, no asset LOD pipeline, no distance-based loading. If you load everything at startup, you run out of VRAM before the player sees the main menu. So we built four streaming layers on top of Godot, all in C#.
|
||||||
|
|
||||||
|
## Layer 1: Terrain Regions
|
||||||
|
|
||||||
|
We use **Terrain3D** for heightmaps --- a GDExtension that gives us a clipmap renderer with 7 LOD levels. Internally, Terrain3D divides each island into 512m x 512m regions. A 4km island has 64 regions. Across 9 islands, that's 576 regions total.
|
||||||
|
|
||||||
|
The key insight: **don't create all 9 terrain nodes at startup.** Each node allocates a clipmap mesh, collision structures, and materials even when hidden. Our original code created all 9 in `_Ready()` and just toggled visibility. This wasted hundreds of megabytes on islands the player hadn't visited yet.
|
||||||
|
|
||||||
|
The fix was lazy instantiation. We create the current island's terrain on startup and defer the rest. When the player gets in a canoe and sails to a new island, we create that island's terrain node on demand, import the heightmap, and start async texture loading --- all while a loading screen covers the transition.
|
||||||
|
|
||||||
|
## Layer 2: Vegetation Chunks (128m Grid)
|
||||||
|
|
||||||
|
This is the main prop streaming system. Every island's vegetation --- trees, rocks, grasses, shrubs --- is divided into a spatial grid of 128m x 128m chunks.
|
||||||
|
|
||||||
|
The camera position is checked every 0.5 seconds. When it crosses a chunk boundary, we calculate which chunks should be active within a 400m radius (roughly 39 chunks in a circle), `QueueFree` chunks that fell out of range, and build new chunks that entered range.
|
||||||
|
|
||||||
|
Each chunk groups vegetation instances by prototype, creates a **MultiMesh** per group, and places instances using height queries. A chunk with 50 palm trees and 30 rocks becomes 2 MultiMesh draw calls, not 80 individual nodes.
|
||||||
|
|
||||||
|
### The cache problem
|
||||||
|
|
||||||
|
Vegetation meshes and materials are cached in dictionaries keyed by prototype name. The problem: these caches are **append-only**. Visit all 9 islands and you accumulate every mesh and material variant permanently. With 155 unique prototypes across the archipelago, that's a lot of GPU memory that never gets freed.
|
||||||
|
|
||||||
|
The fix is island-scoped eviction. When the player leaves an island, we clear the vegetation caches. Meshes and materials for the departed island are released. If the player returns, they reload from disk. The loading screen covers this cost.
|
||||||
|
|
||||||
|
## Layer 3: Async Resource Loading
|
||||||
|
|
||||||
|
Godot's `GD.Load()` is synchronous. It blocks the main thread. During gameplay, the frame freezes. We audited the entire codebase and found **26 resource load calls across 13 files**, and only 1 was async.
|
||||||
|
|
||||||
|
The worst offender was `GetMeshForProto()` in the vegetation grid. As the player walks across an island for the first time, every new vegetation prototype triggers a synchronous load. With 155 prototypes, the first traversal stutters visibly.
|
||||||
|
|
||||||
|
We fixed this in two ways:
|
||||||
|
|
||||||
|
- **Pre-warm during loading screens.** When an island is imported, we kick off background loads for all known prototypes. By the time the player gains control, most meshes are already cached.
|
||||||
|
- **Async loading for biome textures.** Terrain textures use `ResourceLoader.LoadThreadedRequest()` with `_Process()` polling. The terrain renders immediately with autoshader colours, and biome textures pop in when ready. The player never notices.
|
||||||
|
|
||||||
|
### The ResourceLoader cache trap
|
||||||
|
|
||||||
|
On top of our own caches, Godot maintains an internal resource cache. Every `GD.Load()` call caches the result globally. There's no API to query the cache size or evict entries.
|
||||||
|
|
||||||
|
If you load an FBX as a `PackedScene`, instantiate it to extract a mesh, then free the instance --- the PackedScene **stays cached**. The mesh you extracted is fine (it's a Resource, not a Node), but the discarded scene wastes memory forever.
|
||||||
|
|
||||||
|
The rule: use `ResourceLoader.Load(path, "", CacheMode.Ignore)` for one-shot loads where you extract data and discard the container. Use `GD.Load()` only for things that should persist (shaders, shared textures).
|
||||||
|
|
||||||
|
## Layer 4: Entity Rendering
|
||||||
|
|
||||||
|
Dynamic entities --- colonists, animals, buildings, VFX --- are event-driven, not streamed. They update when the simulation pushes new state, not per frame.
|
||||||
|
|
||||||
|
- **Crowd rendering:** Single MultiMesh for up to 2000 colonists. Positions lerped per frame from pre-allocated arrays. Labels distance-culled, capped at 20. No individual nodes, no per-frame allocation.
|
||||||
|
- **Animals:** One MultiMesh per type. Max 500 per type. Updates only on state change, not per frame.
|
||||||
|
- **Buildings:** Tracked by ID from sim state. `QueueFree` when removed. Self-cleaning.
|
||||||
|
- **VFX:** Capped at 50 active particle systems. Worst case: 10,000 GPU particles.
|
||||||
|
|
||||||
|
## Memory Safety: Zero Leaks
|
||||||
|
|
||||||
|
We audited every `QueueFree()` call in the codebase --- 47 calls across 17 files. **Zero `RemoveChild()` calls without a corresponding `QueueFree()`.** Three patterns we follow everywhere:
|
||||||
|
|
||||||
|
**Pattern 1: Chunk streaming** --- Deactivate out-of-range chunks by iterating the active dict, calling `QueueFree()`, collecting keys to remove, then removing them after iteration. Never modify a dictionary while iterating it.
|
||||||
|
|
||||||
|
**Pattern 2: Extract data from PackedScene** --- Instantiate a scene, extract the mesh, `QueueFree()` the temporary instance. The mesh survives because it's a Resource, not a Node.
|
||||||
|
|
||||||
|
**Pattern 3: UI rebuild** --- `QueueFree()` all children, then build new content. Safe because `QueueFree` is deferred --- new children are added in the same frame before old ones are freed.
|
||||||
|
|
||||||
|
## What Runs Every Frame
|
||||||
|
|
||||||
|
We're strict about what goes in `_Process()`:
|
||||||
|
|
||||||
|
- **Vegetation grid:** Camera chunk check (0.5s throttle, early-exits if same chunk)
|
||||||
|
- **Terrain manager:** Poll async texture loads (loop pending list, check status)
|
||||||
|
- **Crowd renderer:** Lerp 2000 colonist positions (math-only, pre-allocated arrays)
|
||||||
|
- **Day/night:** Rotate sun, adjust light energy
|
||||||
|
- **Camera:** Follow + zoom smoothing
|
||||||
|
- **Sim bridge:** Drain WebSocket message queue
|
||||||
|
|
||||||
|
No heap allocation in any of these. Total per-frame overhead is dominated by the crowd lerp and the message queue drain.
|
||||||
|
|
||||||
|
## Shaders We Watch
|
||||||
|
|
||||||
|
Two custom shaders are performance-sensitive:
|
||||||
|
|
||||||
|
**Ocean shader** --- 4 Gerstner wave calculations in the vertex stage, applied to a 12,000m plane. Fragment stage does depth reconstruction, caustics, foam masking, and two normal map lookups. It's the heaviest thing in the render pipeline. We pre-warm it during the loading screen to avoid shader compilation stutter.
|
||||||
|
|
||||||
|
**Wind sway shader** --- 6 trig ops per vertex on every vegetation mesh within 400m. The sway is invisible beyond 100m but the shader runs at full cost regardless. Future optimisation: disable sway on distant chunks.
|
||||||
|
|
||||||
|
## The Target: RTX 3060
|
||||||
|
|
||||||
|
Our early access target is an RTX 3060 with 8GB VRAM:
|
||||||
|
|
||||||
|
- Main island + full vegetation < 4GB VRAM --- ship it, we have headroom
|
||||||
|
- Approaching 6--8GB --- implement lazy terrain nodes + cache eviction
|
||||||
|
- Exceeding 8GB --- implement vegetation LOD and region-level streaming
|
||||||
|
|
||||||
|
**Always measure before optimising.** We added VRAM logging before writing a single line of optimisation code. Half the "problems" we expected turned out to be non-issues. The other half were worse than expected. Profiling isn't optional.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Godot 4 can handle open worlds at this scale, but it won't do it for you. You need to build streaming, manage your own caches, audit your resource loading, and be disciplined about what runs per frame. The engine gives you the primitives --- MultiMesh, `LoadThreadedRequest`, `QueueFree` --- and it's up to you to wire them into a system that scales.
|
||||||
|
|
||||||
|
We're building with these systems and developing the game using [Tinqs Studio](https://tinqs.com). If you're building something large-scale in Godot, we hope this is useful.
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
---
|
||||||
|
title: "One Binary to Rule Them All: Building a Studio CLI"
|
||||||
|
slug: studio-cli
|
||||||
|
date: "2026-05-18"
|
||||||
|
description: "A single Go binary that handles machine identity, screenshots, cloud vision, and health checks. The glue that makes AI agents useful across a multi-machine game studio."
|
||||||
|
og_description: "A single Go binary for machine identity, screenshots, cloud vision, and AI agent coordination."
|
||||||
|
og_image: "https://www.tinqs.com/img/og-cover.jpg"
|
||||||
|
excerpt: "A single Go binary that gives AI agents context about who you are, what machine you're on, and what services are reachable. Screenshots, cloud vision, health checks --- one install, every machine."
|
||||||
|
author: "Ozan Bozkurt"
|
||||||
|
author_initials: "OB"
|
||||||
|
author_role: "CTO & Developer, Tinqs"
|
||||||
|
---
|
||||||
|
Every machine in our studio runs the same Go binary. It knows who you are, what machine you're on, and what services are reachable. It takes screenshots, sends them to cloud vision, and runs health checks. This is the glue that makes AI agents actually useful in a multi-machine game studio.
|
||||||
|
|
||||||
|
## Why Build a CLI
|
||||||
|
|
||||||
|
When you have multiple machines across several people, two operating systems, and AI agents that need context about the environment they're running in, the glue becomes the hardest part. Which machine is this? What services are reachable? Is the game running? Can I take a screenshot of what the developer is looking at?
|
||||||
|
|
||||||
|
We tried shell scripts. A `setup.sh` for Mac, a `setup.ps1` for Windows, a `check-services.sh` for health checks, a `screenshot.py` that never worked on Windows. They drifted. They broke. Nobody updated them.
|
||||||
|
|
||||||
|
So we built one Go binary that does everything.
|
||||||
|
|
||||||
|
## The Identity System
|
||||||
|
|
||||||
|
The most important command is `identity`. When an AI agent starts a new session --- Cursor, Claude Code, any tool --- the first thing it does is call this command. The output tells the agent:
|
||||||
|
|
||||||
|
- **The soul file** --- the agent's persistent identity, values, and operating principles
|
||||||
|
- **Company context** --- team members, roles, what the company does
|
||||||
|
- **Machine context** --- hostname, OS, which repos are cloned, what services are running
|
||||||
|
- **Ecosystem** --- other repos and their purpose
|
||||||
|
- **Service status** --- which URLs are live and reachable
|
||||||
|
|
||||||
|
This solves a fundamental problem with AI agents: **cold starts.** Every new chat window, every new agent tab, every new session is a blank slate. The agent doesn't know what project this is, who's asking, or what infrastructure exists. One CLI call gives it full context.
|
||||||
|
|
||||||
|
The data lives in markdown files in the docs repo --- the source of truth. Any machine on the network can read it.
|
||||||
|
|
||||||
|
## Screenshots and Vision
|
||||||
|
|
||||||
|
The CLI can capture any window from outside the process. No in-game overlay, no rendering pipeline integration. It uses the OS-level window capture API --- works on Windows (via GDI+) and Mac (via screencapture).
|
||||||
|
|
||||||
|
A `photo` command does the same thing but sends the screenshot to a cloud vision model for analysis. The agent says "take a photo of the game" and gets back a structured description: "The player character is standing near a half-built hut. There are 3 palm trees to the left. The terrain has a visible seam between two biomes."
|
||||||
|
|
||||||
|
This is how you file bugs without typing. Look at the game, tell the agent what's wrong, and the agent takes a screenshot, describes what it sees, and creates an issue with both the description and the image attached.
|
||||||
|
|
||||||
|
## Health Checks
|
||||||
|
|
||||||
|
A `doctor` command runs a comprehensive health check:
|
||||||
|
|
||||||
|
- Is the git platform reachable? Can we authenticate?
|
||||||
|
- Is the game server running?
|
||||||
|
- Are all expected repos cloned and on the right branch?
|
||||||
|
- Are required tools installed and at the right version?
|
||||||
|
|
||||||
|
The output is a green/yellow/red table. If something's wrong, the agent knows immediately and can diagnose or escalate. This is essential for unattended agent sessions --- the agent can verify its environment before starting work.
|
||||||
|
|
||||||
|
## Why Go
|
||||||
|
|
||||||
|
Go compiles to a single static binary with no runtime dependencies. No Python virtualenvs, no Node.js version managers, no DLL hell on Windows. The same binary runs on a gaming PC, a designer's MacBook, and a CI runner in AWS.
|
||||||
|
|
||||||
|
Cross-compilation is trivial. We build Windows, Mac (arm64 + amd64), and Linux binaries from a single CI workflow. Push a tag, CI builds all three, uploads to S3, done.
|
||||||
|
|
||||||
|
The binary is 15MB. It starts in under 100ms. It has zero runtime dependencies. For a tool that AI agents call on every session start, speed matters.
|
||||||
|
|
||||||
|
## What We Learned
|
||||||
|
|
||||||
|
**The CLI is the API for AI agents.** When we started, this was a convenience tool for humans. It became the primary interface for AI agents. The `identity` command was originally "nice to have" --- now it's the single most important function in our stack. Every agent session starts with it.
|
||||||
|
|
||||||
|
**One binary beats ten scripts.** Scripts rot. They have different shells, different PATH assumptions, different error handling. A compiled binary either works or it doesn't. It ships with its dependencies baked in. It doesn't care if your Python is 3.9 or 3.12.
|
||||||
|
|
||||||
|
**Cloud vision is underrated for game dev.** Sending a screenshot to a vision model and getting back a structured description sounds gimmicky. In practice, it's the fastest way to document visual bugs. "The tree is floating 2m above the terrain" is much faster to write when the AI is looking at the same screen you are.
|
||||||
|
|
||||||
|
**Agent cold starts are the real problem.** Without the identity system, every new session starts with the agent asking "what project is this?" and the human re-explaining context. With it, the agent knows everything in 100ms. That's the difference between an AI assistant and an AI team member.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
The CLI is part of [Tinqs Studio](https://tinqs.com) --- our game development platform that brings git hosting, AI agent tools, and team workflows together. Every time we find ourselves writing a script that needs to work on multiple machines, we add a subcommand instead. One binary that makes the studio work, whether the operator is human or AI.
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# Skill: Blog Authoring
|
||||||
|
|
||||||
|
Write and publish markdown blog posts with YAML frontmatter. This skill teaches an AI agent how to create well-structured blog posts for a static site built from markdown.
|
||||||
|
|
||||||
|
## Post Format
|
||||||
|
|
||||||
|
Create a markdown file in `posts/<slug>.md` with this frontmatter:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: "Your Post Title"
|
||||||
|
slug: your-post-slug
|
||||||
|
date: "2026-05-22"
|
||||||
|
description: "Full meta description for SEO (150-160 chars ideal)."
|
||||||
|
og_description: "Shorter OG/Twitter description."
|
||||||
|
og_image: "https://your-domain.com/img/og-cover.jpg"
|
||||||
|
excerpt: "Card text shown on the blog index page."
|
||||||
|
author: "Author Name"
|
||||||
|
author_initials: "AN"
|
||||||
|
author_role: "Role, Company"
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
## Writing Guidelines
|
||||||
|
|
||||||
|
- **First paragraph** becomes the lead (displayed prominently below the title, separate from the body)
|
||||||
|
- **Everything after the first blank line** is the post body
|
||||||
|
- Use standard markdown: `## Headings`, `**bold**`, `*italic*`, `[links](url)`, `- lists`, fenced code blocks
|
||||||
|
- Images on their own line become `<figure>` elements with captions
|
||||||
|
- Use `---` for section breaks
|
||||||
|
- Em dashes: `---` renders as —
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
A good technical blog post follows this pattern:
|
||||||
|
|
||||||
|
1. **Lead paragraph** --- what this post is about, in one sentence
|
||||||
|
2. **The Problem** --- what pain point or question motivated this work
|
||||||
|
3. **The Approach** --- what you built or decided, and why
|
||||||
|
4. **Technical Details** --- how it works, with code/diagrams
|
||||||
|
5. **What We Learned** --- insights, surprises, trade-offs
|
||||||
|
6. **Closing** --- what's next, or an invitation to the reader
|
||||||
|
|
||||||
|
## SEO Checklist
|
||||||
|
|
||||||
|
- [ ] Title under 60 characters
|
||||||
|
- [ ] Description 150-160 characters
|
||||||
|
- [ ] og_image set
|
||||||
|
- [ ] Meaningful excerpt for index card
|
||||||
|
- [ ] Internal links where relevant
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- Slugs are kebab-case, matching the filename: `my-post.md` -> slug `my-post`
|
||||||
|
- Dates are ISO format: `2026-05-22`
|
||||||
|
- Canonical URLs: `https://your-domain.com/blog/<slug>`
|
||||||
|
- Don't edit generated HTML --- edit the markdown, then rebuild
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
# Skill: Concept Art Pipeline
|
||||||
|
|
||||||
|
End-to-end workflow for creating game character art --- from design brief through 2D concept art to 3D model export. This skill covers everything before the game engine.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
| Phase | What | Output |
|
||||||
|
|-------|------|--------|
|
||||||
|
| 1 --- Design | 2D concept art via AI image generation | Approved PNG(s) |
|
||||||
|
| 2 --- Model | 3D generation via Tripo Studio | GLB/FBX export |
|
||||||
|
| 3 --- Handoff | Reference file for the dev team | Markdown spec |
|
||||||
|
|
||||||
|
## Phase 1: 2D Concept Art
|
||||||
|
|
||||||
|
### Locking Your Art Style
|
||||||
|
|
||||||
|
Before generating anything, define your art style once and enforce it everywhere. Write it down. Here's an example for a stylised game:
|
||||||
|
|
||||||
|
- **Stylised 3D render**, anime-influenced but not full anime
|
||||||
|
- **Matte skin**, no metallic sheen, warm earthy tones
|
||||||
|
- **Neutral confident expression** --- calm determination, not fierce or smiling
|
||||||
|
- **Earthy palette**: browns, tans, dark reds, cream, black
|
||||||
|
- **Asymmetric accessories** --- different on left vs right
|
||||||
|
- **Dark grey background** for all concept art (consistent, easy to composite)
|
||||||
|
|
||||||
|
### Hard Rules (define yours)
|
||||||
|
|
||||||
|
Every project should have a "do not" list. Examples:
|
||||||
|
|
||||||
|
- NO Disney-adjacent designs (if you're going for something grittier)
|
||||||
|
- NO overly shiny or metallic materials (unless your game's style calls for it)
|
||||||
|
- NO hair falling forward over chest (won't animate well in-engine)
|
||||||
|
- NO culturally inappropriate elements (research your references)
|
||||||
|
|
||||||
|
### Cultural Direction
|
||||||
|
|
||||||
|
If your game draws from real cultures, create an approved/rejected table:
|
||||||
|
|
||||||
|
| Approved | Rejected |
|
||||||
|
|----------|----------|
|
||||||
|
| Woven natural fibres, shell jewelry | Generic "tribal" patterns |
|
||||||
|
| Specific cultural motifs (research them) | Stereotypical elements from wrong cultures |
|
||||||
|
| Natural materials (bone, wood, stone) | Modern materials that break the setting |
|
||||||
|
|
||||||
|
### Generation Steps
|
||||||
|
|
||||||
|
1. **Get the brief** --- gender, role, distinctive features, or "surprise me within the style"
|
||||||
|
2. **Generate 3 variants** using your image generation tool (see [Image Generation skill](image-generation.md))
|
||||||
|
- T-pose, front view, consistent background
|
||||||
|
- Naming convention: `character_<name>_front_full_v01.png`
|
||||||
|
3. **Score each variant** using a rubric (see below)
|
||||||
|
4. **Generate reference sheet** for the winner --- front, side, three-quarter, head closeup
|
||||||
|
5. **Save with metadata** --- prompt, model used, date, score
|
||||||
|
|
||||||
|
### Scoring Rubric (0--10)
|
||||||
|
|
||||||
|
| Score | Meaning | Action |
|
||||||
|
|-------|---------|--------|
|
||||||
|
| 9-10 | Perfect match to art style and brief | Approve, generate reference sheet |
|
||||||
|
| 8 | Strong, minor tweaks needed | Approve with notes, iterate once |
|
||||||
|
| 6-7 | Interesting but needs changes | Note what works, regenerate |
|
||||||
|
| 4-5 | Wrong direction, some salvageable elements | Extract what works, fresh prompt |
|
||||||
|
| 0-3 | Off-target | Drop, adjust approach |
|
||||||
|
|
||||||
|
**Score on:** style match, cultural accuracy, expression, silhouette (distinctive at distance?), technical (T-pose clean? animatable?)
|
||||||
|
|
||||||
|
### Layered Design
|
||||||
|
|
||||||
|
Design characters in separable layers for future equipment/customisation:
|
||||||
|
|
||||||
|
1. **Base body** --- simple underwear, no accessories
|
||||||
|
2. **Lower garment** --- baked into character mesh
|
||||||
|
3. **Upper garment** --- baked or swappable
|
||||||
|
4. **Hair** --- separate asset (swappable)
|
||||||
|
5. **Accessories** --- equipment slots (necklaces, bracelets, headwear)
|
||||||
|
6. **Cape/cloak** --- separate equipment piece
|
||||||
|
|
||||||
|
Generate the full character for the overall look, but keep separation in mind for 3D.
|
||||||
|
|
||||||
|
## Phase 2: 3D Model Generation
|
||||||
|
|
||||||
|
### Using Tripo Studio
|
||||||
|
|
||||||
|
[Tripo Studio](https://studio.tripo3d.ai) generates 3D models from text or images.
|
||||||
|
|
||||||
|
1. Open Tripo Studio
|
||||||
|
2. Text-to-3D or paste your approved concept art for image-to-3D
|
||||||
|
3. Use **Ultra quality**, latest model version, **Texture ON** (~35-50 credits)
|
||||||
|
4. Export as **GLB** (preferred --- preserves PBR textures) or FBX
|
||||||
|
5. Save to your project's asset pipeline
|
||||||
|
|
||||||
|
Tripo outputs ~1.5M faces with full PBR textures (basecolour, normal, ORM). You'll decimate to your target polygon budget in Blender or your engine.
|
||||||
|
|
||||||
|
### Large Hair Problem
|
||||||
|
|
||||||
|
Auto-riggers (like Mixamo) break when the mesh includes big hair --- wrong arm poses, face distortion, rig artifacts.
|
||||||
|
|
||||||
|
**Rule:** For characters with large or complex hair:
|
||||||
|
- Export a **body-only version** (no hair) for rigging
|
||||||
|
- In Tripo: use **Segment** to split hair from body, export body-only
|
||||||
|
- Hair is added back as a separate mesh after rigging
|
||||||
|
|
||||||
|
### Polygon Budget
|
||||||
|
|
||||||
|
Define your LOD targets. Example:
|
||||||
|
|
||||||
|
| LOD | Face Count | Use |
|
||||||
|
|-----|-----------|-----|
|
||||||
|
| LOD0 | 25,000 | Close-up, player character |
|
||||||
|
| LOD1 | 10,000 | Medium distance NPCs |
|
||||||
|
| LOD2 | 2,500 | Crowd/background characters |
|
||||||
|
|
||||||
|
### Texture QA Checklist
|
||||||
|
|
||||||
|
Before handoff, verify:
|
||||||
|
|
||||||
|
- [ ] PBR textures present --- basecolour, normal, roughness/metallic maps
|
||||||
|
- [ ] No UV seams on prominent areas (face, hands)
|
||||||
|
- [ ] Skin tone matches the approved concept art
|
||||||
|
- [ ] No texture stretching on limbs or torso
|
||||||
|
- [ ] Accessories have distinct materials
|
||||||
|
- [ ] Resolution 2K minimum for hero characters
|
||||||
|
- [ ] No generation artifacts (floating geometry, merged fingers, extra limbs)
|
||||||
|
|
||||||
|
## Handoff
|
||||||
|
|
||||||
|
Create a handoff document for each approved character:
|
||||||
|
|
||||||
|
1. **Character identity** --- name, role, description
|
||||||
|
2. **Concept art files** --- paths to approved PNGs
|
||||||
|
3. **3D model files** --- path to GLB/FBX exports
|
||||||
|
4. **Art direction notes** --- what to keep, what to change
|
||||||
|
5. **Technical requirements** --- shader, rig type, LOD targets, scale
|
||||||
|
6. **Known issues** --- large hair flag, texture problems, etc.
|
||||||
|
|
||||||
|
## Batch Generation
|
||||||
|
|
||||||
|
When generating multiple characters:
|
||||||
|
|
||||||
|
1. Prepare all briefs upfront
|
||||||
|
2. Generate in priority order (ship-soonest first)
|
||||||
|
3. Use free retries before spending credits
|
||||||
|
4. Score as you go --- don't batch review
|
||||||
|
5. Track credits per generation
|
||||||
|
6. Export immediately after approval (don't leave work in the cloud tool)
|
||||||
|
|
||||||
|
## Common Mistakes
|
||||||
|
|
||||||
|
| Problem | Cause | Fix |
|
||||||
|
|---------|-------|-----|
|
||||||
|
| Characters look generic | No art style lock | Define and enforce your style guide |
|
||||||
|
| Inconsistent across characters | No reference images | Use your best character as image-to-image reference |
|
||||||
|
| Metallic skin sheen | Default material settings | Use matte keywords, check PBR roughness |
|
||||||
|
| Symmetric accessories | Generation default | Explicitly describe left vs right in prompt |
|
||||||
|
| Auto-rigger fails | Large hair in mesh | Segment and export body-only |
|
||||||
|
| Low-poly look in engine | PBR textures missing | Always generate with Texture ON + PBR ON |
|
||||||
|
|
||||||
|
## Related Skills
|
||||||
|
|
||||||
|
- [Image Generation](image-generation.md) --- fal.ai Flux models and prompt patterns
|
||||||
|
- [Tripo 3D](tripo-browser-workflow.md) --- detailed Tripo Studio workflow
|
||||||
|
- [Sora 2 Video](sora2-video.md) --- animate concept art into video
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
# Skill: Image Generation with fal.ai Flux
|
||||||
|
|
||||||
|
Generate game art, concept art, icons, logos, trailer frames, and marketing visuals using fal.ai Flux models. This skill teaches an AI agent how to call fal.ai's API with structured prompts optimised for game development.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
[fal.ai](https://fal.ai) hosts Flux image generation models with a simple API. You describe what you want, pick a model and size, and get back a URL to the generated image. Costs range from $0.004 to $0.015 per image.
|
||||||
|
|
||||||
|
## Models
|
||||||
|
|
||||||
|
| Model | Quality | Cost/img | Speed | Use |
|
||||||
|
|-------|---------|---------|-------|-----|
|
||||||
|
| `fal-ai/flux-2-pro` | High | ~$0.01 | ~15s | **Default.** Final art, icons, trailer frames. Most reliable. |
|
||||||
|
| `fal-ai/flux/schnell` | Fast | $0.004 | ~4s | Quick mockups, iteration, exploration |
|
||||||
|
| `fal-ai/flux-pro/v1.1-ultra` | Ultra | $0.015 | ~8s | Highest quality, but can be slow. Fall back to flux-2-pro if it hangs. |
|
||||||
|
| `fal-ai/ideogram/v2` | Typography | $0.008 | ~5s | Logos with readable text, posters, banners |
|
||||||
|
|
||||||
|
**How to pick:** Use `flux-2-pro` for most work. Use `schnell` when iterating fast. Use `ideogram/v2` when you need readable text in the image.
|
||||||
|
|
||||||
|
## Sizes
|
||||||
|
|
||||||
|
| Value | Dimensions | Use |
|
||||||
|
|-------|-----------|-----|
|
||||||
|
| `square` | 512x512 | Icons, favicons |
|
||||||
|
| `square_hd` | 1024x1024 | App icons, logos, character portraits |
|
||||||
|
| `landscape_16_9` | 1024x576 | Trailer frames, hero images, Steam banners |
|
||||||
|
| `portrait_16_9` | 576x1024 | Steam capsules, posters, mobile splash screens |
|
||||||
|
|
||||||
|
## API Usage
|
||||||
|
|
||||||
|
### Python (fal-client)
|
||||||
|
|
||||||
|
```python
|
||||||
|
import fal_client
|
||||||
|
|
||||||
|
result = fal_client.subscribe("fal-ai/flux-2-pro", arguments={
|
||||||
|
"prompt": "Your detailed prompt here",
|
||||||
|
"image_size": "landscape_16_9",
|
||||||
|
"num_images": 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
image_url = result["images"][0]["url"]
|
||||||
|
print(image_url)
|
||||||
|
```
|
||||||
|
|
||||||
|
### JavaScript
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import * as fal from "@fal-ai/serverless-client";
|
||||||
|
|
||||||
|
const result = await fal.subscribe("fal-ai/flux-2-pro", {
|
||||||
|
input: {
|
||||||
|
prompt: "Your detailed prompt here",
|
||||||
|
image_size: "landscape_16_9",
|
||||||
|
num_images: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(result.images[0].url);
|
||||||
|
```
|
||||||
|
|
||||||
|
### cURL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://queue.fal.run/fal-ai/flux-2-pro" \
|
||||||
|
-H "Authorization: Key $FAL_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"prompt": "Your detailed prompt here",
|
||||||
|
"image_size": "landscape_16_9",
|
||||||
|
"num_images": 1
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Image-to-image (reference images)
|
||||||
|
|
||||||
|
Pass a reference image URL for guided generation:
|
||||||
|
|
||||||
|
```python
|
||||||
|
result = fal_client.subscribe("fal-ai/flux-2-pro", arguments={
|
||||||
|
"prompt": "Same scene but at sunset, warm golden light",
|
||||||
|
"image_url": "https://your-reference-image.png",
|
||||||
|
"image_size": "landscape_16_9",
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
For dual-reference compositing (mixing elements from two images), pass comma-separated URLs and describe which elements come from which reference in the prompt.
|
||||||
|
|
||||||
|
## Prompt Engineering --- the 4-Layer Pattern
|
||||||
|
|
||||||
|
This pattern consistently produces the best results for game art. Each layer adds specificity.
|
||||||
|
|
||||||
|
### Layer 1: Design context
|
||||||
|
|
||||||
|
Set the overall art direction. This anchors the model's style. Example for a Polynesian survival game:
|
||||||
|
|
||||||
|
```
|
||||||
|
Art direction: stylized 3D render for a survival colony sim set in a Polynesian
|
||||||
|
archipelago. Warm earthy palette --- browns, tans, dark reds, cream, ocean blues.
|
||||||
|
Carved wood textures, koru spirals, woven pandanus patterns. Moana-meets-Valheim
|
||||||
|
aesthetic. Game engine quality, not photorealistic.
|
||||||
|
```
|
||||||
|
|
||||||
|
Adapt this to your game's art style. The key is being specific about palette, materials, and cultural references.
|
||||||
|
|
||||||
|
### Layer 2: Scene description
|
||||||
|
|
||||||
|
Describe exactly what should appear, element by element:
|
||||||
|
|
||||||
|
- Camera angle and POV
|
||||||
|
- Characters (count, poses, clothing, expressions)
|
||||||
|
- Environment (time of day, weather, terrain, vegetation)
|
||||||
|
- Colours and lighting
|
||||||
|
- Technical style (stylised realism, cel-shaded, pixel art, etc.)
|
||||||
|
|
||||||
|
**Be specific.** "A warrior standing on a beach" produces generic results. "A Polynesian warrior in a T-pose, front view, wearing tapa cloth wrap and cowrie shell necklace, matte skin, earthy tones, dark grey background" produces usable concept art.
|
||||||
|
|
||||||
|
### Layer 3: Negative prompt
|
||||||
|
|
||||||
|
Always include what you don't want:
|
||||||
|
|
||||||
|
```
|
||||||
|
Do not include: cartoon style, anime style, photorealistic render, extra text
|
||||||
|
or taglines, watermark, deformed elements, modern or sci-fi elements.
|
||||||
|
```
|
||||||
|
|
||||||
|
Extend with subject-specific negatives. For character art: "no extra fingers, no merged limbs, no floating accessories."
|
||||||
|
|
||||||
|
### Layer 4: Reference images (optional)
|
||||||
|
|
||||||
|
When you have existing art to match, pass it as `image_url`. Describe in the prompt which elements to keep: "Same character design but in a side view. Keep the clothing and hair style from the reference."
|
||||||
|
|
||||||
|
## Game Dev Use Cases
|
||||||
|
|
||||||
|
### Character concept art
|
||||||
|
|
||||||
|
```
|
||||||
|
Stylized 3D render of a young Polynesian woman in T-pose, front view.
|
||||||
|
Wearing woven pandanus skirt and tapa cloth top. Cowrie shell necklace,
|
||||||
|
bone bracelet on left wrist only. Hair swept back over one shoulder,
|
||||||
|
decorated with a hibiscus flower. Matte skin, warm brown tones.
|
||||||
|
Neutral confident expression. Dark grey background.
|
||||||
|
Size: square_hd (1024x1024)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Trailer frames / key art
|
||||||
|
|
||||||
|
```
|
||||||
|
Wide cinematic shot of a coastal village at golden hour. Thatched-roof
|
||||||
|
huts on stilts along a turquoise lagoon. Outrigger canoes pulled up on
|
||||||
|
white sand. Volcanic mountain in the background with clouds wrapping
|
||||||
|
the peak. Warm orange sunlight, long shadows. Stylized game engine
|
||||||
|
quality, not photorealistic.
|
||||||
|
Size: landscape_16_9 (1024x576)
|
||||||
|
```
|
||||||
|
|
||||||
|
### UI icons
|
||||||
|
|
||||||
|
```
|
||||||
|
Game icon: a carved wooden fishing hook with a glowing blue thread
|
||||||
|
wrapped around the shaft. Dark background, subtle ambient occlusion.
|
||||||
|
Clean silhouette, suitable for a 64x64 game UI icon.
|
||||||
|
Size: square (512x512)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logo with text
|
||||||
|
|
||||||
|
```
|
||||||
|
Game logo: the word "ARIKI" in thick bold blocky capital letters.
|
||||||
|
Each letter carved from dark mahogany wood with distinct Polynesian
|
||||||
|
tribal patterns (koru spirals, chevrons, wave motifs) carved as
|
||||||
|
deep relief. Different pattern per letter. Warm directional lighting
|
||||||
|
from above-left. Dark background.
|
||||||
|
Size: square_hd (1024x1024)
|
||||||
|
Model: ideogram/v2 (for readable text)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
| Do | Don't |
|
||||||
|
|----|-------|
|
||||||
|
| Be specific per-element | Write vague one-line prompts |
|
||||||
|
| Always include negative prompts | Skip negatives and hope for the best |
|
||||||
|
| Use `flux-2-pro` for final art | Default to the most expensive model |
|
||||||
|
| Use `schnell` for rapid iteration | Spend $0.01/img on throwaway drafts |
|
||||||
|
| Generate 2-3 variants and pick the best | Generate one and accept it |
|
||||||
|
| Save prompts alongside images | Lose track of what prompt made what |
|
||||||
|
| Match your game's art style in Layer 1 | Let the model pick a random style |
|
||||||
|
| Use reference images for consistency | Describe the same character differently each time |
|
||||||
|
|
||||||
|
## Cost Tracking
|
||||||
|
|
||||||
|
| Scenario | Cost |
|
||||||
|
|----------|------|
|
||||||
|
| 1 quick mockup (schnell) | $0.004 |
|
||||||
|
| 1 final frame (flux-2-pro) | ~$0.01 |
|
||||||
|
| 10-iteration design session | ~$0.10 |
|
||||||
|
| Full character sheet (4 views x 3 variants) | ~$0.12 |
|
||||||
|
| 20-frame trailer storyboard | ~$0.20 |
|
||||||
|
|
||||||
|
At these prices, the bottleneck is creative direction, not budget.
|
||||||
|
|
||||||
|
## Common Mistakes
|
||||||
|
|
||||||
|
| Mistake | Fix |
|
||||||
|
|---------|-----|
|
||||||
|
| Generic one-line prompts | Use the 4-layer pattern |
|
||||||
|
| No art direction context | Always set Layer 1 for your game's style |
|
||||||
|
| No negative prompt | Always include what you don't want |
|
||||||
|
| Using the wrong model for text | Use `ideogram/v2` for logos with readable text |
|
||||||
|
| Not iterating | Generate 2-3 variants, pick the best, refine |
|
||||||
|
| Inconsistent character designs | Use reference images to anchor style across generations |
|
||||||
|
|
||||||
|
## Related Skills
|
||||||
|
|
||||||
|
- [Concept Art Pipeline](concept-art-pipeline.md) --- full 2D-to-3D character workflow
|
||||||
|
- [Sora 2 Video](sora2-video.md) --- animate your generated art into trailer clips
|
||||||
|
- [Tripo 3D](tripo-browser-workflow.md) --- turn 2D concept art into 3D models
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
# Skill: Video Generation with OpenAI Sora 2
|
||||||
|
|
||||||
|
Generate trailer clips, gameplay-style footage, and cinematic sequences using OpenAI's Sora 2 API. This skill covers the API workflow, prompting patterns, and cost management for game development use.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Sora 2 generates 5-20 second video clips from text prompts or still images. For game studios, it's useful for:
|
||||||
|
|
||||||
|
- Trailer pre-visualisation (storyboard frames as video)
|
||||||
|
- Marketing clips before the game is playable
|
||||||
|
- Concept videos to test art direction
|
||||||
|
- Social media content
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- OpenAI API key with Sora access
|
||||||
|
- Set `OPENAI_API_KEY` environment variable
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### Create a video
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://api.openai.com/v1/videos/generations" \
|
||||||
|
-H "Authorization: Bearer $OPENAI_API_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"model": "sora-2",
|
||||||
|
"prompt": "Your prompt here",
|
||||||
|
"size": "1920x1080",
|
||||||
|
"duration": 10,
|
||||||
|
"n": 1
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Response includes a generation ID. Video generation takes 2-10 minutes.
|
||||||
|
|
||||||
|
### Check status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl "https://api.openai.com/v1/videos/generations/{generation_id}" \
|
||||||
|
-H "Authorization: Bearer $OPENAI_API_KEY"
|
||||||
|
```
|
||||||
|
|
||||||
|
Poll until `status` is `"completed"`. The response includes a download URL.
|
||||||
|
|
||||||
|
### Download
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -o output.mp4 "{video_download_url}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Image-to-video
|
||||||
|
|
||||||
|
Animate a still image:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://api.openai.com/v1/videos/generations" \
|
||||||
|
-H "Authorization: Bearer $OPENAI_API_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"model": "sora-2",
|
||||||
|
"prompt": "Camera slowly pulls back, revealing the full village. Waves lap at the shore.",
|
||||||
|
"image": "{base64_or_url_of_image}",
|
||||||
|
"size": "1920x1080",
|
||||||
|
"duration": 5
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
This is powerful for animating your generated concept art or key art frames.
|
||||||
|
|
||||||
|
## Models
|
||||||
|
|
||||||
|
| Model | Quality | Speed | Cost |
|
||||||
|
|-------|---------|-------|------|
|
||||||
|
| `sora-2` | High | 2-5 min | ~$0.10-0.20/clip |
|
||||||
|
| `sora-2-pro` | Highest | 5-10 min | ~$0.50-1.00/clip |
|
||||||
|
|
||||||
|
Use `sora-2` for iteration and pre-vis. Use `sora-2-pro` for final trailer clips only.
|
||||||
|
|
||||||
|
## Prompting for Game Trailers
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
[Camera movement] + [Subject action] + [Environment] + [Lighting/mood] + [Style]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Opening shot
|
||||||
|
|
||||||
|
```
|
||||||
|
Slow aerial drone shot descending toward a cluster of thatched-roof huts
|
||||||
|
on a tropical island shoreline. Crystal clear turquoise water, white sand
|
||||||
|
beach, palm trees swaying gently. Golden hour sunlight, long shadows.
|
||||||
|
Stylised 3D game engine quality, warm colour palette. No text overlays.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Character reveal
|
||||||
|
|
||||||
|
```
|
||||||
|
Medium shot of a young Polynesian woman standing on a cliff edge, looking
|
||||||
|
out over an ocean dotted with volcanic islands. Wind blowing her hair.
|
||||||
|
She turns to face the camera with a calm, determined expression. Sunset
|
||||||
|
light behind her. Stylised 3D render, game cinematic quality.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Action sequence
|
||||||
|
|
||||||
|
```
|
||||||
|
Wide shot of three outrigger canoes racing across open ocean toward a
|
||||||
|
volcanic island. Waves crashing, spray in the air. Warriors paddling
|
||||||
|
in unison. Storm clouds building on the horizon. Dynamic camera
|
||||||
|
tracking the lead canoe. Stylised game engine quality.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cultural Guardrails
|
||||||
|
|
||||||
|
If your game draws from real cultures, set explicit rules:
|
||||||
|
|
||||||
|
- **No anachronistic elements** (modern objects, wrong architectural styles)
|
||||||
|
- **Research your references** --- use authentic building styles, clothing, tools
|
||||||
|
- **Avoid stereotypes** --- specific cultural elements, not generic "exotic"
|
||||||
|
- **No sacred symbols used decoratively** without understanding their meaning
|
||||||
|
|
||||||
|
## Workflow for Trailer Storyboards
|
||||||
|
|
||||||
|
1. **Write the storyboard** --- list each shot with description, duration, and camera movement
|
||||||
|
2. **Generate key frames** using image generation (see [Image Generation skill](image-generation.md))
|
||||||
|
3. **Animate key frames** using Sora 2's image-to-video
|
||||||
|
4. **Generate original clips** for shots that don't need a specific starting frame
|
||||||
|
5. **Review and iterate** --- regenerate clips that don't match the vision
|
||||||
|
6. **Compile** in a video editor (DaVinci Resolve, Premiere, etc.)
|
||||||
|
|
||||||
|
## Cost Management
|
||||||
|
|
||||||
|
| Scenario | Estimated Cost |
|
||||||
|
|----------|---------------|
|
||||||
|
| 1 test clip (sora-2, 5s) | ~$0.10 |
|
||||||
|
| 10-clip exploration session | ~$1.00 |
|
||||||
|
| 20-clip trailer storyboard | ~$2-4 |
|
||||||
|
| Final 5-clip trailer (sora-2-pro) | ~$2.50-5.00 |
|
||||||
|
|
||||||
|
**Tips:**
|
||||||
|
- Use `sora-2` (not pro) for all iteration
|
||||||
|
- Keep clips to 5-10 seconds --- shorter clips have better coherence
|
||||||
|
- Generate 2-3 variants per shot and pick the best
|
||||||
|
- Only use `sora-2-pro` for the final selected shots
|
||||||
|
|
||||||
|
## Common Mistakes
|
||||||
|
|
||||||
|
| Mistake | Fix |
|
||||||
|
|---------|-----|
|
||||||
|
| Overly long prompts | Keep under 200 words. Focus on what's visible. |
|
||||||
|
| Requesting specific text/UI | Sora can't render readable text. Add text in post. |
|
||||||
|
| Not specifying art style | Always end with style direction ("stylised 3D", "game engine quality") |
|
||||||
|
| Using sora-2-pro for iteration | Expensive and slow. Use sora-2 until you're happy with the prompt. |
|
||||||
|
| Ignoring cultural accuracy | Set guardrails before generating. Review outputs for stereotypes. |
|
||||||
|
| Not tracking costs | Log every generation with model, duration, and cost. |
|
||||||
|
|
||||||
|
## Related Skills
|
||||||
|
|
||||||
|
- [Image Generation](image-generation.md) --- create key frames to animate with Sora
|
||||||
|
- [Concept Art Pipeline](concept-art-pipeline.md) --- character and asset design workflow
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
# Skill: 3D Model Generation with Tripo Studio
|
||||||
|
|
||||||
|
Generate 3D models from text descriptions or 2D images using [Tripo Studio](https://studio.tripo3d.ai). This skill covers the workflow for game-ready 3D assets.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Tripo Studio is a web-based text-to-3D and image-to-3D tool. You describe a character, prop, or environment piece --- or upload concept art --- and Tripo generates a textured 3D model in ~60 seconds.
|
||||||
|
|
||||||
|
**Output:** GLB or FBX with full PBR textures (basecolour, normal, ORM/metallic/roughness).
|
||||||
|
|
||||||
|
**Cost:** ~25-50 credits per generation. Free tier: 150 credits/month.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- You have approved 2D concept art and need a 3D model
|
||||||
|
- You need a quick 3D prototype from a text description
|
||||||
|
- You're generating props, characters, or environment pieces for a game
|
||||||
|
- You need multiple variants of the same object
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
### Text-to-3D
|
||||||
|
|
||||||
|
1. Open [Tripo Studio](https://studio.tripo3d.ai)
|
||||||
|
2. Click **Create** -> **Text to 3D**
|
||||||
|
3. Enter your prompt (see prompt tips below)
|
||||||
|
4. Settings:
|
||||||
|
- Quality: **Ultra**
|
||||||
|
- Model: **v3.1 Best Quality** (or latest)
|
||||||
|
- Texture: **ON** (critical --- generates PBR maps)
|
||||||
|
5. Click Generate (~35-50 credits, ~60s)
|
||||||
|
6. Review the model in the 3D viewer --- rotate, check materials
|
||||||
|
7. Export as **GLB** (preferred) or FBX
|
||||||
|
|
||||||
|
### Image-to-3D
|
||||||
|
|
||||||
|
1. Upload your approved concept art (front view, T-pose for characters)
|
||||||
|
2. Settings: same as text-to-3D
|
||||||
|
3. Generate
|
||||||
|
4. Review --- check if the back and sides match your expectations
|
||||||
|
5. Export
|
||||||
|
|
||||||
|
## Prompt Tips for Game Assets
|
||||||
|
|
||||||
|
### Characters
|
||||||
|
|
||||||
|
```
|
||||||
|
Full body character, T-pose, front facing. Young Polynesian woman wearing
|
||||||
|
woven pandanus skirt and tapa cloth top. Shell necklace, flower in hair.
|
||||||
|
Stylized game character, not photorealistic. Clean topology.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key rules:**
|
||||||
|
- Always specify **T-pose** for characters (needed for rigging)
|
||||||
|
- Mention **clean topology** to reduce mesh artifacts
|
||||||
|
- Describe clothing and accessories explicitly
|
||||||
|
- Specify art style (stylized, realistic, low-poly, etc.)
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
```
|
||||||
|
Carved wooden fishing spear with bone tip. Wrapped handle with
|
||||||
|
woven cord. Polynesian style, game prop, stylized.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment pieces
|
||||||
|
|
||||||
|
```
|
||||||
|
Thatched-roof hut on wooden stilts. Open sides with woven wall panels.
|
||||||
|
Polynesian longhouse style. Game-ready, stylized 3D.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Post-Generation Tools
|
||||||
|
|
||||||
|
Tripo offers several refinement tools after generation:
|
||||||
|
|
||||||
|
| Tool | Purpose | When to Use |
|
||||||
|
|------|---------|-------------|
|
||||||
|
| **Segment** | Split model into parts | Characters with large hair (split hair from body for rigging) |
|
||||||
|
| **Retopo** | Retopologize mesh | When face count is too high or topology is bad |
|
||||||
|
| **Texture** | Regenerate textures | When colours don't match concept art |
|
||||||
|
| **Animate** | Add basic animations | Quick previews (not production quality) |
|
||||||
|
| **Edit** | Modify the model | Remove artifacts, adjust proportions |
|
||||||
|
|
||||||
|
## Export Options
|
||||||
|
|
||||||
|
| Format | Use |
|
||||||
|
|--------|-----|
|
||||||
|
| **GLB** | Preferred. Single file, preserves PBR textures, works everywhere |
|
||||||
|
| **FBX** | When your pipeline requires it (Unity, some Blender workflows) |
|
||||||
|
| OBJ | Legacy. Loses PBR data. Avoid. |
|
||||||
|
| USD | For USD-based pipelines |
|
||||||
|
| STL | 3D printing only. No textures. |
|
||||||
|
|
||||||
|
## Polygon Budget
|
||||||
|
|
||||||
|
Tripo outputs ~1.5M faces by default. You'll need to decimate:
|
||||||
|
|
||||||
|
| LOD | Target Faces | Method |
|
||||||
|
|-----|-------------|--------|
|
||||||
|
| LOD0 | 25,000 | Blender Decimate modifier or CLI |
|
||||||
|
| LOD1 | 10,000 | Same |
|
||||||
|
| LOD2 | 2,500 | Same |
|
||||||
|
|
||||||
|
Use Tripo's built-in **Retopo** tool for a quick reduction, or decimate in Blender for more control.
|
||||||
|
|
||||||
|
## The Large Hair Problem
|
||||||
|
|
||||||
|
Auto-riggers (Mixamo, Godot's skeleton system) break when character meshes include large or complex hairstyles. The rig misidentifies the hair volume as part of the body.
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
1. After generation, use Tripo's **Segment** tool
|
||||||
|
2. Select the hair and split it from the body
|
||||||
|
3. Export the **body-only** mesh for rigging
|
||||||
|
4. Export hair separately
|
||||||
|
5. Reattach hair after rigging in Blender or your engine
|
||||||
|
|
||||||
|
Flag this in your handoff document for every character with big hair.
|
||||||
|
|
||||||
|
## Batch Generation
|
||||||
|
|
||||||
|
When generating multiple assets in one session:
|
||||||
|
|
||||||
|
1. Prepare all prompts upfront
|
||||||
|
2. Generate in priority order
|
||||||
|
3. Use the 3 free retries per generation before spending more credits
|
||||||
|
4. Score and review each model immediately
|
||||||
|
5. Track remaining credits
|
||||||
|
6. Export approved models right away --- don't leave them only in the cloud
|
||||||
|
|
||||||
|
## Credit Optimisation
|
||||||
|
|
||||||
|
| Action | Credits |
|
||||||
|
|--------|---------|
|
||||||
|
| Standard quality generation | ~15-25 |
|
||||||
|
| Ultra quality generation | ~35-50 |
|
||||||
|
| Retopo | ~10-15 |
|
||||||
|
| Texture regeneration | ~10 |
|
||||||
|
| Segment | ~5 |
|
||||||
|
|
||||||
|
**Tip:** Start with Standard quality for exploration, switch to Ultra only for final approved designs.
|
||||||
|
|
||||||
|
## Common Mistakes
|
||||||
|
|
||||||
|
| Problem | Fix |
|
||||||
|
|---------|-----|
|
||||||
|
| Model has no textures | Ensure Texture is ON before generating |
|
||||||
|
| Back of character looks wrong | Use image-to-3D with front AND back views, or add "detailed back view" to prompt |
|
||||||
|
| Mesh has floating geometry | Use Edit tool to clean up, or regenerate |
|
||||||
|
| Merged fingers | Common artifact. Regenerate or fix in Blender |
|
||||||
|
| Too many polygons for game use | Use Retopo tool or Blender Decimate |
|
||||||
|
| Hair breaks auto-rigger | Segment hair from body, rig body-only |
|
||||||
|
|
||||||
|
## Related Skills
|
||||||
|
|
||||||
|
- [Image Generation](image-generation.md) --- create 2D concept art to feed into Tripo
|
||||||
|
- [Concept Art Pipeline](concept-art-pipeline.md) --- full 2D-to-3D workflow
|
||||||
Reference in New Issue
Block a user