I Built an AI Holding Company That Runs From My Phone

ยท 10 min read
aiautomationtelegramindie-hackingclaude

I Built an AI Holding Company That Runs From My Phone

Two days ago I had an idea. What if I could run an entire portfolio of software products from Telegram? Not manage them. Run them. Scout ideas, approve them, build them, deploy them, launch them. All from my phone, all with AI doing the actual work.

48 hours later, it works.

What I built

The system is simple. I send a Telegram message. A bot on a $25/month VM in Mumbai picks it up, spawns Claude Code, and Claude writes real code, pushes to GitHub, deploys to Cloud Run, updates Notion, and reports back.

flowchart LR A["๐Ÿ“ฑ Telegram\n(You)"] -->|command| B["๐Ÿค– Bot\n($25/mo VM)"] B -->|spawns| C["๐Ÿง  Claude Code\n(--print mode)"] C -->|pushes| D["๐Ÿ“ฆ GitHub"] C -->|deploys| E["โ˜๏ธ Cloud Run"] C -->|updates| F["๐Ÿ““ Notion"] C -->|reports back| A style A fill:#1a1a2e,stroke:#e94560,color:#fff style B fill:#1a1a2e,stroke:#0f3460,color:#fff style C fill:#1a1a2e,stroke:#533483,color:#fff style D fill:#1a1a2e,stroke:#e94560,color:#fff style E fill:#1a1a2e,stroke:#0f3460,color:#fff style F fill:#1a1a2e,stroke:#533483,color:#fff

Here is the actual workflow:

  1. I type /approve AI storybook generator for kids in Telegram
  2. The bot creates a GitHub repo, writes a SKILL.md file that describes the product, creates a Notion entry, and tells me what to build first
  3. I type /work storybook-generator
  4. Claude reads the SKILL.md, picks up where it left off, writes code, commits after every milestone, deploys, updates the SKILL.md with what to do next, and updates Notion
  5. I type /work storybook-generator again. It picks up from where it stopped
  6. When it's ready, I type /launch storybook-generator and get a full launch package: Product Hunt copy, Twitter thread, LinkedIn post, cold email template, SEO keywords
flowchart TD subgraph IDEA ["๐Ÿ’ก Ideation"] S["/scout\nFind ideas from\nideabrowser.com"] end subgraph INIT ["โœ… Initialize"] AP["/approve idea\nGitHub repo + SKILL.md\n+ Notion entry"] end subgraph BUILD ["๐Ÿ”จ Build (repeat)"] W1["/work product\nSession 1: Scaffold"] W2["/work product\nSession 2: Core features"] W3["/work product\nSession 3: UI + deploy"] end subgraph SHIP ["๐Ÿš€ Ship"] DNS["/dns product\nSubdomain + SSL"] L["/launch product\nPH, Twitter, Reddit,\nemail, SEO"] end S --> AP --> W1 --> W2 --> W3 --> DNS --> L style IDEA fill:#0d1117,stroke:#238636,color:#c9d1d9 style INIT fill:#0d1117,stroke:#1f6feb,color:#c9d1d9 style BUILD fill:#0d1117,stroke:#a371f7,color:#c9d1d9 style SHIP fill:#0d1117,stroke:#f78166,color:#c9d1d9

Each /work session is stateless. Claude Code starts fresh every time. The trick is SKILL.md. It lives in the repo and acts as the memory between sessions. It tracks what's done, what's next, what decisions were made, and what's broken. Every session reads it at the start and updates it at the end.

flowchart TD SKILL["๐Ÿ“‹ SKILL.md\n\nstatus: building\nWhat's Next: Add payments\nCurrent State: โœ… scaffold โœ… core โฌœ stripe\nDecisions: Next.js + Tailwind\nChangelog: 3 sessions logged"] READ["1๏ธโƒฃ Read SKILL.md\nUnderstand current state"] WORK["2๏ธโƒฃ Do the work\nBuild what 'What's Next' says"] COMMIT["3๏ธโƒฃ Checkpoint commits\nSave progress incrementally"] UPDATE["4๏ธโƒฃ Update SKILL.md\nCheck off items, set new 'What's Next'"] PUSH["5๏ธโƒฃ Push + update Notion\nSync everything"] SKILL --> READ --> WORK --> COMMIT --> UPDATE --> PUSH --> SKILL style SKILL fill:#161b22,stroke:#f78166,color:#c9d1d9,stroke-width:3px style READ fill:#0d1117,stroke:#388bfd,color:#c9d1d9 style WORK fill:#0d1117,stroke:#388bfd,color:#c9d1d9 style COMMIT fill:#0d1117,stroke:#388bfd,color:#c9d1d9 style UPDATE fill:#0d1117,stroke:#388bfd,color:#c9d1d9 style PUSH fill:#0d1117,stroke:#388bfd,color:#c9d1d9

The hard problems I solved

Notion MCP doesn't work in headless mode. Claude Code's --print flag runs without a terminal. Notion's MCP server requires OAuth, which requires a browser. I spent hours debugging SSH port forwarding for OAuth callbacks before realizing this was a dead end. The fix was simple: pass the Notion API token as an environment variable and tell Claude to use curl. Works perfectly.

