Discover prompts, agents, and integrations for Google Gemini.
Also: <a href="https://deepmind.google/models/gemini/image/" rel="nofollow">https://deepmind.google/models/gemini/image/</a>, <a href="https://techcrunch.com/2025/08/26/google-geminis-ai-image-model-gets-a-bananas-upgrade/" rel="nofollow">https://techcrunch.com/2025/08/26/google-geminis-ai-image-mo...</a>
I've been testing Gemini 2.5 Pro with a 180k token codebase context window and the results are remarkable. It correctly traced a bug through 14 files, identified the root cause in a race condition between two services, and suggested a fix that actually worked first try. The 1M token context window is not just a marketing number — it fundamentally changes how you can work with AI on large projects. Has anyone else been stress-testing the context limits?
Complete competitive intelligence framework with market sizing, feature matrices, and strategic recommendations.
Generates a complete REST API with models, endpoints, middleware, and OpenAPI documentation.
A collection of hands-on Generative AI projects built using Google's Gemini API and Google GenAI SDK, progressing from prompt engineering to agentic AI.
Creates a complete interactive web app within Gemini Canvas with responsive design and accessibility.
Advanced document OCR with structured data extraction, classification, and multi-format output.
System prompt for building a research-focused Gemini Gem with citation methodology and evidence grading.
Synthesize multiple documents into a unified analysis with contradiction detection, gap identification, and confidence assessment.
Generates production-ready Google Apps Scripts with triggers, UI, and best practices.
ATS-optimized resume rewriting and tailored cover letter generation for specific job applications.
Official Google study prompts for students using Gemini. Includes prompts for creating study guides, flashcards, step-by-step problem solving, concept explanation, exam preparation, and podcast-style audio discussions of study materials.
Get your product in front of the builders defining the future.
An open-source AI agent that brings the power of Gemini directly into your terminal.
Collection of awesome LLM apps with AI Agents and RAG using OpenAI, Anthropic, Gemini and opensource models.
Stars: 351 Language: Shell
Prompt leak of Google Gemini Pro (Bard version) system prompts, instructions, and guidelines
Stars: 288
Full System Prompt Transparency for All—that aggregates full system prompts, guidelines, and tools from major AI models like ChatGPT, Gemini, Claude, Mistral, Anthropic, xAI, Perplexity, and more. It’s dedicated to exposing hidden AI instructions to build trust through openness.
Stars: 38
import os import json import re import requests import time from bs4 import BeautifulSoup from ddgs import DDGS import litellm from concurrent.futures import ThreadPoolExecutor from urllib.parse import urlparse
class BaseAgent: def init(self, name, role_description, temperature=0.7, primary_model="gemini/gemini-1.5-flash"): self.name = name self.role_description = role_description self.temperature = temperature self.primary_model = primary_model
def _build_system(self, negative_constraints="", positive_examples=""):
parts = [self.role_description]
si = getattr(self, "special_instructions", "")
if si:
parts.append(f"\nSPECIAL INSTRUCTIONS FOR THIS ARTICLE:\n{si}")
if positive_examples:
parts.append(f"\nWHAT WORKED WELL (keep doing this):\n{positive_examples}")
if negative_constraints:
parts.append(f"\nPAST FEEDBACK TO AVOID:\n{negative_constraints}")
return "\n".join(parts)
def execute_task(self, prompt_context, negative_constraints="", positive_examples=""):
print(f" [Agent: {self.name}] Started...")
full_system = self._build_system(negative_constraints, positive_examples)
messages = [{"role": "system", "content": full_system}, {"role": "user", "content": prompt_context}]
for attempt in range(3):
try:
response = litellm.completion(model=self.primary_model, messages=messages, temperature=self.temperature, timeout=180)
return response.choices[0].message.content
except Exception as e:
err = str(e)
is_rate_limit = "rate_limit" in err.lower() or "429" in err or "RateLimitError" in err or "RESOURCE_EXHAUSTED" in err
if is_rate_limit and attempt < 2:
m = re.search(r'retry[^\d]*(\d+(?:\.\d+)?)', err, re.IGNORECASE)
delay = min(int(float(m.group(1))) + 5, 90) if m else 65
print(f" [{self.name}] Rate limit — retrying in {delay}s (attempt {attempt+1}/3)...")
time.sleep(delay)
else:
print(f" Error in {self.name}: {e}")
return f"Agent {self.name} failed: {e}"
def stream_task(self, prompt_context, negative_constraints="", positive_examples=""):
"""Yields cumulative text as LLM generates. Falls back to non-streaming on Gemini repetition loops."""
print(f" [Agent: {self.name}] Streaming...")
full_system = self._build_system(negative_constraints, positive_examples)
messages = [{"role": "system", "content": full_system}, {"role": "user", "content": prompt_context}]
try:
response = litellm.completion(model=self.primary_model, messages=messages,
temperature=self.temperature, timeout=180, stream=True)
full_text = ""
for chunk in response:
delta = chunk.choices[0].delta.content or ""
if delta:
full_text += delta
yield full_text
if not full_text:
yield f"Agent {self.name} returned empty response."
except Exception as e:
err = str(e)
if "repeating the same chunk" in err or "MidStreamFallback" in err:
# Gemini repetition loop — retry non-streaming at slightly higher temperature
print(f" [{self.name}] Repetition loop detected — retrying without streaming...")
try:
fallback_temp = min(self.temperature + 0.2, 0.7)
response = litellm.completion(model=self.primary_model, messages=messages,
temperature=fallback_temp, timeout=180)
yield response.choices[0].message.content
except Exception as e2:
yield f"Agent {self.name} failed: {e2}"
else:
yield f"Agent {self.name} failed: {e}"
def _is_error(text): """Returns True if the text is an agent failure message, not real content.""" if not text: return True t = str(text).strip() return t.startswith("Agent ") and " failed:" in t
COMPETITOR_DOMAINS = [ "thesleepcompany.in", "wakefit.co", "duroflex.com", "sunday.in", "kurlon.com", "sleepycat.in", "wakeup.in", "flo.health", "centuary.in", "morningsleepcompany.com", "peps.in", "springwel.com", ] URL_BLACKLIST = [ "youtube.com", "youtu.be", "reddit.com", "amazon.", "flipkart.", "quora.com", "facebook.com", "instagram.com", "twitter.com", "x.com", "snapchat.com", "tiktok.com", ]
class SERPScraperAgent: """Agent 1: Two-pass DDG search (competitor blogs first, filtered fallback second) + rich page scraping.""" def init(self): self.name = "The SERP Spy"
def _scrape_page(self, url):
"""Scrapes meta description, H1, H2/H3, first 4 paragraphs, bold claims from a URL."""
try:
res = requests.get(url, timeout=5, headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"})
if res.status_code != 200: return {}
soup = BeautifulSoup(res.text, 'html.parser')
meta_desc = ""
meta_tag = soup.find("meta", attrs={"name": "description"}) or soup.find("meta", attrs={"property": "og:description"})
if meta_tag: meta_desc = (meta_tag.get("content") or "")[:200]
h1 = next((h.get_text().strip() for h in soup.find_all('h1')[:1]), "")
headings = [h.get_text().strip() for h in soup.find_all(['h2', 'h3'])[:8] if h.get_text().strip()]
paras = [p.get_text().strip()[:200] for p in soup.find_all('p')[:4] if len(p.get_text().strip()) > 60]
bold = list({b.get_text().strip() for b in soup.find_all(['strong', 'b'])
if 10 < len(b.get_text().strip()) < 120})[:5]
return {"meta": meta_desc, "h1": h1, "headings": headings, "paras": paras, "bold": bold}
except:
return {}
def _ddg_search(self, query, max_results=5):
try:
return DDGS().text(query, max_results=max_results) or []
except:
return []
def _is_junk(self, url):
return any(b in url for b in URL_BLACKLIST)
def execute_task(self, keyword):
print(f" [Agent: {self.name}] Two-pass DDG search...")
collected = []
seen_domains = set()
def _domain(url):
return urlparse(url).netloc.replace("www.", "")
# Pass 1: competitor blog targeting — 1 result per brand
site_filter = " OR ".join(f"site:{d}" for d in COMPETITOR_DOMAINS)
p1_results = self._ddg_search(f"{keyword} ({site_filter})", max_results=8)
for r in p1_results:
d = _domain(r['href'])
if not self._is_junk(r['href']) and d not in seen_domains and len(collected) < 3:
collected.append(r)
seen_domains.add(d)
# Pass 2: generic fallback — fill up to 3 if pass 1 came up short
if len(collected) < 3:
p2_results = self._ddg_search(f"{keyword} India mattress", max_results=10)
seen_urls = {r['href'] for r in collected}
for r in p2_results:
d = _domain(r['href'])
if not self._is_junk(r['href']) and r['href'] not in seen_urls and d not in seen_domains and len(collected) < 3:
collected.append(r)
seen_domains.add(d)
seen_urls.add(r['href'])
if not collected:
return "No real-time SERP data available."
# Scrape each URL in parallel for rich page data
urls = [r['href'] for r in collected]
with ThreadPoolExecutor(max_workers=3) as executor:
page_data = list(executor.map(self._scrape_page, urls))
output = []
for r, pd in zip(collected, page_data):
lines = [f"URL: {r['href']}", f"Title: {r['title']}"]
if pd.get("meta"): lines.append(f"Meta: {pd['meta']}")
if pd.get("h1"): lines.append(f"H1: {pd['h1']}")
if pd.get("headings"):lines.append(f"H2/H3: {' | '.join(pd['headings'])}")
if pd.get("paras"): lines.append(f"Content: {' // '.join(pd['paras'])}")
if pd.get("bold"): lines.append(f"Key claims: {' | '.join(pd['bold'])}")
if not pd: lines.append(f"Preview: {r['body'][:200]}")
output.append("\n".join(lines))
return "\n\n".join(output)
class BrandStrategistAgent(BaseAgent): """Agent 2: Produces a 6-section structured strategy brief.""" def init(self, brand_dna, product_db, tech_glossary, model): system = f"""You are SleepyCat's Senior Brand Strategist. Produce a structured CONTENT STRATEGY BRIEF.
REQUIRED SECTIONS:
BRAND DNA: {brand_dna[:2000]} TECH GLOSSARY: {tech_glossary[:2000]}
RULES:
Use real specs (AirGen™, 5-Zone Ortho, GOLS Latex).
Do not fabricate any features.
Angle must be 'The Art of Rest' vs 'Hustle Culture'.
Section 7 PRODUCT_SLUGS must be valid JSON — the Drafter reads it programmatically.""" super().init("Strategist", system, 0.7, model) self.db = product_db
def execute_task(self, context, neg="", pos=""): return super().execute_task(f"{context}\n\nPRODUCT DB:\n{json.dumps(self.db, indent=1)}", negative_constraints=neg, positive_examples=pos)
def stream_task(self, context, neg="", pos=""): yield from super().stream_task(f"{context}\n\nPRODUCT DB:\n{json.dumps(self.db, indent=1)}", negative_constraints=neg, positive_examples=pos)
class ReviewerPersonaAgent(BaseAgent): """Agent 3: Writes the full 1000-1500 word factual draft.""" def init(self, brand_dna, tech_glossary, model): system = f"""You are SleepyCat's Technical Drafter. Write a complete first draft (1000-1500 words).
BRAND VOICE: Confident, witty, chilled. Never clinical. Use "we". ANTI-JARGON: NEVER use ILD, density, coil count. Use "feel", "materials", "support".
CONTENT FORMULA:
REQUIREMENTS:
GLOSSARY: {tech_glossary[:2000]}""" super().init("Drafter", system, 0.4, model)
def execute_task(self, brief, db, neg="", pos=""):
return super().execute_task(f"STRATEGY BRIEF:\n{brief}\n\nPRODUCT DB:\n{json.dumps(db, indent=1)}", negative_constraints=neg, positive_examples=pos)
def stream_task(self, brief, db, neg="", pos=""):
yield from super().stream_task(f"STRATEGY BRIEF:\n{brief}\n\nPRODUCT DB:\n{json.dumps(db, indent=1)}", negative_constraints=neg, positive_examples=pos)
class SEOEditorAgent(BaseAgent): """Agent 4: Optimizes for AEO snippets without shortening content.""" def init(self, model): system = """You are SleepyCat's SEO Architect. Optimize for Google and AEO. DO NOT SHORTEN.
TASKS:
Final output must be 1000+ words.""" super().init("SEO Architect", system, 0.3, model)
def execute_task(self, draft, keyword, db, neg="", pos=""):
return super().execute_task(f"TARGET: {keyword}\n\nPRODUCT DB:\n{json.dumps(db, indent=1)}\n\nDRAFT:\n{draft}", negative_constraints=neg, positive_examples=pos)
def stream_task(self, draft, keyword, db, neg="", pos=""):
yield from super().stream_task(f"TARGET: {keyword}\n\nPRODUCT DB:\n{json.dumps(db, indent=1)}\n\nDRAFT:\n{draft}", negative_constraints=neg, positive_examples=pos)
class HumanizerAgent(BaseAgent): """Agent 5: Final pass to apply brand soul.""" def init(self, rules, model): system = f"""You are SleepyCat's Senior Editor. Apply final humanizing pass.
RULES: {rules}
class Orchestrator: def init(self, model="gemini/gemini-1.5-flash"): self.base_path = os.path.dirname(os.path.abspath(file)) dna = self._read(os.path.join(self.base_path, "brand_guidelines.txt")) tech = self._read(os.path.join(self.base_path, "sleepycat-tech-glossary.md")) rules = self._read(os.path.join(self.base_path, "humanizer_rules.txt")) raw = self._json(os.path.join(self.base_path, "sleepycat-products.json")) self.products = raw.get("products", []) if isinstance(raw, dict) else raw
# Compact: enough for Strategist to pick the right product type + material + use-case
self.compact_products = [
{
"name": p.get("product_name", ""),
"slug": p.get("slug", ""),
"category": p.get("category", ""),
"material": p.get("key_technologies", p.get("technologies", [])),
"firmness": p.get("firmness", ""),
"best_for": p.get("best_for", ""),
"summary": (p.get("description_short") or p.get("description", ""))[:150],
}
for p in self.products
]
# SEO trim: enough for comparison table + internal links, not full specs
self.seo_products = [
{
"name": p.get("product_name", ""),
"slug": p.get("slug", ""),
"category": p.get("category", ""),
"technologies": p.get("technologies", p.get("key_technologies", [])),
"certifications": p.get("certifications", []),
"firmness": p.get("firmness", ""),
"best_for": p.get("best_for", ""),
}
for p in self.products
]
# Groq free tier: 6K TPM hard limit.
# Drafter: _select_products() (3-5 full specs) on paid; compact on Groq.
# SEO Architect: name+slug only (~700 tokens) on Groq — enough for internal links + table.
self.is_groq = model.startswith("groq/")
self.seo_arch_products = (
[{"name": p.get("product_name", ""), "slug": p.get("slug", "")} for p in self.products]
if self.is_groq else self.seo_products
)
self.serp_agent = SERPScraperAgent()
self.strategist = BrandStrategistAgent(dna, self.compact_products, tech, model)
self.drafter = ReviewerPersonaAgent(dna, tech, model)
self.seo_editor = SEOEditorAgent(model)
self.humanizer = HumanizerAgent(rules, model)
def _read(self, path):
try:
with open(path, "r", encoding="utf-8") as f: return f.read()
except: return ""
def _json(self, path):
try:
with open(path, "r", encoding="utf-8") as f: return json.load(f)
except: return {}
def _select_products(self, brief):
"""Parse PRODUCT_SLUGS from Strategist brief. Returns full-spec products for those slugs.
Falls back to compact_products if parsing fails or no slugs match the DB."""
try:
m = re.search(r'PRODUCT_SLUGS:\s*(\[[\s\S]*?\])', brief)
if not m:
print(" [Orchestrator] No PRODUCT_SLUGS found — compact fallback")
return self.compact_products
slugs = json.loads(m.group(1))
slug_set = {s.lower().strip() for s in slugs if isinstance(s, str)}
selected = [p for p in self.products if p.get("slug", "").lower() in slug_set]
if not selected:
print(f" [Orchestrator] No slug matches for {slugs} — compact fallback")
return self.compact_products
print(f" [Orchestrator] Drafter gets {len(selected)} products: {[p.get('slug') for p in selected]}")
return selected
except Exception as e:
print(f" [Orchestrator] Slug parse error: {e} — compact fallback")
return self.compact_products
def _load_memory(self, agent_name=None):
"""Returns (positives_str, negatives_str) filtered to entries targeting this agent or 'all'."""
try:
p = os.path.join(self.base_path, "agent_memory.json")
if os.path.exists(p):
with open(p, "r") as f: m = json.load(f)
if agent_name:
m = [i for i in m if i.get("target", "all") in ("all", agent_name)]
pos = "\n".join([f"- {i['feedback']}" for i in m[-6:] if i.get('type') == 'positive'])
neg = "\n".join([f"- {i['feedback']}" for i in m[-6:] if i.get('type') == 'negative'])
return pos, neg
return "", ""
except: return "", ""
def run(self, keyword, checkpoint=None, progress_callback=None):
"""Full quality pass with per-agent memory injection. Pass checkpoint to skip completed stages.
progress_callback(agent, status, ctx, out) is called before ("running") and after ("done")
each agent so the UI can highlight the active agent and accumulate token estimates.
"""
start = time.time()
print(f"\n🚀 Pipeline Start: {keyword}")
cp = checkpoint or {}
def _cb(agent, status, ctx="", out=""):
if progress_callback:
progress_callback(agent, status, ctx, out)
serp = cp.get("serp") or self.serp_agent.execute_task(keyword)
if not cp.get("brief"):
pos, neg = self._load_memory("strategist")
ctx = f"TARGET: {keyword}\nSERP: {serp}\n\nPRODUCT DB:\n{json.dumps(self.compact_products, indent=1)}"
_cb("strategist", "running", ctx, "")
brief = self.strategist.execute_task(f"TARGET: {keyword}\nSERP: {serp}", neg=neg, pos=pos)
if _is_error(brief): return brief, round(time.time() - start, 1)
_cb("strategist", "done", ctx, brief)
else:
brief = cp["brief"]
# Select only the products Strategist recommended — Groq stays on compact (6K TPM limit)
drafter_db = self.compact_products if self.is_groq else self._select_products(brief)
if not cp.get("draft"):
pos, neg = self._load_memory("drafter")
ctx = f"STRATEGY BRIEF:\n{brief}\n\nPRODUCT DB:\n{json.dumps(drafter_db, indent=1)}"
_cb("drafter", "running", ctx, "")
draft = self.drafter.execute_task(brief, drafter_db, neg=neg, pos=pos)
if _is_error(draft): return draft, round(time.time() - start, 1)
_cb("drafter", "done", ctx, draft)
else:
draft = cp["draft"]
if not cp.get("opt"):
pos, neg = self._load_memory("seo_architect")
ctx = f"TARGET: {keyword}\n\nPRODUCT DB:\n{json.dumps(self.seo_arch_products, indent=1)}\n\nDRAFT:\n{draft}"
_cb("seo_architect", "running", ctx, "")
opt = self.seo_editor.execute_task(draft, keyword, self.seo_arch_products, neg=neg, pos=pos)
if _is_error(opt): return opt, round(time.time() - start, 1)
_cb("seo_architect", "done", ctx, opt)
else:
opt = cp["opt"]
pos, neg = self._load_memory("humanizer")
_cb("humanizer", "running", opt, "")
final = self.humanizer.execute_task(opt, negative_constraints=neg, positive_examples=pos)
if _is_error(final): return final, round(time.time() - start, 1)
_cb("humanizer", "done", opt, final)
dur = round(time.time() - start, 1)
return final, dur
if name == "main": try: if os.isatty(0): target = input("Target Keyword: ") orchestrator = Orchestrator() content, dur = orchestrator.run(target) print(f"✅ Success in {dur}s") else: print("Non-interactive.") except Exception as e: print(f"Error: {e}")
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
gemma-4-31b to the curated Cerebras provider/model catalog for interactive configuration.minLength / maxLength, while preserving strict local validation after generation.config command now offers a guided, interactive flow built on @clack/prompts for picking a provider + model, entering API keys with masked input, and editing general settings (including locale).MODEL_COMBOS catalog (utils/models.ts) listing supported provider/model combinations that work with structured output, plus a custom "enter any model id" escape hatch per provider.LOCALE_OPTIONS selector so users can choose the PR output language interactively instead of typing the value by hand.tsc --noEmit typecheck script and a corresponding CI step.MODEL to openai/gpt-oss-20b (fast and cheap on Groq).ai to v7.0.2 and provider packages (@ai-sdk/groq v4, @ai-sdk/cerebras v3, @ai-sdk/google v4, @ai-sdk/openai v4), replacing the deprecated system option with instructions.commander to v15.clipboardy with the lighter tinyclip.config set and config get now mask API key values in output, and config files are written with 0o600 permissions to restrict filesystem access.buildGhPrCommand now uses POSIX single-quote escaping so $, backticks, newlines, and embedded quotes in branch names and labels are emitted safely.~/.lazypr configuration.1 so scripts and CI correctly detect failures.DEFAULT_BRANCH casing instead of lowercasing case-sensitive git branch names.gh pr create commands.GOOGLE_GENERATIVE_AI_API_KEY for Google provider authentication.picocolors to Node.js styleText via node:util.styleText is stable starting in Node 21.Array#sort() with Array#toSorted() to avoid array mutation{ cause } when re-throwing for better debuggingnew URL() side-effect validation with URL.canParse()chalk to picocolors for terminal coloring, resulting in a smaller bundle size and faster startup time.utils/shell.ts (escapeShellArg, buildGhPrCommand)utils/prompts.ts for better separation of concernsvalidateOption helper to DRY up locale/context validationselectTargetBranch and selectTemplate helper functions for cleaner main flowPromise.all() for improved performancezod to version 4.3.4generateText for structured object generationlog.warning() which doesn't exist in @clack/prompts. Replaced all 6 instances with the correct log.warn() method.Example: lazypr config set LOCALE=eslazypr config listhttp://localhost:11434/v1), LM Studio (http://localhost:1234/v1), LocalAIOPENAI_API_KEY and OPENAI_BASE_URL configuration options. The API key is optional for local providers that don't require authentication.CUSTOM_LABELS configuration option, allowing users to define their own set of labels for PR generation. Users can now specify any labels used in their project instead of being limited to the default set (enhancement, bug, documentation).@ai-sdk/cerebras, @ai-sdk/groq, ai, zod, and @types/bun to their latest versions.master to main to align with modern Git conventions. Users who previously relied on master as their default can restore it by running lzp config set DEFAULT_BRANCH=master.ai package version to 5.0.106, updating the Biome schema to 2.3.8, and performing general dependency upgrades for improved stability and compatibility.handleGitError function to provide more robust and user-friendly error handling for Git-related failures.config list command to ensure proper functionality and output formatting.displayConfigBadge function to validate configuration badge display across various scenarios.dist/lzp.js and added a postbuild script to generate the lzp.js file for improved build automation.PROVIDER configuration option supports switching providers seamlessly.PROVIDER=cerebras and configuring their CEREBRAS_API_KEY.CEREBRAS_API_KEY configuration option for Cerebras authentication.MODEL setting now accepts any model name supported by your chosen provider, giving users full flexibility.openai/gpt-oss-20b to llama-3.3-70b which works well across multiple providers.groq.ts to a generic provider.ts module, enabling easy addition of future providers.list subcommand for configuration management, allowing users to view all current configuration settings with their statuses. Sensitive values (like API keys) are automatically masked for security.--context (-c) flag or the CONTEXT configuration key. This allows users to influence the tone, style, and structure of the generated PR content (e.g., "make it simple and cohesive", "be more technical"). Context is limited to 200 characters maximum.noFilter option with clearer filter parameter for improved code clarity and consistency.bunx and removed redundant 'public' flag.mock from bun:test).LABEL_COLORS.bug, etc.) instead of array indexing.DEFAULT_BRANCH to align with the renamed target argument.ai and zod dependencies.v1.2.1 package on the npm registry. No new code changes were introduced in this release.child_process.exec with the safer child_process.execFile for executing Git commands, fully eliminating the reliance on shell interpretation.1) when a configuration error occurs, ensuring better pipeline and script integration.description, author) in package.json and removed deprecated scripts (test, test:watch, build:standalone).--gh flag to automatically generate a complete gh pr create command using the AI-generated title, description, and labels. This command is then copied to the clipboard, streamlining the process for users who deploy PRs with the GitHub CLI.docs:, test:, chore:) are now excluded from the prompt sent to the AI.FILTER_COMMITS configuration option (default true) and the --no-filter CLI flag to disable this feature.enhancement, bug, documentation) based on the changes in the commits, which are included in the generated output and the new gh pr create command.PULL_REQUEST_TEMPLATE.md). The AI now automatically detects and uses the structure and content of this template to format the generated PR description, allowing users to enforce consistent and custom documentation standards. (#7)--locale (-l) flag to the main command. This allows users to explicitly request that the AI generate the PR title and description in a specified language (e.g., Italian, Spanish, German), enabling localized output. (#9)child_process.exec with child_process.execFile in the getPullRequestCommits function. This prevents shell interpretation of commands, mitigating potential command injection risks.
[]) instead of throwing an error. This prevents unexpected crashes during PR generation. (30edcdf)remove subcommand to the config command, allowing users to easily delete a configured key from the .lazypr file. (e1c5318)Inquirer) to @clack/prompts for a modern, consistent, and performant command-line user experience. (#5)
MODEL configuration option in the config file (.lazypr). This allows users to specify and use custom large language models (LLMs) for pull request generation. (#3)Initial public release of lazypr.
Auto Game Builder is a portable, open-source developer automation platform designed to manage the full lifecycle of multiple software applications from a single interface. It combines a FastAPI REST backend with a Flutter mobile app and exposes its API remotely via a Cloudflare Tunnel, enabling control from a mobile device anywhere.
The system targets solo or small-team developers who maintain several apps simultaneously (Flutter, Godot, Python, Web) and want to automate repetitive tasks — building, fixing bugs, deploying, and iterating — using AI agents.
Mobile App ──► Cloudflare Worker Proxy
│
▼
Cloudflare Tunnel
│
▼
┌───────────────────────────────┐
│ FastAPI REST API (Python) │
│ server/api/server.py │
│ │
│ ┌──────────────────────┐ │
│ │ AutoFix Engine │ │
│ │ Deploy Engine │ │
│ │ Pipeline Engine │ │
│ │ Internet Monitor │ │
│ └──────────────────────┘ │
│ │ │
│ SQLite Database │
└───────────────────────────────┘
| Component | Description |
|---|---|
server/api/server.py | FastAPI REST API. Core orchestration layer. |
server/core/autofix_engine.py | Queues and processes issues automatically via AI agents. |
server/core/deploy_engine.py | Builds and uploads artifacts to Google Play or other targets. |
server/core/pipeline_engine.py | Asset pipeline for processing game/app resources. |
server/core/internet_monitor.py | Polls connectivity; gates AI actions behind internet availability. |
server/database/db_manager.py | SQLite abstraction layer. |
server/database/models.py | ORM models: App, Build, Task, etc. |
server/automations/ | Per-app automation shell scripts and config (configs.json). |
server/config/ | MCP server definitions, per-app MCP assignments, settings. |
app/ | Flutter mobile companion app. |
| Type | Build Targets | Notes |
|---|---|---|
flutter | APK, AAB, EXE, Web, iOS | Reads version from pubspec.yaml. |
godot | APK, AAB, Windows, Web, Linux | Reads version from export_presets.cfg. |
python | — | Managed for automation/task tracking. |
web | Web | Static or server-rendered. |
slug, project folder, initial tasklist.json, and a pre-populated CLAUDE.md with type-specific conventions.status, publish_status, current_version, package_name, project_path, github_url, play_store_url, website_url, console_url.idle, building, fixing.development, internal, alpha, beta, production.building or fixing (from a crash) is automatically reset to idle.internal, alpha, beta, production).psutil.running build records from previous crashes are automatically marked failed on startup.title, description, category (bug/feature/etc.), priority (1–5), source, and optional assigned_ai.tasklist.json file in its project folder.issue, idea, feature, fix.pending, in_progress, partial, completed, built, divided, failed, archived.task_attachments/).task_archives/).os.replace) with .bak backup to prevent corruption.type=idea that have an AI response.ai_agent (claude/gemini/codex), interval_minutes, max_session_minutes, prompt, and mcp_servers.{slug}_auto.sh) is auto-generated from the config and lives in server/automations/.ai_tool, status, exit_code, duration_seconds, files_changed, and timestamps.server/config/mcp_servers.json.server/config/app_mcp.json).mcp_config.json is generated in the app's project folder and passed to the AI agent.mcp_config_path.gdd.md (Game/App Design Document) — editable via API and mobile app.CLAUDE.md — the AI instruction file, pre-populated with type-specific rules and editable via API.InternetMonitor periodically polls a configurable URL (default: api.anthropic.com) to verify connectivity.internet_check_interval).auto_build_logs/completions.log within each project folder.app_name, app_id, level (info/success/warning/error), source (agent name), message, and timestamp./api/logs endpoint aggregates logs across all apps./api/dashboard endpoint returns a summary of all apps: status, publish status, version, and open issue count.| Model | Key Fields |
|---|---|
App | id, name, slug, app_type, status, publish_status, current_version, package_name, project_path, fix_strategy, mcp_config_path, automation_script_path, github_url, play_store_url, website_url, console_url, group_name, icon_path |
Issue | id, app_id, title, description, category, priority, status, source, assigned_ai, fix_prompt, fix_result |
Build | id, app_id, build_type, version, status, output_path, duration_seconds, started_at, completed_at |
Session | id, app_id, issue_id, ai_tool, status, exit_code, duration_seconds, error_message, files_changed, started_at, completed_at |
Settings | Key-value store for global configuration (loaded from server/config/settings.json). |
| Method | Path | Description |
|---|---|---|
| GET | /api/apps | List all apps |
| POST | /api/apps | Create app (generates folder, CLAUDE.md, tasklist.json, DB entry) |
| PATCH | /api/apps/{id} | Update app metadata |
| GET/PUT | /api/apps/{id}/mcp | Get/set per-app MCP servers |
| POST | /api/apps/{id}/deploy | Trigger build + optional Play Store upload |
| POST | /api/apps/{id}/deploy/cancel | Cancel active build |
| POST | /api/apps/{id}/deploy/retry-upload | Re-upload last AAB |
| GET | /api/apps/{id}/tasks | List per-app tasks |
| POST | /api/apps/{id}/tasks | Add task (with optional image attachments) |
| PATCH | /api/apps/{id}/tasks/{task_id} | Update task |
| DELETE | /api/apps/{id}/tasks/{task_id} | Delete task |
| GET/PUT | /api/apps/{id}/gdd | Read/write GDD document |
| GET/PUT | /api/apps/{id}/claude-md | Read/write CLAUDE.md |
| POST | /api/apps/{id}/enhance | AI-enhance GDD or CLAUDE.md (async) |
| GET | /api/apps/{id}/enhance/status | Poll enhance job status |
| GET/POST | /api/issues | List/create issues (auto-queues autofix) |
| GET | /api/sessions | List AI fix sessions |
| GET | /api/builds | List build records |
| GET | /api/logs | Unified log feed across all apps |
| GET | /api/ideas | All tasks of type idea with AI responses |
| GET | /api/dashboard | Global summary |
| GET | /api/health | Health check |
| Item | Location |
|---|---|
| Database | server/app_manager.db |
| Settings | server/config/settings.json |
| App projects | Configurable via projects_root in settings |
| Task list | {project_path}/tasklist.json |
| Design document | {project_path}/gdd.md |
| AI instructions | {project_path}/CLAUDE.md |
| Task archives | {project_path}/task_archives/ |
| Task attachments | {project_path}/task_attachments/{task_id}/ |
| Build artifacts | {project_path}/build/ (engine-managed) |
| Build logs | {project_path}/auto_build_logs/completions.log |
| MCP config (per app) | {project_path}/mcp_config.json |
| Automation scripts | server/automations/{slug}_auto.sh |
| Automation configs | server/automations/configs.json |
| MCP server registry | server/config/mcp_servers.json |
| Per-app MCP assignments | server/config/app_mcp.json |
| Signing keys | Configurable via keys_dir in settings |
| Integration | Purpose |
|---|---|
| Cloudflare Tunnel | Exposes local API to mobile app over HTTPS without port forwarding |
| Cloudflare Worker | Proxy layer that routes mobile requests to the tunnel |
| Google Play Console | Build upload and track management |
| Claude (Anthropic) | Primary AI agent for autofix, automation, and document enhancement |
| Gemini (Google) | Secondary AI agent option for automation |
| Codex (OpenAI) | Tertiary AI agent option for automation |
| PixelLab | Pixel art generation for games (MCP + Python SDK) |
| ElevenLabs | Sound effects and music generation (MCP) |
| GitHub | Source control link per app (URL stored, not managed directly) |
You are a Content Strategist Gem, an expert in planning, creating, and optimizing content that serves both business goals and audience needs.
Your role: Help teams develop content strategies that drive measurable results — traffic, engagement, conversion, and retention.
Your expertise:
How you communicate:
Rules:
Ready-to-use automation templates from the marketplace



