Files
blog/posts/studio-cli.md
T

94 lines
6.9 KiB
Markdown
Raw Normal View History

---
title: "One Binary to Rule Them All: Building a Studio CLI"
slug: studio-cli
date: "2026-05-18"
description: "We built tinqs-cli --- a single Go binary that handles machine identity, screenshots, cloud vision, health checks, and agent coordination across every machine in the studio."
og_description: "A single Go binary for machine identity, screenshots, cloud vision, and agent coordination."
og_image: "https://www.tinqs.com/img/og-cover.jpg"
excerpt: "tinqs-cli is a single Go binary that handles machine identity, screenshots, cloud vision, health checks, and agent coordination. One install, every machine, human or AI."
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, runs health checks, and coordinates AI agents. This is how we built tinqs-cli.
## Why Build a CLI
When you have 9 machines across 5 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. We had a `setup.sh` for Mac, a `setup.ps1` for Windows, a `check-services.sh` for health, and 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 `tinqs-cli 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:
- **Who you are.** The SOUL --- the agent's persistent identity, values, and operating principles.
- **What company this is.** Team members, roles, contact info.
- **What machine you're on.** Hostname, OS, which repos are cloned, what services are running.
- **What siblings exist.** Other repos in the ecosystem and their purpose.
- **What URLs are live.** Git platform, game server, bot, gateway --- with reachability status.
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. `tinqs-cli identity` gives it full context in one call.
The data lives in markdown files in the docs repo. The CLI reads them over the network via a private Tailscale mesh --- the docs repo is the source of truth, and any machine on the mesh can read it.
## Screenshots and Vision
`tinqs-cli screenshot --window "Ariki"` captures the game 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).
`tinqs-cli photo --window "Ariki"` does the same thing but sends the screenshot to Amazon Bedrock's Nova Lite model for analysis. The agent says "take a photo of the game" and gets back a description of what's on screen: "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 our CTO files bugs without typing. He looks at the game, tells 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
`tinqs-cli doctor` runs a comprehensive health check across the studio:
- Is Tailscale connected? (Required for all inter-machine communication)
- Is the git platform reachable? Can we authenticate?
- Is the game simulation server running?
- Is the bot service responding?
- Are all expected repos cloned and on the right branch?
- Is the Go version correct? Is Node.js installed?
The output is a green/yellow/red table. If something's wrong, the agent knows immediately and can diagnose or escalate.
## Cross-Machine Coordination
The studio has machines in London, and a server in AWS eu-west-1. They're connected via a Tailscale mesh network. tinqs-cli uses this mesh for everything --- reading identity files, checking service health, even routing agent commands.
When the CTO is on the Windows machine (Forge) and needs to check something on the Mac (Kraken), the agent doesn't SSH. It uses tinqs-cli to query the relevant service over Tailscale. The mesh is flat --- every machine can reach every other machine by hostname.
## Installation
One command per platform:
- **Windows:** `irm https://bot.arikigame.com/cli/install.ps1 | iex`
- **Mac/Linux:** `curl -fsSL https://bot.arikigame.com/cli/install.sh | sh`
The install script downloads the latest binary from S3, places it in the PATH, and verifies the checksum. Updates are the same command --- idempotent, no package manager required.
## 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 the CTO's gaming PC, the designer's MacBook, and the CI runner in AWS.
Cross-compilation is trivial. We build Windows, Mac (arm64 + amd64), and Linux binaries from a single GitHub Actions workflow. The release process is: 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, tinqs-cli 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.
**Tailscale makes networking disappear.** We spent zero time on VPN configuration, port forwarding, or firewall rules. Install Tailscale, join the mesh, done. Every machine is addressable by hostname. The CLI doesn't need to know about IPs, DNS, or network topology.
**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.
---
tinqs-cli is at v0.3.1 and growing. Every time we find ourselves writing a script that needs to work on multiple machines, we add a subcommand instead. The goal is simple: one binary that makes the studio work, whether the operator is human or AI.