flowchart LR subgraph BROKEN ["โŒ MCP Approach (doesn't work)"] direction TB B1["claude --print"] --> B2["MCP Server"] B2 --> B3["OAuth Flow"] B3 --> B4["๐Ÿšซ Needs browser\nNo terminal = no auth"] end subgraph WORKS ["โœ… Direct API (works)"] direction TB W1["claude --print"] --> W2["$NOTION_TOKEN\nin env vars"] W2 --> W3["curl Notion API"] W3 --> W4["โœ… Headless\nNo browser needed"] end style BROKEN fill:#1c0a0a,stroke:#f85149,color:#c9d1d9 style WORKS fill:#0a1c0a,stroke:#238636,color:#c9d1d9

15-minute timeouts killed builds mid-work. Claude Code was building a product, getting 80% through, then the process would get SIGTERM'd. Exit code 143. Nothing was saved because all the git commits happened at the end. I fixed this two ways: bumped the timeout to 30 minutes, and more importantly, told Claude to commit after every checkpoint. Scaffold the project, commit. Build core features, commit. Add styling, commit. Now if it times out, the progress is on GitHub.

gantt title Before: All commits at the end (lost on timeout) dateFormat X axisFormat %s section Work Scaffold :a1, 0, 3 Core features :a2, 3, 8 UI/Styling :a3, 8, 12 โš ๏ธ TIMEOUT (code 143) - all work lost :crit, a4, 12, 15 section Commits (none saved) :milestone, 15, 0
gantt title After: Checkpoint commits (progress survives timeout) dateFormat X axisFormat %s section Work Scaffold :a1, 0, 3 Core features :a2, 3, 8 UI/Styling :a3, 8, 12 Deploy :a4, 12, 20 Update SKILL :a5, 20, 22 section Commits commit 1 :milestone, m1, 3, 0 commit 2 :milestone, m2, 8, 0 commit 3 :milestone, m3, 12, 0 commit 4 :milestone, m4, 20, 0 commit 5 :milestone, m5, 22, 0

No visibility into running jobs. I'd send /work and then stare at silence for 15 minutes wondering if it was working or stuck. I added a progress parser that watches Claude Code's stdout for keywords like "cloning", "npm install", "deploying" and sends real-time status updates back to Telegram. I also added a /jobs command that shows what's currently running, how long it's been going, and the last 5 errors.

Secrets management for a headless bot. The bot needs API keys for Anthropic, GitHub, Notion, Stripe, Cloudflare, and Telegram. All stored in GCP Secret Manager, loaded at startup, and injected as environment variables into every Claude Code process. Adding a new integration means adding one secret and one line of code.

What actually works today

The bot runs as a systemd service on a GCE VM. It survives reboots. It has 14 commands. The full lifecycle works: scout ideas, approve them, build iteratively, deploy to Cloud Run, map custom subdomains on ani.computer, generate launch materials.

mindmap root(("ani.computer\nHQ")) ๐Ÿ’ก Ideation /scout Scrape ideabrowser Filter by criteria Return top 3 ๐Ÿ”จ Build /approve idea GitHub repo SKILL.md Notion entry /work product Read SKILL.md Build next chunk Checkpoint commits /update product issue Fix bugs Redeploy ๐Ÿš€ Ship /dns subdomain Cloudflare CNAME Cloud Run mapping Auto SSL /launch product Product Hunt Twitter thread LinkedIn post Cold email SEO keywords ๐Ÿ“Š Monitor /status Uptime + API calls /jobs Active sessions Recent errors /cancel Kill stuck jobs

Products get their own subdomain automatically. I type /dns storybook-generator and it creates a Cloudflare CNAME record and a Cloud Run domain mapping. SSL provisions automatically. The product is live at storybook-generator.ani.computer within 30 minutes.

Everything syncs to Notion. When I approve an idea, it creates a Notion entry. When I build, it updates the status. I can open Notion on my phone and see the state of every product without asking the bot.

The whole codebase is 6 files. Gateway (command routing), executor (process management), prompts (all the AI instructions), secrets (GCP Secret Manager), DNS (Cloudflare API), and a cron endpoint for future scheduled tasks.

flowchart TB subgraph VM ["GCE VM - $25/mo - Mumbai"] GW["gateway.js\n14 commands\nTelegram routing"] EX["executor.js\nProcess manager\nJob tracking"] PR["prompts.js\n6 personas\n10+ prompt templates"] SE["secrets.js\nGCP Secret Manager\n10 secrets"] DN["dns.js\nCloudflare API\nSubdomain CRUD"] CR["cron-endpoint.js\nScheduled tasks\nPort 3000"] end TG["๐Ÿ“ฑ Telegram"] <--> GW GW --> EX GW --> DN GW --> SE EX --> PR EX --> CC["๐Ÿง  Claude Code CLI"] CC --> GH["GitHub"] CC --> RUN["Cloud Run"] CC --> NO["Notion API"] DN --> CF["Cloudflare"] SE --> GSM["GCP Secret Manager"] style VM fill:#0d1117,stroke:#30363d,color:#c9d1d9 style TG fill:#0088cc,stroke:#0088cc,color:#fff style CC fill:#6e40c9,stroke:#6e40c9,color:#fff

What I learned

SKILL.md is the real invention here. Not the bot. Not the Telegram integration. The persistence layer. Each product has a single markdown file that contains everything Claude needs to pick up where it left off. It's a YAML frontmatter block with status, stack, and metadata, followed by sections for architecture, current state, what's next, decisions made, known issues, and a changelog. It turns stateless AI into an iterative builder.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  SKILL.md                                       โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                 โ”‚
โ”‚  ---                                            โ”‚
โ”‚  name: storybook-generator          (slug)      โ”‚
โ”‚  status: building                   (state)     โ”‚
โ”‚  domain: storybook.ani.computer     (URL)       โ”‚
โ”‚  repo: ani-computer/storybook       (code)      โ”‚
โ”‚  stack: Next.js, Tailwind, TS       (tech)      โ”‚
โ”‚  ---                                            โ”‚
โ”‚                                                 โ”‚
โ”‚  ## What It Is                      (pitch)     โ”‚
โ”‚  AI-powered storybook generator...              โ”‚
โ”‚                                                 โ”‚
โ”‚  ## Current State                   (progress)  โ”‚
โ”‚  โœ… Project scaffolded                          โ”‚
โ”‚  โœ… Core functionality                          โ”‚
โ”‚  โฌœ UI/UX complete                              โ”‚
โ”‚  โฌœ Stripe integration                          โ”‚
โ”‚                                                 โ”‚
โ”‚  ## What's Next                     (the key)   โ”‚
โ”‚  Build the story editor UI.                     โ”‚
โ”‚  Add character selection.                       โ”‚
โ”‚  Connect to image generation API.               โ”‚
โ”‚                                                 โ”‚
โ”‚  ## Decisions Made                  (context)   โ”‚
โ”‚  - Using GPT-4o for story gen                   โ”‚
โ”‚  - Stable Diffusion for images                  โ”‚
โ”‚                                                 โ”‚
โ”‚  ## Known Issues                    (bugs)      โ”‚
โ”‚  - Image gen slow on long stories               โ”‚
โ”‚                                                 โ”‚
โ”‚  ## Changelog                       (history)   โ”‚
โ”‚  - 2026-02-22: Session 1 - scaffold             โ”‚
โ”‚  - 2026-02-22: Session 2 - core gen             โ”‚
โ”‚                                                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Headless AI needs different patterns than interactive AI. MCP, OAuth, browser-based auth flows all assume a human is sitting at a terminal. When you're spawning AI processes from a bot, you need env vars, direct API calls, and explicit instructions. Every tool integration follows the same pattern: get an API token, store it in Secret Manager, inject it as an env var, and tell Claude how to use it via curl in the system prompt.

flowchart LR subgraph PATTERN ["Adding Any New Tool"] direction TB P1["1. Get API token\nfrom the service"] P2["2. Store in GCP\nSecret Manager"] P3["3. Inject as env var\nin executor.js"] P4["4. Add curl examples\nto system prompt"] P1 --> P2 --> P3 --> P4 end P4 --> EX1["Notion โœ…"] P4 --> EX2["Stripe โœ…"] P4 --> EX3["Cloudflare โœ…"] P4 --> EX4["Any API ๐Ÿ”œ"] style PATTERN fill:#0d1117,stroke:#58a6ff,color:#c9d1d9

Timeouts are a feature, not a bug. A 30-minute timeout forces the AI to scope its work. It can't boil the ocean in one session. It has to pick a chunk, do it well, commit, and leave clear instructions for the next session. This is actually better than giving it unlimited time.

The numbers

Total build time: 2 days of focused work across 4 sessions.

Infrastructure cost: $25/month for the VM. Claude API costs are roughly $0.10-0.50 per /work session depending on complexity. Cloud Run and Cloudflare DNS are free tier.

Lines of code: about 1,200 across 6 files.

Time from idea to first working /work session that built and committed real code: about 8 hours.

Monthly Cost Breakdown
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
GCE VM (e2-medium, Mumbai)    $25.00  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ
Claude API (~30 sessions)      $9.00  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ
Cloud Run                      $0.00  (free tier)
Cloudflare DNS                 $0.00  (free)
GCP Secret Manager             $0.06
                              โ”€โ”€โ”€โ”€โ”€โ”€
Total                         ~$34/mo
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

What's next

The system works. Now I need to use it. The goal is simple: ship one product per week, each on its own subdomain, each tracked in Notion, each built entirely through Telegram commands.

The first product is already approved and in progress. The SKILL.md is written. The next /work session will pick it up.

I'm one person running a holding company from my phone. The AI does the building. I do the deciding.


Built in 48 hours. 6 files. $34/month. One founder, zero employees, unlimited products.