# OpenHelm OpenHelm is an operating system for AI agents. Its first template grows and looks after a live product: agents build a keyword plan from Google Keyword Planner data, write and publish posts to the product’s own repository, keep pages indexed through Google Search Console, make the product easy for AI answer engines to cite, map user journeys from GA4 and turn stalls into tasks, fix production bugs reported by Sentry or by customers (verified in production before the issue is resolved), and answer customer email with risky replies held for human approval. Agents run on the user’s own Claude Code or Codex subscription, on a local model such as Gemma through Ollama, or on hosted models billed from plan credits. It is used in the browser at www.app.openhelm.ai or as a macOS app. Made by Maxed Labs Ltd in the UK. # What the agents do ## AI SEO that does the work itself. Source: https://www.openhelm.ai/seo A team of AI agents runs your SEO week after week. They build a keyword plan from real search data, write and publish the posts, fix what stops pages being indexed, and report what moved. ### What AI SEO means here AI SEO usually means a tool that suggests keywords or scores a draft, and then waits for you. Here it means AI agents that do the whole job: they research, write, publish, check and report, on a schedule, without you starting each step. You still set the direction. The agents work from a keyword plan you can read and change, and anything risky waits for your approval. ### How it works 1. **A keyword plan from real data.** A strategist agent pulls volumes and competition from Google Keyword Planner, groups the terms into pillars and clusters, and keeps the plan in a table you can edit. 2. **Posts written and published.** A publisher writes against the plan, commits the post to your site’s repository and pushes it. A follow-up job checks the page is live before it is logged. 3. **Indexing kept healthy.** Technical checks run weekly. When a fix lands, the agent resubmits your sitemap in Search Console, which is the honest route Google offers. 4. **A weekly report you can trust.** Clicks, impressions, CTR and position come straight from Search Console and are written back against each post, so you see which ones earn. ### What it will not do - It does not buy links or run outreach for backlinks. - It cannot ask Google to index a single URL on demand. Google offers no public API for that, so it resubmits your sitemap instead. - It will not publish a post it cannot verify is live. A failed deploy is reported, not logged as done. ### Questions **Where does the keyword data come from?** Google Ads Keyword Planner, through a Google connection you authorise. Rankings and clicks come from your own Search Console property. **Does it need access to my code?** For publishing, yes: posts are committed to your site’s repository. Everything else, such as research and reporting, works without it. **How is this different from an SEO tool?** Tools give you data and a to-do list. These agents do the items on the list and then check they worked. **Can I stop it publishing on its own?** Yes. Set the publisher to open a pull request instead of pushing, or hold posts for approval. ## Autoblogging you would put your name to. Source: https://www.openhelm.ai/autoblogging Autoblogging has a bad name because most of it is spam. This is the other kind: posts written against a keyword plan, published to your own site, checked, indexed and rewritten when they stop earning. ### What autoblogging is Autoblogging is software that writes and publishes blog posts without a person doing each step. Done badly, it floods a site with thin pages that search engines learn to ignore. Done well, it is a writer that never misses a week, follows a plan, links posts together properly and goes back to fix the ones that are not working. ### How it works 1. **Pick the next post from the plan.** The publisher reads your keyword plan and chooses the next topic, respecting a weekly budget so quality does not slip. 2. **Read before writing.** It reads existing posts on your site first, so the new one matches your format, tone and components. 3. **Write, check, commit.** The draft is checked for AI tells, its frontmatter is validated, and it is committed and pushed to your repository. 4. **Confirm it is live and log it.** A chained job waits for the deploy, requests the page, and only then records it in the content log. 5. **Measure and refresh.** Search Console numbers are written back weekly. Posts that stop earning are refreshed or pruned. ### What it will not do - It will not invent statistics, studies or customer quotes to pad a post. - It does not publish to a platform you do not own. Posts live in your repository. - A post is only logged once the live page returns successfully. ### Questions **Will Google penalise AI-written posts?** Google’s guidance is about helpfulness, not authorship. The risk is thin, repetitive content, which is exactly what the plan, the budget and the refresh cycle are there to avoid. **Which site frameworks does it work with?** Any site whose posts live as files in a Git repository, such as Next.js, Astro, Hugo or Jekyll. It reads your existing posts to learn the format. **How many posts a week?** You choose. Most products start with one or two a week and raise it once the posts are earning. **Can I review each post first?** Yes. Have the publisher open a pull request, and merge when you are happy. ## Generative engine optimization, done for you. Source: https://www.openhelm.ai/ai-visibility People now ask ChatGPT, Perplexity and Google’s AI Overviews before they search. Agents make your product easy for those engines to read and cite, then check whether it is being cited. ### What generative engine optimization is Generative engine optimization (GEO) is the work of getting a product mentioned and cited in AI-generated answers. It overlaps with SEO, because answer engines lean on search indexes, but it rewards different things: clear entities, citable facts, structured data and pages that answer a question directly. AI visibility is how you measure it: for the questions your buyers ask, how often is your product named or linked? ### How it works 1. **Audit what engines can read.** An agent checks llms.txt, JSON-LD, AI crawler access in robots.txt, heading structure and authorship signals across your site. 2. **Fix what it finds.** Missing schema, blocked crawlers and unclear pages are fixed in your repository, with the change recorded. 3. **Write answers worth citing.** Guides and comparison pages lead with a direct answer, a table and a date, the shape answer engines lift. 4. **Track citations.** Where an answer-engine connection exists, the agent asks the questions in your plan and records whether you were cited and who was. ### What it will not do - No one can guarantee an AI engine will cite you. The agents improve the odds and measure the result. - Citation tracking needs a connection to the engines you want to track. Without one, the job says it is blocked rather than guessing. - It does not generate fake reviews or mentions on other sites. ### Questions **Is GEO different from SEO?** It builds on SEO. Answer engines use search indexes to find sources, so indexing still matters, but they reward direct answers, clear entities and structured data more than classic ranking signals do. **Does llms.txt help?** It is cheap to publish and some tools read it, but no major engine has confirmed it affects citations. We publish it and do not oversell it. **Which engines can it track?** Whichever you connect. The job is written to work with any answer engine you have access to through a connection. ## A customer journey map that keeps itself up to date. Source: https://www.openhelm.ai/user-funnels An agent maps the journeys that matter in your product, watches each step in your analytics, and turns the places people get stuck into tasks with the evidence attached. ### What a customer journey map is A customer journey map is the sequence of steps people take from first visit to getting value, and eventually paying. Each step is a place they can drop out. Most teams draw one once, in a workshop, and never look at it again. Here the map is built from the product itself and your GA4 events, and it is checked every week. ### How it works 1. **Map the key journeys.** The journey analyst reads your product and its events and proposes the journeys that matter, such as sign up to first project. 2. **Make sure it can measure.** If a live product has no analytics, a task is filed. OpenHelm can create a GA4 property and wire the measurement ID into your deployment. 3. **Watch each step.** Funnel, retention and audience numbers are pulled into tables and charts you can read. 4. **Turn stalls into tasks.** Where people drop off, the agent files a task that says where, how many, and what it thinks is happening. ### What it will not do - It reads your analytics. It does not record sessions or fingerprint users. - A journey with no events behind it is shown as unmeasured, never as healthy. ### Questions **Do I need GA4?** The analyst works from GA4 today. If your product has no analytics at all, OpenHelm files a task and can set GA4 up for you. **What happens to a stall it finds?** It becomes a task with the evidence. You can fix it yourself, or hand it to the engineering agent. **How often does it look?** Weekly by default. You can change the schedule like any other job. ## An AI coding agent that fixes what your users hit. Source: https://www.openhelm.ai/bug-fixing When Sentry reports an issue or a customer emails about a bug, an agent wakes straight away. It checks the report is genuine, fixes the code, deploys, confirms the fix in production and resolves the issue. ### What an AI coding agent does here An AI coding agent reads a codebase, makes changes and runs them. Most are pointed at tickets a developer writes. This one is pointed at production: the errors your users actually hit. The hard part is not writing the fix. It is knowing whether to make it, proving it worked, and closing the loop with whoever reported it. ### How it works 1. **A report arrives.** A Sentry issue arrives by webhook, or a customer’s bug email is routed from your inbox. The incident job starts at once, not on the next schedule. 2. **Is it real, and should we?.** Before touching the repository the agent decides: not real, not in good faith, conflicts with a decision already made, or legitimate. A bad-faith request is refused and escalated. 3. **Fix and test.** It reproduces the problem, changes the code and runs your tests. 4. **Deploy and verify.** It ships the fix and checks production. If the fix is merged but not live yet, the issue stays open with a comment. 5. **Close the loop.** The issue is resolved only when the fix is verified live. If it cannot fix it, you get one task with what it found. ### What it will not do - It will not mark an issue resolved because a pull request merged. Only a verified live fix counts. - It will not partially implement a request it judged to be in bad faith. - It needs access to your repository and a way to deploy. Without them it reports what it found and stops. ### Questions **Does it replace Sentry?** No. Sentry finds and groups the errors. OpenHelm acts on them. The two work together. **Can I review fixes before they ship?** Yes. Have it open a pull request and wait for your approval instead of deploying. **What about customer bug reports by email?** The support agent routes them to the incident job with the customer’s exact error, and the customer is told it is fixed only once it really is. **Which models does it use?** Your choice: your own Claude Code or Codex subscription, a local model, or hosted models. See Models. ## AI customer service that knows when to ask you. Source: https://www.openhelm.ai/customer-support Your product gets a real inbox. Every email wakes an agent that reads the thread, answers what it can answer truthfully, and holds anything risky for you to approve. ### What AI customer service should mean AI customer service is software that reads and answers customer messages. The danger is an agent that sounds sure while making things up: a feature you do not have, a refund you did not offer, a date you never set. So the agent here answers from what your product actually does, says when it is still checking, and asks you before anything that carries risk. ### How it works 1. **A real address.** Each product gets an inbox on its own domain once DNS verifies, or a relay address until then. Mail sends with its own reputation. 2. **Mail wakes the agent.** An inbound message starts the triage job bound to that address. Replies wake the same thread, so a conversation stays with one handler. 3. **Answer or hold.** Set the inbox to hold agent replies for approval, send and notify you, or send automatically. You can edit before anything goes. 4. **Hand bugs to engineering.** A defect goes to the incident job with the customer’s words attached. ### What it will not do - It will not promise refunds, prices or dates it cannot find evidence for. - It does not send from a domain that has not passed verification. - Chat widgets and phone are not part of this. It is email. ### Questions **Do I need a new email provider?** No. OpenHelm Mail gives each product an inbox. Point your support address at it or forward to it. **Can I see every reply before it is sent?** Yes. Set the inbox to hold agent mail and nothing goes out until you approve it. **What if a customer replies to the agent?** The reply wakes the same job with the whole thread, so it carries on from where it left off. # The platform ## Agents. Each one owns its work. An agent is a named role with a brief, the connections it may use, and the jobs it runs. Agents can hand work to each other, so the support agent can pass a bug to the engineering agent with the customer’s words attached. - A brief and a persona per agent - Scoped connections per agent - Sub-agents for larger crews - A record of every run ## Jobs and triggers. Work that starts itself. A job is a prompt, a trigger and an outcome contract: what done looks like, how to check it, and when to stop. Jobs run once, on an interval, on a cron schedule, by hand, after another job succeeds, when an email arrives, or when a webhook fires. - Schedules, webhooks and inbound email - Chains: run this after that succeeds - Priority levels, so urgent work goes first - Budgets that stop runaway spend ## Data tables and charts. Where agents keep their notes. Agents read and write tables: the keyword plan, the content log, incidents, funnel steps. Connectors fill tables from Search Console, GA4 and more, and charts update as rows arrive. - Tables agents and people both edit - Connector-fed tables that refresh themselves - Charts on any table - A change history on every row ## Approvals and reviews. You decide what ships. Risky actions become tasks with Approve and Reject on them. Pull requests, deploys, published posts and held emails land in one review queue, so you can clear a morning’s work in a few minutes. - Autonomy levels you choose - One queue for everything waiting on you - Edit before you approve - Nothing runs for the first time without your yes ## Goals that are checked. Not activity counts. Each agent works towards a few criteria a machine can check. After every run, a separate evaluator reads the record of what the agent actually did and decides whether the work moved forward. The agent’s own summary is never taken on trust. - Machine-checkable goal criteria - An evaluator that is not the worker - Failures that name the external fix they need - Progress you can read in Pulse ## Memory, chat and templates. So the tenth run is better than the first. With the Contextely plugin, agents remember what they learned about each product. Chat builds agents, jobs and tables from a plain description, and every job it creates carries an outcome contract. Templates provision a whole crew in one step. - Product-scoped memory - Chat that creates real agents and jobs - Templates you can change freely - Plugins for mail, connections and memory # Models ## Your Claude Code subscription The desktop app runs agents on your Mac with the Claude Code plan you already have. It can also pick up your cloud workspace’s runs, so your subscription does the work the browser app schedules. - No API key needed - Runs use no OpenHelm credits - Pauses cleanly when you hit a usage limit, then resumes ## Your Codex plan Prefer OpenAI? Choose Codex as the backend and the same agents run on your Codex subscription instead. - Choose per machine - Same jobs, same checks - Runs use no OpenHelm credits ## A local model Run Gemma through Ollama, entirely on your machine. OpenHelm runs the agent loop itself and gives the model file, shell and web tools. Local models are best at focused jobs; long multi-step work is still better on a larger model. - Nothing leaves your Mac - Free to run - Honest about limits: failures are reported, not hidden ## Hosted models No subscription and no local setup? Agents run on hosted models, paid for from the AI credits in your plan. - Works from the browser - Credits included on every plan - Business plans can add metered overage # The product growth template - **Strategist**: Builds and maintains the keyword plan from Keyword Planner data. - **Publisher**: Writes posts against the plan, publishes them to your repo and confirms they are live. - **Technical SEO**: Checks index coverage, sitemaps, redirects and broken links, and resubmits after fixes. - **Content lifecycle**: Refreshes or prunes posts that stop earning, and reviews keyword accuracy monthly. - **AI visibility**: Audits llms.txt, schema and crawler access, and tracks citations in answer engines. - **SEO reporter**: A weekly digest from Search Console, written back against every post. - **Journey analyst**: Maps key journeys from GA4 and files tasks where users stall. - **Sentinel**: Wakes on Sentry issues and bug reports, fixes, deploys and verifies. - **Customer steward**: Triages the product inbox and drafts replies, held for approval by risk. - **Competitor and trend analysts**: Weekly briefs on competitors and what your niche is discussing. # Security ## Isolated runs In the cloud, each run happens in a fresh, isolated Linux sandbox that is thrown away afterwards. In desktop mode, runs happen on your own Mac, and the built-in file tools used with local models are confined to the job’s working directory. ## Scoped, encrypted credentials Connections use OAuth scopes you grant or keys you supply. In the cloud they are kept in an encrypted vault; on the desktop, in the macOS Keychain. They are injected only when a run needs them, and you can revoke them at any time. ## Organisation-level access Data is scoped to your organisation by row-level security in the database. Team workspaces have Owner, Admin, Member and Viewer roles. ## A person in the loop You set how much agents may do alone. Risky actions become approvals, the first run of any plan needs your yes, and hard daily budgets stop runaway spend. ## Where it runs Our cloud worker runs in London. Product mail is sent through AWS in London (eu-west-2). The database is hosted by Supabase and run sandboxes by E2B. Ask us for the current list of sub-processors. ## Fully local, if you prefer The desktop app can run everything on your Mac against a local database. Paired with a local model through Ollama, nothing leaves the machine. # Guides ## Google indexing: why pages aren't indexed and how to fix it Source: https://www.openhelm.ai/guides/google-indexing (updated 2026-09-24) Google indexing is the step where Google stores a page it has crawled so the page can appear in search results, and it is never guaranteed: Google decides URL by URL whether a page is worth keeping. If a page is missing, look up its status in Search Console's Page indexing report or URL Inspection, fix the cause that status points to, then resubmit your sitemap or use Request indexing. | Status | What it means | What to do | | --- | --- | --- | | Crawled - currently not indexed | Google fetched the page and chose not to index it for now | Improve or consolidate the content, add internal links, then request indexing once | | Discovered - currently not indexed | Google knows the URL but has not crawled it yet | Fix slow or failing server responses, link to the page, cut low-value URLs | | Duplicate, Google chose different canonical than user | Google treats another URL as the main version | Check which URL Google picked and align canonicals, redirects and internal links | | Alternate page with proper canonical tag | The page points to another URL as canonical | Usually fine; no action unless this page should be the main version | | Excluded by 'noindex' tag | A noindex directive told Google not to index it | Remove the tag or header if the page should rank | | Blocked by robots.txt | Googlebot is not allowed to crawl the URL | Allow crawling if the page should be indexed; use noindex, not robots.txt, to keep pages out | | Soft 404 | The page returns 200 but looks empty or like an error page | Return a real 404 or 410, or add the missing content | | Page with redirect | The URL redirects elsewhere | Expected for old URLs; remove redirecting URLs from your sitemap | ### How Google indexing works Google handles every URL in four stages. 1. **Discovery.** Google finds the URL through a link from a page it already knows, a sitemap or a redirect. 2. **Crawling.** Googlebot fetches the page, within the limits of robots.txt and how quickly your server responds. 3. **Rendering and indexing.** Google renders the page (JavaScript included), works out what it is about, picks a canonical URL from any duplicates, and decides whether to store it. 4. **Serving.** Only indexed pages can appear in results. Step three is where people get caught out. A crawl is not a promise to index. Google's own documentation says it does not guarantee to crawl, index or serve any page, even one that follows every guideline. A new site, or one that publishes lots of similar pages, will nearly always have some URLs sitting outside the index. You can see this in the **Page indexing** report in Google Search Console (Indexing > Pages). It splits your known URLs into indexed and not indexed, with a reason for each group that isn't. Those reasons matter because each one points to a different fix. The two that confuse people most are "Crawled - currently not indexed" and "Discovered - currently not indexed". They sound alike and mean quite different things. One sense check before you chase anything: a `site:yourdomain.com` search is a rough sample, not a count. Use Search Console for real numbers. ### Crawled - currently not indexed: causes and fixes This status means Googlebot fetched the page, looked at it, and decided not to add it to the index for now. Nothing technical is blocking it. Google has judged that the page isn't worth storing yet, or that another page already covers the same ground. ### Common causes - **Thin or unfinished content.** Short pages, placeholder copy, tag and archive pages with a few lines of text. - **Near duplicates.** Pages that differ only by a town name, a product variant or a URL parameter. - **Weak internal linking.** A page linked only from the sitemap looks unimportant. - **Little demand.** A page on a topic nobody searches for can sit here for a long time. - **A young site.** Google is more selective until a site has built up some trust. ### How to fix it 1. Open the URL in URL Inspection and check that the live test renders the real content, not an empty shell waiting on JavaScript. 2. Make the page clearly more useful than what already ranks: answer the question, add original detail, cut boilerplate. 3. Merge or redirect pages that compete with each other, and set a canonical where duplicates have to stay. 4. Link to the page from relevant pages that are already indexed, using descriptive anchor text. 5. Request indexing once, or wait for the next crawl. If a page stays in this state after real improvements, ask whether it needs to exist at all. Pruning or merging weak pages often helps the rest of a site get indexed. ### Discovered - currently not indexed: causes and fixes Here Google knows the URL exists but hasn't crawled it yet. Google's documentation gives the typical reason: it went to crawl, expected the site to be overloaded, and rescheduled. In practice it often means Google doesn't yet see enough reason to spend crawling effort on those URLs. ### Common causes - **Server capacity.** Slow responses, timeouts or 5xx errors make Googlebot back off. Check Settings > Crawl stats in Search Console for response times and host problems. - **Too many low-value URLs.** Faceted navigation, calendar pages, session IDs and endless parameter combinations soak up crawling. - **Orphan pages.** URLs that appear only in a sitemap, with no internal links pointing at them. - **A sudden spike.** Hundreds of new URLs published at once on a small site. ### Crawl budget, briefly Google says crawl budget mainly matters for very large sites (around a million unique pages or more) or sites with 10,000 or more pages that change daily. If your site has a few hundred pages and still shows many "Discovered" URLs, the problem is usually quality or internal linking, not budget. ### How to fix it 1. Fix server errors and slow responses first. 2. Stop generating useless URL patterns, or block them in robots.txt. 3. Link to the pages you care about from pages that are already indexed. 4. Keep your sitemap to canonical, indexable URLs with accurate `lastmod` dates. ### Using URL Inspection properly URL Inspection, the search bar at the top of Search Console, is the most direct tool you have. For any URL on a verified property it shows: - whether the URL is on Google and, if not, why - the last crawl date and which Googlebot fetched it - the canonical you declared and the canonical Google selected - whether crawling and indexing are allowed (robots.txt, noindex) - structured data and other enhancements Google detected Click **Test live URL** to fetch the page as it is right now, then **View tested page** to see the rendered HTML and a screenshot. This is how you catch a page that looks fine in your browser but renders empty for Googlebot, or a noindex tag a plugin slipped in. **Request indexing** puts the URL in a priority crawl queue. It helps for a single important page after a fix. It does not force indexing, it has a daily quota, and pressing it again for the same URL does nothing extra. It is not a way to index a whole site. There is also a URL Inspection API. It is read-only: it returns the same inspection data so you can monitor pages in bulk, but it cannot request indexing. Tools promising to "instantly index" any page through Google are usually misusing the Indexing API covered in the next section. ### Sitemaps: the honest way to ask Google to recrawl Google offers no public API to request indexing of an arbitrary page. The Indexing API exists, but Google limits it to pages with JobPosting structured data or a BroadcastEvent embedded in a VideoObject. Using it for blog posts or product pages is outside its supported use, and Google's documentation warns that abuse can get access revoked. That leaves the sitemap as the supported route: - List only canonical, indexable URLs that return a 200 status. - Keep `lastmod` accurate. Google uses it when it is consistently correct, and ignores `priority` and `changefreq`. - Submit the sitemap in Search Console (Indexing > Sitemaps) and reference it in robots.txt with a `Sitemap:` line. - After a significant change, resubmit it. The Search Console API has a `sitemaps.submit` method for exactly this. Google retired its old sitemap "ping" endpoint in 2023, so scripts that still call it do nothing. A sitemap is a hint, not an instruction. It helps Google find URLs and see what changed; whether a page is indexed still depends on the page. OpenHelm's SEO agents work this way. A technical SEO job reads index coverage from Search Console, fixes what it can in the product's own repository, and once the fix is live it resubmits the sitemap through Search Console rather than pretending it can force indexing. See [SEO with OpenHelm](/seo). ### IndexNow and Google IndexNow is an open protocol, launched in 2021 by Microsoft Bing and Yandex, that lets a site tell search engines the moment a URL is added, updated or deleted. You host a key file on your domain, then send the changed URLs to an IndexNow endpoint. One submission is shared with every participating engine, including Bing, Yandex, Naver, Seznam and Yep. Google does not use IndexNow. It said in 2021 that it would test the protocol and has not adopted it since. Sending IndexNow pings will not speed up Google indexing. It is still worth setting up, for two reasons: - **Bing matters beyond Bing.** Microsoft Copilot runs on Bing's index, and ChatGPT search draws partly on Bing, so fast Bing indexing can help you show up in AI answers sooner. - **It is cheap.** Many CMSs, SEO plugins and CDNs support it with a setting, and Cloudflare can send the pings for you. A sensible order after publishing or updating a page: 1. Make sure the page is in your sitemap with a fresh `lastmod`. 2. Send the URL through IndexNow for Bing and the others. 3. Let Google pick it up from the sitemap and internal links, and use Request indexing only for the pages that matter most. For AI search more broadly, see our guides to [ranking in ChatGPT](/guides/how-to-rank-in-chatgpt) and [Google AI Overviews](/guides/ai-overviews). ## Schema markup: what it is, which types matter and how to test it Source: https://www.openhelm.ai/guides/schema-markup (updated 2026-09-24) Schema markup is structured data, written in the schema.org vocabulary, that tells search engines and AI systems exactly what a page describes, such as an organisation, an article, a product or a piece of software. Add it as JSON-LD in the page's HTML, use only the types that match what is visibly on the page, and check it with Google's Rich Results Test and the Schema Markup Validator. | Type | Use it on | What Google can show | | --- | --- | --- | | Organization | Homepage or About page | Your logo and organisation details in results and knowledge panels | | Article / BlogPosting | Blog posts, news and guides | The right headline, image, author and dates for the article | | FAQPage | Pages with visible questions and answers | FAQ rich results only for well-known government and health sites since 2023 | | Product | Individual product pages | Price, availability and review stars in product snippets and merchant listings | | BreadcrumbList | Any page within a site hierarchy | A breadcrumb trail in desktop results | | SoftwareApplication | App and SaaS product pages | Rating and price in a software app rich result (needs ratings or reviews) | | Person | Author pages and article bylines | No rich result on its own; makes authorship clear | ### What schema markup does Schema.org is a shared vocabulary for describing things on the web, started in 2011 by Google, Microsoft, Yahoo and Yandex. Schema markup is that vocabulary applied to your pages: a machine-readable statement that this page is a `BlogPosting` by this `Person`, published by this `Organization`, or that this is a `Product` with this price. It pays off in two ways. **Rich results.** Google uses structured data to decide whether a page can show an enhanced listing: review stars, prices, breadcrumbs, a logo. Markup makes a page eligible, but it never guarantees Google will show the enhancement. **Machine understanding.** Markup states facts explicitly instead of leaving a crawler to infer them from layout. That helps search engines connect your pages to entities in their knowledge graph, and gives AI systems unambiguous facts to work with when they summarise or cite you. What schema markup won't do is push a page up the rankings by itself. Google has said structured data is not a general ranking signal. Its value comes from clearer understanding and better-looking listings, which can lift click-through. The rule underneath all of it: **mark up what is visible on the page, and nothing else.** Markup describing content users can't see, or reviews that don't exist, breaks Google's structured data guidelines and can lead to a manual action. ### JSON-LD vs Microdata vs RDFa There are three ways to add schema markup, and Google supports all of them. **JSON-LD** is a block of JSON inside a ` ``` A few details worth copying: - Use full, absolute URLs for `url`, `logo` and `image`. - Use ISO 8601 dates, and change `dateModified` only when the content actually changes. - Put the Organization once, with an `@id`, and reference it everywhere else. - Generate the block from the same data that renders the page, so the two can't drift apart. In a framework such as Next.js, that usually means building the object in the page component from the post's own metadata and rendering it with `JSON.stringify` inside the script tag. The headline, dates and author then come from one source, and a content edit updates the markup automatically. Add a `BreadcrumbList` beside it if the page sits in a hierarchy, and a `FAQPage` if the post ends with visible questions. All of them can live in the same `@graph` array. ### Testing and maintaining schema markup Use two tools, because they answer different questions. - **Rich Results Test** (search.google.com/test/rich-results) shows which Google rich results a page is eligible for, and lists errors that block eligibility and warnings that don't. It tests a live URL or a pasted code snippet, and renders JavaScript. - **Schema Markup Validator** (validator.schema.org) checks your markup against the whole schema.org vocabulary, including types Google doesn't use for rich results. Use it for anything the Rich Results Test ignores. After launch, watch the enhancement reports in Google Search Console, such as Breadcrumbs, Product snippets and Review snippets. They show valid and invalid items across the whole site and flag new errors after a deploy. Common mistakes: - Markup that doesn't match the visible page, especially prices and ratings. - Self-serving review stars on your own Organization or LocalBusiness, which Google won't show. - Missing required properties after a template change. - Bumping `dateModified` on every build when nothing changed. OpenHelm's GEO audit includes a JSON-LD and schema check alongside llms.txt, AI crawler access, citable facts, heading hierarchy and authorship. Its agents make fixes in the product's own repository, so the markup lives with your code. See [SEO with OpenHelm](/seo). ## E-E-A-T explained: experience, expertise, authority and trust Source: https://www.openhelm.ai/guides/eeat (updated 2026-09-24) E-E-A-T stands for experience, expertise, authoritativeness and trustworthiness, the framework Google's quality raters use to judge whether a page and its creator can be relied on. It is not a direct ranking factor or a score, but Google says its systems look for signals that line up with it, so showing who wrote a page, why they know, and why your site can be trusted is worth the effort. | Component | What it asks | How to show it | | --- | --- | --- | | Experience | Has the creator actually used, done or seen what they describe? | Original screenshots, photos, data and specific first-hand detail | | Expertise | Does the creator have the knowledge or skill the topic needs? | Named author with relevant background; accurate, current, sourced content | | Authoritativeness | Is the creator or site a go-to source for this topic? | Mentions, links and reviews from respected independent sources | | Trust | Is the page accurate, honest, safe and reliable? | Clear ownership, contact details, transparent pricing, cited claims, HTTPS | | YMYL topics | Could bad information harm health, money or safety? | Expert authorship or review, and a much higher bar for every signal above | ### What E-E-A-T is and where it comes from E-E-A-T comes from Google's **Search Quality Rater Guidelines**, the handbook for the people Google pays to assess search results. Raters look at real queries and results and judge page quality and how well results meet the need behind the search. Their ratings don't change the ranking of the pages they review. Google uses them to check whether changes to its ranking systems are producing better results. The guidelines first used E-A-T (expertise, authoritativeness, trustworthiness). In December 2022 Google added a second E for **experience**, recognising that someone who has actually used a product or been through a situation often has more useful things to say than someone with formal credentials. You'll see it written as E-E-A-T, EEAT or "double-E-A-T". They all mean the same thing. Within the four, the guidelines put **trust** at the centre and call it the most important. Experience, expertise and authoritativeness feed into trust. A page can be written by an expert and still be untrustworthy if it is misleading, out of date or hiding who is behind it. The bar also depends on the topic. For "Your Money or Your Life" (YMYL) subjects, such as health, finance, legal matters and safety, raters are told to expect a much higher level of all four, because bad information can do real harm. ### Is E-E-A-T a ranking factor? Not directly. There is no E-E-A-T score in Google's systems and no single signal you can switch on. Google has said its ranking systems use a mix of factors that help identify content showing good E-E-A-T, and that these signals carry more weight for YMYL queries. In practice that means two things. First, you can't add E-E-A-T with a plugin. An author box or a schema snippet doesn't create expertise. They help Google and readers see expertise and trust that are already there. Second, it mostly shows up through things Google can observe: whether other reputable sites mention and link to you, whether your content is accurate and specific, whether readers can tell who is responsible for it, and whether the site behaves honestly. Google's guidance on helpful content suggests asking three questions of every page: - **Who** created it? Make that obvious, with a byline and background where people would expect it. - **How** was it created? If you tested something, say how. If automation or AI helped, be open about it where readers would reasonably want to know. - **Why** was it created? Primarily to help people, not primarily to attract search traffic. Those questions are a more useful working test than the acronym itself. ### Showing experience and expertise on the page The strongest evidence of experience is detail nobody could write without doing the thing. - **Original material.** Your own screenshots, photos, measurements and data rather than stock images and figures copied from elsewhere. - **Specifics.** What you tried, what happened, what went wrong, what it cost, how long it took. - **Limits.** Where a method doesn't work, or where your product isn't the right choice. Honest caveats read as experience; blanket praise doesn't. Expertise shows through accuracy and care: - Claims that are correct and current, with sources linked where a reader might want to check. - Dates that mean something: a published date, and an updated date only when the content genuinely changed. - For YMYL topics, an author or reviewer with relevant qualifications, named on the page. AI-assisted writing isn't ruled out. Google has said it cares about whether content is helpful, not how it was produced. But since March 2024 its spam policies cover **scaled content abuse**: publishing large amounts of unoriginal content mainly to rank, however it is made. A post that restates the top ten results adds no experience at all. One built on your own product data, screenshots or customer questions does. ### Bylines, author pages and Person schema Authorship is where E-E-A-T becomes concrete and machine-readable. **Bylines.** Put a real name on articles, linked to an author page. "Admin" or "The team" tells readers and machines nothing. **Author pages.** Give each author a page with a short bio, their role, relevant experience or qualifications, links to profiles elsewhere (LinkedIn, GitHub, a professional register), and a list of what they have written. Keep it factual. **Person schema.** Mark up the author in your Article or BlogPosting structured data as a `Person`, with `name`, `url` pointing to the author page, and `sameAs` links to their other profiles: ```json { "@context": "https://schema.org", "@type": "BlogPosting", "headline": "How to chase a late invoice", "datePublished": "2026-09-01", "author": { "@type": "Person", "name": "Sam Taylor", "url": "https://acme.example/authors/sam-taylor", "jobTitle": "Head of Finance", "sameAs": ["https://www.linkedin.com/in/sam-taylor-example"] } } ``` Schema doesn't create authority. It connects the facts you already show, so search engines and AI systems can tie an article to a real person and that person to their other work. That connection matters more as answer engines decide which sources to cite. Our [schema markup guide](/guides/schema-markup) covers the rest of the setup. ### Trust and authority at site level Much of E-E-A-T is judged across a whole site, not page by page. ### Trust signals - An **About** page that says who runs the site or company, with a real registered name and location. - Clear **contact details** and a way to reach a person. - **Transparent pricing**, refund and cancellation terms for anything you sell. - A privacy policy, HTTPS everywhere, and no deceptive ads or dark patterns. - **Corrections**: fix errors openly and update the date only when content changes. ### Authority signals Authority is mostly what others say about you. Mentions and links from respected sites in your field, genuine reviews on third-party platforms, citations in industry roundups and talks all count. You can't write these yourself, but you can earn them with original data, useful tools and honest comparisons. Add `Organization` schema on your homepage with your legal name, logo and `sameAs` links to official profiles, so your brand is identified consistently. OpenHelm's GEO audit checks authorship signals, headings and schema alongside other items, and its blog publisher writes posts against a keyword plan and checks them for AI tells before publishing, into the product's own repository. See [autoblogging](/autoblogging) and [SEO](/seo) for how that works. ## Google AI Overviews: how they work and how to get cited Source: https://www.openhelm.ai/guides/ai-overviews (updated 2026-09-24) Google AI Overviews are AI-generated summaries shown at the top of some search results, built with Gemini from pages in Google's index and displayed with links to the sources used. There is no special markup or sign-up for them: a page has to be indexed and eligible for a snippet, and the pages that get cited are the ones that answer a specific part of the question clearly and credibly. | Lever | What it does | When to use it | | --- | --- | --- | | Indexing and snippet eligibility | Required before a page can be cited at all | Always; fix indexing problems first | | nosnippet | Stops text from the page being shown or used, in AI features and normal snippets | Rarely; it also removes your ordinary search snippet | | data-nosnippet | Excludes specific sections of a page from snippets and AI features | For passages you don't want quoted, such as pricing detail or gated content | | max-snippet | Caps how many characters Google may use from the page | When you want to limit how much is reproduced | | noindex or blocking Googlebot | Removes the page from Google Search, AI features included | Only for pages you don't want in Search at all | | Google-Extended | Controls use in Gemini training and grounding in some other Google products | A separate choice; it does not affect Search or AI Overviews | ### What AI Overviews and AI Mode are **AI Overviews** are the summaries that appear above the usual results for some searches. Google launched them in the US in May 2024, growing out of its Search Generative Experience trial, and has since rolled them out to many more countries and languages. They appear for a share of queries, most often longer informational questions, and not at all for many navigational or commercial ones. **AI Mode** is a separate, conversational way to search. It takes more complex questions, handles follow-ups, and reasons across more sources before answering. Google launched it in the US in 2025 and has expanded it since. Both are built on Gemini models and both draw on Google's search index. Google describes the difference like this: AI Overviews help people get the gist of a topic quickly, while AI Mode suits questions that need more exploration, reasoning or comparison. For a site owner, they matter for the same reason. The answer now sits above the blue links, and whether your page appears as a cited source can matter as much as where it ranks. Both features show links to their sources, as a list beside the answer and as inline links, and Google says they often show a wider range of sites than a traditional results page. ### How sources get cited: query fan-out Google says both AI Overviews and AI Mode use a technique it calls **query fan-out**: issuing several related searches across subtopics and data sources, then building a response from what comes back. Take a question like "best way to chase a late invoice as a freelancer in the UK". Behind the scenes that might become searches about statutory late payment interest, polite reminder wording, when to use a debt recovery service, and small claims court fees. Each sub-search has its own set of results, and a page can be cited for one of those sub-questions even if it ranks nowhere near the top for the original query. That changes what to aim for: - **Cover the questions around your topic,** not just the head term. A page that answers "how much interest can I charge on a late invoice" cleanly is a candidate for every broader question that fans out to it. - **Make passages self-contained.** A paragraph that states the answer, with the specific figure, date or rule, is easier to lift than one that depends on the three before it. - **Be precise.** Specific facts, named entities and clear definitions give the model something concrete to cite. Citations still come from Google's index. There is no separate AI crawler for Search: Googlebot does the crawling, and ordinary indexing decides what is available to cite. ### What you can influence Google's guidance is plain: there are no extra technical requirements and no special optimisation for AI features. A page must be indexed and eligible to be shown with a snippet. Beyond that, the same things that make a page good for search make it good for AI Overviews. The levers that matter most: 1. **Get indexed.** A page that isn't in the index can't be cited. Start with our [Google indexing guide](/guides/google-indexing) if Search Console shows gaps. 2. **Answer first.** Put the direct answer in the opening lines of a section, then the detail. Use headings that match real questions. 3. **Use tables and lists for comparisons and steps.** They are easy to extract accurately. 4. **State facts precisely.** Numbers, prices, dates, limits and names beat vague claims. 5. **Keep pages current.** For topics that change, date your content and update the facts, not just the date. 6. **Show who is behind it.** Clear authorship and a trustworthy site help; see [E-E-A-T](/guides/eeat). 7. **Add structured data that matches the page.** It helps Google understand entities, though it isn't required for AI features. See [schema markup](/guides/schema-markup). What you can't do is request inclusion, pay for it, or guarantee it. Treat citations as an outcome of being the clearest answer to part of a question. ### Controls and opting out There is no AI-specific opt-out for AI Overviews or AI Mode. The controls are the same snippet and indexing controls that apply to all of Search. - **nosnippet** stops Google showing or using text from a page. It works for AI features, but it also removes your normal search snippet, which usually costs clicks. - **data-nosnippet** is an HTML attribute you can put on specific elements. Text inside them won't be used in snippets or AI features, while the rest of the page stays eligible. - **max-snippet:[number]** limits how many characters Google may use. - **noindex**, or blocking Googlebot in robots.txt, removes the page from Search altogether. A common mistake is to assume **Google-Extended** handles this. It doesn't. Google-Extended is a robots.txt token that controls whether your content is used for training Gemini models and for grounding in some other Google products. Google has said it does not affect inclusion in Search, and AI Overviews are part of Search. For most sites, opting out makes little sense. If a competitor is cited in the overview and you aren't, blocking Google from quoting you won't bring the click back. The better question is which passages you don't want reproduced, and `data-nosnippet` handles those precisely. ### Measuring impact in Search Console Traffic from AI Overviews and AI Mode is counted in Search Console's **Performance** report under the **Web** search type, mixed in with everything else. Clicks, impressions and position from AI features are included in those totals, so you can't separate them in the main report. Google counts all links inside an AI Overview at the position of the overview itself. In 2026 Google added a **Generative AI performance report**. It shows impressions from AI Overviews and AI Mode over time, by page, country and device. It reports impressions only, not clicks, and it is a slice of data already counted in the Web totals rather than a new search type. Google is rolling it out gradually, and sites below a minimum impression threshold won't see it. Practical things to watch: - Pages whose impressions rise while click-through rate falls, often a sign an overview is answering the query on the results page. - Which pages appear in the Generative AI report, and for which topics. - Queries where position improves but clicks don't follow. On clicks, be careful with numbers you see quoted. One of the better public studies, from [Pew Research Center](https://www.pewresearch.org/short-reads/2025/07/22/google-users-are-less-likely-to-click-on-links-when-an-ai-summary-appears-in-the-results/), tracked the browsing of about 900 US adults in March 2025. They clicked a traditional result on 8% of visits to a results page with an AI summary, against 15% without one, and clicked a link inside the summary on 1% of visits. ### Tracking citations over time Search Console tells you about impressions. It won't tell you which competitor Google cited instead of you, or whether your product is named in the answer at all. For that you have to look at the answers themselves, regularly, for the questions that matter to your business. A simple routine is to keep a list of target questions, run them on a schedule, and record whether your site is cited, which pages are, and who else appears. Answers vary from run to run and by location, so a single check proves little; trends over weeks are what count. OpenHelm's AI visibility tracking does this as a scheduled job. It asks answer engines the questions from your keyword plan, through whichever answer-engine connections you have set up, and records whether your product is cited. If no engine is connected, it reports that it is blocked rather than guessing. A weekly SEO digest reads Search Console alongside it. More at [AI visibility](/ai-visibility). ## How to rank in ChatGPT and get your site cited Source: https://www.openhelm.ai/guides/how-to-rank-in-chatgpt (updated 2026-09-24) To rank in ChatGPT, your pages first have to be reachable by the systems ChatGPT searches with, which means allowing OAI-SearchBot in robots.txt and making sure Bing indexes your site. Then you need to be the kind of source it prefers to cite: clear, specific, current pages about topics where other reputable sites also mention you. | User agent | What it does | If you block it | | --- | --- | --- | | OAI-SearchBot | Crawls pages for ChatGPT's search features | Your pages won't appear in ChatGPT search answers, though they may still show as navigational links | | GPTBot | Crawls content that may be used to train OpenAI's models | Your content is excluded from training; no effect on ChatGPT search | | ChatGPT-User | Visits a page when a user or custom GPT asks ChatGPT to | ChatGPT may not be able to open your pages on request | | OAI-AdsBot | Checks landing pages for ChatGPT ads | Only matters if you advertise in ChatGPT | | Bingbot | Crawls for Bing's index, one of the sources ChatGPT search draws on | You drop out of Bing and lose a route into ChatGPT and Copilot answers | ### How ChatGPT search finds and cites pages ChatGPT answers in two ways. For many questions it replies from what the model learned in training. When a question needs current or specific information, or the user asks it to, it **searches the web**, reads the pages it finds, and writes an answer with inline citations and a list of sources. Ranking in ChatGPT means getting into that second path: being one of the pages it retrieves, reads and cites, and ideally having your product named in the answer itself. The search side draws on two things: - **Third-party search providers.** OpenAI has said ChatGPT search uses them, and Microsoft's Bing is a long-standing, known partner. If Bing hasn't indexed a page, you lose an important way in. - **OpenAI's own crawler.** OAI-SearchBot crawls the web to surface sites in ChatGPT's search features. Training data matters too, but more slowly. It shapes whether the model already knows your brand and what category it puts you in, and it only updates when new models are trained. Search is where a new page or a fresh fact can show up within days. There is no ranking position to submit to or buy. OpenAI publishes no ranking factors, so everything below is about being reachable, being mentioned, and being easy to quote. Those are the parts you can control. ### Make sure ChatGPT can reach you Start with access, because nothing else matters if the crawlers are blocked. **robots.txt.** OpenAI runs separate crawlers for separate jobs, and you can treat them differently. To appear in ChatGPT search while keeping your content out of model training: ```text User-agent: OAI-SearchBot Allow: / User-agent: GPTBot Disallow: / User-agent: Bingbot Allow: / Sitemap: https://www.example.com/sitemap.xml ``` OpenAI says changes to robots.txt take about 24 hours to reach its systems. **Firewalls and CDNs.** Many sites block AI crawlers without realising it, through a bot protection setting or a CDN rule. Check your firewall logs and bot settings for OAI-SearchBot and Bingbot, not just your robots.txt file. **Bing.** Verify your site in Bing Webmaster Tools, submit your sitemap, and look for crawl errors. Turn on IndexNow so Bing hears about new and updated pages straight away. Our [Google indexing guide](/guides/google-indexing) covers how IndexNow fits alongside Google. **Server-rendered content.** Put your main content, prices and key facts in the HTML the server sends. Don't count on every AI crawler running your JavaScript. ### Brand mentions and third-party sources When someone asks ChatGPT "what is the best tool for X", it tends to repeat what several independent sources agree on. Your own site says you're good; other sites saying so is what makes a recommendation likely. Places worth being mentioned, accurately: - **Comparison and review articles** in your category, including "best X for Y" roundups. - **Review platforms** relevant to your market, with genuine reviews from real customers. - **Communities** where your audience asks questions, such as Reddit, specialist forums and Stack Overflow. Answer honestly and say who you are; disguised promotion gets spotted and removed. - **Directories and marketplaces** for your category or platform. - **Press, podcasts and newsletters** that cover your niche. Consistency helps. If your product is described the same way everywhere, with the same name, category and core claim, a model has an easier time linking your brand to the problem it solves. Mixed descriptions leave it guessing. You can't manufacture this quickly and you shouldn't try to fake it. Invented reviews and paid placements dressed up as editorial are exactly what search systems, and readers, learn to discount. The durable route is to do something worth mentioning and make it easy for people to describe accurately. ### Write facts that are easy to cite A model can only cite what it can lift cleanly. Pages that get quoted tend to share a few habits. - **Answer first.** Open each section with the direct answer in a sentence or two, then the detail. - **Be specific.** Prices, limits, dates, supported platforms, version numbers. "Plans start at £12 per user per month" is citable. "Affordable pricing" is not. - **Use tables** for comparisons, specifications and plans. They extract accurately. - **Make each passage stand alone.** A paragraph that depends on the three before it is hard to quote correctly. - **Name things properly.** Use the full product and company names rather than "it" or "we" throughout. **Comparison content** deserves its own mention. People use ChatGPT to compare options, and a clear, honest page comparing your product with alternatives answers that directly. Say where the other option is better. A comparison that admits trade-offs is more credible to readers, and more useful to anything summarising it. **Freshness** matters for anything that changes. Put a visible date on pages, update the facts when they change, and keep `dateModified` in your structured data honest. Outdated prices are worse than none, because they get repeated. None of this is ChatGPT-specific. The same pages tend to do well in [Google AI Overviews](/guides/ai-overviews) and Perplexity. ### How to check whether ChatGPT cites you There is no ChatGPT equivalent of Search Console, so you check from three directions. **Ask it.** Keep a list of the questions your customers actually ask, including ones where you'd expect to be recommended. Run them with search on, in a temporary chat so your history doesn't colour the results. Note which sources are cited, whether you're named, and which competitors appear. Answers change between runs and by location, so repeat checks and look at the pattern over weeks rather than any single answer. **Check your analytics.** ChatGPT adds `utm_source=chatgpt.com` to many of the links it shows, so visits often appear in GA4 with chatgpt.com as the source. Look at which landing pages those visits reach. **Read your server logs.** Requests from OAI-SearchBot show your pages are being crawled for search. Requests from ChatGPT-User show ChatGPT opening a page for a user in real time. Doing the first of these by hand gets tedious fast. OpenHelm's AI visibility tracking runs it as a scheduled job: it asks answer engines the questions from your keyword plan, through whichever answer-engine connections you have set up, and records whether your product is cited. With no engine connected, it reports that it is blocked rather than guessing. See [AI visibility](/ai-visibility). ## llms.txt explained: the format, llms-full.txt and who reads it Source: https://www.openhelm.ai/guides/llms-txt (updated 2026-09-24) llms.txt is a proposed Markdown file at the root of a website (/llms.txt) that gives large language models a short, curated map of your most useful pages. It is cheap to add, but no major search or answer engine has confirmed using it for ranking or citations, so treat it as a small bet for documentation-heavy sites rather than a traffic lever. | File | What it does | Who reads it | Status | | --- | --- | --- | --- | | robots.txt | Allows or blocks crawlers by user agent | Search and AI crawlers that honour it | Internet standard (RFC 9309) | | sitemap.xml | Lists URLs and when they changed | Search engine crawlers | Widely supported protocol | | llms.txt | Summarises the site and links to key pages in Markdown | Some AI tools and agents, when pointed at it | Proposal; no confirmed ranking use | | llms-full.txt | Puts full documentation text in one Markdown file | Coding assistants and retrieval tools | Community convention | | Page.md versions | Serves a clean Markdown copy of a single page | Agents fetching one page at a time | Part of the llms.txt proposal | ### What llms.txt is and why it was proposed Jeremy Howard of Answer.AI published the llms.txt proposal at llmstxt.org in September 2024. The problem it targets is simple: websites are built for people, and a typical page is mostly navigation, scripts, cookie banners and layout. A language model trying to answer a question about your product has limited context and gains little from all that. The proposal asks sites to publish a plain Markdown file at `/llms.txt` that says, in a few lines, what the site is and where the useful material lives. It also suggests offering a Markdown version of important pages at the same URL with `.md` appended, so a tool can fetch clean text instead of HTML. The intended use is at inference time rather than training. When someone asks an assistant about your API, or points a coding tool at your docs, the tool can read llms.txt first and go straight to the right pages. People search for it as "llms txt" as often as "llms.txt", and it gets described as "robots.txt for AI". That comparison is misleading. robots.txt is about permission; llms.txt is closer to a curated table of contents. It doesn't control anything. ### The llms.txt format The format is ordinary Markdown in a fixed order: 1. An **H1** with the name of the project or site. This is the only required part. 2. A **blockquote** with a short summary holding the key facts someone needs to understand the rest. 3. Optional paragraphs or lists with more detail (no headings). 4. **H2 sections**, each a list of links written as `[name](url): optional notes`. 5. An optional H2 called **Optional**, for links a tool can skip when it is short on context. A small example: ```markdown # Acme Invoicing > Acme is invoicing software for UK freelancers. It creates VAT-compliant invoices, chases late payments and syncs with Xero. Acme runs in the browser and on iOS. All prices are in GBP. ## Docs - [Getting started](https://acme.example/docs/start.md): create an account and send a first invoice - [VAT rules](https://acme.example/docs/vat.md): how Acme handles VAT and the flat rate scheme - [API reference](https://acme.example/docs/api.md): endpoints, authentication and rate limits ## Product - [Pricing](https://acme.example/pricing.md): plans and what each includes - [Changelog](https://acme.example/changelog.md): releases by date ## Optional - [Company history](https://acme.example/about.md) ``` Keep the summary factual and specific. It is the part most likely to be read in full, so put the facts a model would otherwise get wrong there: what the product does, who it is for, where it works and how it is priced. For the link lists, a few habits help: - Link to canonical URLs, and prefer the `.md` versions if you serve them. - Write notes that say what a page answers, not marketing copy. - Group links the way a newcomer would look for them: docs, product, policies. - Put anything a tool could safely skip under **Optional**. There is no required length, but a file that lists every URL on your site defeats the point. That is what your sitemap is for. ### llms-full.txt and Markdown page copies llms.txt is an index: it points elsewhere. **llms-full.txt** is the opposite idea, the full text of your documentation concatenated into one Markdown file, so a tool can load everything in a single request. It isn't part of the core llmstxt.org proposal. It grew up as a convention among documentation platforms, and many hosted docs tools now generate both files automatically. Developers use it by pasting the URL into a coding assistant or adding it as a docs source in their editor, which is where it is most clearly useful. A few practical points: - **Size.** A large docs site can produce an llms-full.txt of several megabytes, more than many tools will load. Split it by product area if it gets large. - **Freshness.** Generate it at build time from the same source as your docs, never by hand, or it will drift. - **Duplication.** It is plain text at a separate URL, so it won't compete with your HTML pages in Google in any way that matters, but you can add an `X-Robots-Tag: noindex` header if you'd rather it stayed out of search results. Markdown page copies (`/docs/start.md` beside `/docs/start`) do the same job one page at a time. If you already build your site from Markdown, serving these is often a small change. ### llms.txt vs robots.txt The two files answer different questions. - **robots.txt** says who may crawl what. It is a formal standard (RFC 9309) that well-behaved crawlers check before fetching anything. - **llms.txt** says what is worth reading. It grants and denies nothing. So an llms.txt does not override robots.txt. If you block a crawler in robots.txt, listing pages in llms.txt won't let it in, and if you allow a crawler, leaving a page out of llms.txt won't keep it out. To control AI access, use robots.txt user-agent groups for each crawler: ```text User-agent: OAI-SearchBot Allow: / User-agent: GPTBot Disallow: / User-agent: Google-Extended Disallow: / ``` Note that Google-Extended is a control token, not a separate crawler. It tells Google whether content crawled by Googlebot may be used for Gemini training and grounding in some Google products. It does not affect Google Search or AI Overviews. Get robots.txt right first. A carefully written llms.txt is wasted if your CDN or firewall is quietly blocking the AI crawlers you want. ### Who actually reads llms.txt This is where honesty matters, because a lot of advice oversells it. **Google Search does not use it.** Google's Gary Illyes said in 2025 that Google does not support llms.txt and has no plans to, and John Mueller has compared it to the keywords meta tag. Google's guidance for AI Overviews and AI Mode lists no special files. **No major answer engine has confirmed using it for ranking or citations.** OpenAI, Anthropic, Perplexity and Microsoft have not said their search products use llms.txt to choose sources. You may see AI crawlers request the file in your server logs, but fetching a file is not the same as acting on it. **Where it does help:** - Coding assistants and agents that a developer points at your docs. - Tools that let users add a documentation URL as context. - Anyone pasting your site into a chat and wanting a clean starting point. That makes llms.txt worthwhile for products with APIs, SDKs or substantial documentation, and low priority for a small marketing site. It costs an hour to write and little to maintain, so the downside is small. Just don't expect it to move your visibility in ChatGPT, Perplexity or Google on its own. Citable content, crawl access and brand mentions do far more; see [how to rank in ChatGPT](/guides/how-to-rank-in-chatgpt). ### Adding llms.txt to your site A workable process: 1. Write it by hand first. Name the product in the H1, then a two or three sentence summary with real facts: what it does, who it's for, where it works, how it's priced. 2. Link your ten to thirty most useful pages in grouped H2 sections, each with a short note. 3. Serve it at the root as `/llms.txt`, as plain text (`text/plain` or `text/markdown`), with a 200 status. 4. Check it with `curl -I https://yourdomain.com/llms.txt` and make sure no redirect or bot rule gets in the way. 5. Regenerate or review it whenever key pages move, so it never links to a 404. If you have documentation, generate llms-full.txt and the `.md` page copies from your build rather than maintaining them manually. OpenHelm's GEO audit checks for llms.txt as one item among several: JSON-LD and schema, AI crawler access in robots.txt, citable facts, heading hierarchy and authorship signals. The agent then fixes what it can in the product's repository. More on that at [AI visibility](/ai-visibility). ## The aha moment: what it is and how to find yours Source: https://www.openhelm.ai/guides/aha-moment (updated 2026-09-24) The aha moment is the point where a new user first gets the core value of your product, usually by completing one specific key action. You find it by comparing how often users come back after doing, or not doing, each candidate action early on, then treating the action most tied to return visits as your activation event. | Term | What it means | How to measure it | | --- | --- | --- | | Aha moment | The first time a user feels the value the product promised | Retention of users who did a candidate action early vs those who did not | | Activation event | The trackable action you treat as the aha moment | Share of new sign-ups who complete it within a set window, such as 7 days | | First key action | The first action that delivers value, such as sharing a first document | Whether and when each new user triggers that event | | Time to value | How long a new user takes to reach the aha moment | Median time from sign-up to the activation event | | Onboarding | Everything between sign-up and the activation event | Completion rate at each step of the onboarding funnel | | Retention curve | The share of a sign-up cohort still active over time | Cohort retention at day 1, day 7 and day 30 | ### Aha moment, activation and time to value These three terms get used interchangeably, but they describe different things, and keeping them apart makes the work easier. The **aha moment** is a feeling. It is the point where a new user stops wondering whether the product is for them because they have just seen it do the thing they came for. You cannot measure a feeling directly. The **activation event** is the stand-in you can measure. It is one action, logged as an event, that reliably happens at or just after the aha moment. For a note-taking app it might be writing a second note on a different day. For an invoicing tool it might be sending the first invoice. **Time to value** is the gap between sign-up and that event. A product can have a clear aha moment and still lose most new users because the path to it takes twenty minutes of setup. The practical goal is simple: pick an activation event that genuinely predicts retention, then get more new users to it, sooner. Onboarding is the set of steps you control to make that happen, and the retention curve is how you check that it worked. ### How to find your aha moment from event data You need event tracking on the actions that matter, a few weeks of sign-ups, and a definition of "retained" that fits how often people should use your product (weekly for most B2B tools, daily for some consumer apps). 1. **List candidate actions.** Write down 5 to 10 actions a new user could take that plausibly deliver value: creating a first project, inviting a teammate, connecting a data source, completing a first export. 2. **Pick a window.** Look at what each user did in their first day, first session or first week. 3. **Split and compare.** For each candidate, compare the retention of users who did it in the window with those who did not. In GA4, a Cohort exploration lets you set the inclusion condition to a specific event and compare return rates; a Funnel exploration shows where people drop between steps. Mixpanel, Amplitude and PostHog have equivalent cohort and retention reports. 4. **Look for thresholds.** Sometimes doing an action once changes little but doing it three times changes a lot. Try counts as well as yes or no. 5. **Test the winner.** A correlation is not a cause. Users who invite teammates may simply be more committed already. Confirm by running an onboarding change that pushes more people to the action and checking whether retention actually moves. Keep the event you choose simple enough that everyone on the team can say it out loud. ### Common aha moments by product type Every product is different, but the activation events that work tend to follow a few patterns. | Product type | Typical activation pattern | |---|---| | Collaboration tool | A second person joins and does something in a shared space | | Analytics or reporting | A real data source is connected and the first chart shows the user's own data | | Developer tool or API | The first successful call or deploy from the user's own code | | Marketplace | A first completed transaction, not just a listing or a search | | Content or media | Returning to consume a second piece within a few days | | Finance or invoicing | The first real invoice sent or payment received | The common thread is that the user sees their **own** data, work or people inside the product, not a demo. You will also see famous "magic numbers" repeated online, such as a social network's number of friends within a set number of days. They are widely quoted, rarely sourced, and describe someone else's product. Use them as a reminder that thresholds exist, not as targets. ### Shortening time to value Once you know the activation event, work backwards from it and remove anything that stands between a new user and that moment. - **Cut steps before value.** Every form field, setting and tour screen before the first key action costs you people. Move what you can to after the aha moment. - **Start with something real.** Import, templates or sample data can help, but the moment usually lands when the user sees their own material. Make connecting it the first thing you ask for. - **Watch the funnel, not the average.** A median time to value can look fine while one step loses a third of users. Track step-by-step completion in the onboarding funnel. - **Follow up on the stuck.** A user who signed up and stopped one step short of activation is your best prospect. A timely email or in-app nudge pointing at the exact next step often does more than a redesign. - **Re-check the retention curve.** After each change, compare the new sign-up cohorts with earlier ones. If activation rose but the curve did not lift, you may have made the event easier to hit without delivering more value. ### How OpenHelm helps OpenHelm runs agents that look after a live product, and one of them, the journey analyst, maps your key user journeys from the product itself and your GA4 events. Where users stall between steps, it files a task with the evidence, so the drop-off before your activation event becomes something on your list rather than a number nobody looked at. If a live product has no analytics yet, OpenHelm files a task for that too, and can create the GA4 property and data stream and wire the measurement ID into your deployment. Funnels, retention and audience appear as charts and data tables alongside the agents' work. The analyst runs as a scheduled job, and a separate evaluator checks every run against the job's outcome contract rather than taking the agent's word for what it found. See [user funnels](/user-funnels) for how it fits together. ## Retention rate: formula, types and how to read a cohort table Source: https://www.openhelm.ai/guides/retention-rate (updated 2026-09-24) Retention rate is the percentage of customers or users still active or paying at the end of a period, out of those you had at the start. The formula is (customers at end - new customers gained) / customers at start, so starting with 200 customers, gaining 40 and ending with 220 gives (220 - 40) / 200 = 90%. | Type | Formula | Best for | | --- | --- | --- | | Customer retention rate | (Customers at end - new customers) / customers at start | Subscription businesses counting paying accounts | | N-day retention | Users active on day N / users in the cohort | Products meant to be used daily, such as consumer apps | | Unbounded retention | Users active on day N or any later day / users in the cohort | Products used irregularly, where a quiet day is not a loss | | Bracket retention | Users active within a window, such as days 7 to 13 / users in the cohort | Products with a weekly or monthly rhythm | | Net revenue retention | (Start MRR + expansion - contraction - churned MRR) / start MRR | Revenue from an existing customer base, including upsells | | Gross revenue retention | (Start MRR - contraction - churned MRR) / start MRR | Revenue kept before any upsell, capped at 100% | ### How to calculate retention rate: a worked example The standard customer retention rate formula is: ``` retention rate = (customers at end of period - new customers during period) / customers at start of period ``` Take a product that starts the quarter with 200 paying customers, gains 40 new ones and finishes with 220. - Customers at end: 220 - New customers during the quarter: 40 - Customers kept from the start: 220 - 40 = 180 - Retention rate: 180 / 200 = **90%** Subtracting new customers is the step people forget. Without it you would get 220 / 200 = 110%, which only tells you the business grew, not whether it kept anyone. For the same customers and period, retention rate and churn rate add up to 100%: here, 10% of the starting customers left. See the [churn rate guide](/guides/churn-rate) for the churn side and for converting between monthly and annual figures. Choose the period to fit how customers pay and use the product. Monthly works for monthly plans. Quarterly or annual suits annual contracts, where customers can only leave at renewal and a monthly figure would look perfect for eleven months. ### N-day, unbounded and bracket retention For user activity rather than paying accounts, product analytics tools usually offer three ways to define "retained". They answer different questions, so the choice matters. ### N-day retention A user counts as retained on day 7 only if they were active on day 7 exactly. It is strict and suits products people should use every day. For a tool used once a week, it will look alarmingly low and bounce around depending on which weekday people signed up. ### Unbounded retention A user counts as retained on day 7 if they were active on day 7 or on any day after it. It answers "has this person come back at least once from this point on?" It is always equal to or higher than N-day retention, and it keeps changing for recent cohorts as more days pass, so compare cohorts of the same age. ### Bracket retention You define windows that match your product's rhythm, such as days 1 to 6, 7 to 13 and 14 to 29, and count users active at any point in each window. This is often the most honest choice for weekly or monthly tools, because it forgives a quiet day without pretending an absent month does not matter. Whichever you pick, define "active" as doing something valuable, not simply opening the app. ### Reading a cohort retention table A cohort retention table groups users by when they signed up and shows the share still active at each later interval. An illustrative example with made-up numbers, using weekly bracket retention: | Sign-up week | Users | Week 1 | Week 2 | Week 4 | Week 8 | |---|---|---|---|---|---| | 1 June | 310 | 44% | 35% | 29% | 26% | | 8 June | 285 | 46% | 37% | 31% | 28% | | 15 June | 330 | 52% | 42% | 36% | not yet | | 22 June | 295 | 51% | 41% | not yet | not yet | Three ways to read it: - **Reading along a row** shows how one cohort decays. Here each cohort drops fast in the first weeks and then levels off, which is what a product with real users looks like. A row that keeps falling towards zero is a warning sign. - **Reading down a column** compares cohorts at the same age. Week 1 retention jumped from the 15 June cohort, so it is worth checking what shipped that week. - **Reading the diagonal** shows everyone's activity in the same calendar week, which helps spot outages, seasonality or a marketing email that briefly brought people back. In GA4, a Cohort exploration builds this kind of table from any event you choose as the inclusion and return conditions. ### Net revenue retention Net revenue retention (NRR) measures how much recurring revenue you keep from an existing group of customers over a period, counting upgrades as well as losses. New customers are excluded. ``` NRR = (start MRR + expansion - contraction - churned MRR) / start MRR ``` A worked example over a year, for customers who were paying £10,000 a month at the start: - Expansion (extra seats and upgrades): £2,000 - Contraction (downgrades): £500 - Churned (cancellations): £1,000 - NRR = (10,000 + 2,000 - 500 - 1,000) / 10,000 = **105%** Above 100% means the customers you already had are worth more than they were a year ago, even after losses. That is why seat-based and usage-based products track it so closely: a business with NRR above 100% keeps growing revenue from its existing base even with no new sales. Gross revenue retention (GRR) uses the same inputs without expansion: (10,000 - 500 - 1,000) / 10,000 = 85%. GRR can never exceed 100%, and it shows how much revenue leaks out before upsells mask it. Report both. ### Customer retention vs user retention The two are easy to mix up, and they often move in different directions. **Customer retention** counts accounts that are still paying. It is a finance and revenue measure, and it is what the formula at the top of this page calculates. **User retention** counts people who are still actively using the product. It is a product measure, and it usually leads customer retention: users drift away first, and the account cancels at the next renewal. In a B2B product the gap can be large. A company account can stay paid for months while only one of its twenty seats is active. That account looks retained in the billing data and is quietly at risk. Tracking seat-level activity inside each account gives you warning before the renewal conversation. In a consumer product the two are closer, but free users complicate things. Decide whether your headline figure covers paying customers only or all active users, and label every chart so nobody compares one with the other. ### How OpenHelm helps Retention is easy to measure once and hard to keep watching. In OpenHelm, a journey analyst agent maps your product's key user journeys from GA4 events and files a task, with the evidence, wherever users stall. Funnels, retention and audience appear as charts and data tables that the agents keep current, alongside the rest of the work being done on the product. If the product has no analytics at all, OpenHelm files a task and can create the GA4 property and data stream for you, then wire the measurement ID into your deployment. Because the analyst reads the same events every time it runs, a new stall shows up as a task with the numbers attached rather than being spotted by chance a month later. See [user funnels](/user-funnels). ## Churn rate: how to calculate it, read it and reduce it Source: https://www.openhelm.ai/guides/churn-rate (updated 2026-09-24) Churn rate is the share of customers, or revenue, you lose over a period, calculated as the number lost during the period divided by the number you had at the start. If you begin the month with 400 customers and 12 cancel, your monthly churn rate is 12 / 400 = 3%. | Metric | Formula | Use it for | | --- | --- | --- | | Customer (logo) churn | Customers lost in period / customers at start of period | How many accounts leave, regardless of size | | Gross revenue churn | (Churned MRR + contraction MRR) / MRR at start of period | Revenue lost from existing customers, ignoring upsells | | Net revenue churn | (Churned MRR + contraction MRR - expansion MRR) / MRR at start | Whether existing customers grow or shrink in total | | Annual churn from monthly | 1 - (1 - monthly churn) ^ 12 | Comparing a monthly figure with an annual one | | Cohort churn | Share of a sign-up cohort lost by month N | Seeing whether newer customers stay longer than older ones | | Retention rate | 1 - churn rate, for the same customers and period | The same fact framed as who stayed | ### How to calculate churn rate: a worked example The basic customer churn formula is: ``` churn rate = customers lost during the period / customers at the start of the period ``` Say a subscription product starts March with 400 paying customers. During March, 30 new customers sign up and 12 existing customers cancel, so it ends the month with 418. - Customers lost: 12 - Customers at the start: 400 - Monthly churn rate: 12 / 400 = **3%** Notice that the 30 new customers play no part. Churn measures what happened to the customers you already had. If you divide by the end-of-month figure (418) you get about 2.9%, and if a new customer signs up and cancels within the same month, some teams count them and some do not. None of these choices is wrong, but mixing them is. Write down your definition, including what counts as "lost" (cancelled, lapsed after a failed payment, downgraded to free), and use it every month so the trend means something. For products with a lot of mid-month movement, some teams divide by the average of the start and end counts instead. That is fine too, as long as you stick with it. ### Logo churn vs revenue churn Logo churn counts customers. Revenue churn counts money. They can tell very different stories. Losing ten customers on your smallest plan and losing one customer on your largest plan might cost the same revenue, but the first looks far worse on logo churn. The reverse is also true: a healthy logo churn can hide the loss of your biggest account. Revenue churn usually comes in two forms. Here is a worked example for a product starting the month on £20,000 of monthly recurring revenue (MRR): - Churned MRR (customers who cancelled): £600 - Contraction MRR (customers who downgraded): £200 - Expansion MRR (upgrades and extra seats): £1,000 **Gross revenue churn** = (600 + 200) / 20,000 = **4%**. This is what you lost before any upsell, and it can never be negative. **Net revenue churn** = (600 + 200 - 1,000) / 20,000 = **-1%**. A negative figure means expansion from existing customers more than covered what you lost. This is often called negative churn, and it is the reason seat-based products watch net figures closely. Track both. Gross churn tells you how leaky the product is; net churn tells you whether the customers who stay are growing. ### Converting monthly churn to annual churn You cannot multiply monthly churn by 12. Each month you lose a percentage of a smaller base, so the losses compound rather than add up. The conversion is: ``` annual churn = 1 - (1 - monthly churn) ^ 12 ``` With 3% monthly churn: 1 - 0.97 ^ 12 = 1 - 0.694 = about **30.6%** a year, not 36%. Going the other way, from an annual figure to its monthly equivalent: ``` monthly churn = 1 - (1 - annual churn) ^ (1 / 12) ``` Two cautions. First, this assumes churn is steady across the year, which it rarely is; new customers tend to churn faster than long-standing ones. Second, customers on annual contracts can only leave at renewal, so a monthly churn rate calculated across a mixed base will look low for eleven months and spike in the twelfth. Report monthly and annual plans separately if you sell both. ### Use cohort analysis to see where churn comes from A single churn rate blends customers who joined last week with customers who have been around for three years. Cohort analysis separates them by grouping customers by the month they signed up and tracking each group over time. An illustrative cohort table (made-up numbers, showing cumulative share of each cohort that has cancelled): | Sign-up month | Customers | After 1 month | After 3 months | After 6 months | |---|---|---|---|---| | January | 120 | 9% | 18% | 26% | | February | 140 | 8% | 15% | 22% | | March | 150 | 5% | 11% | not yet | Reading down a column tells you whether newer customers are churning less at the same age. Here, March's first-month churn is lower, which might be the effect of an onboarding change shipped that month. Reading along a row tells you when customers leave. If most of the churn happens in month one, the problem is activation and onboarding. If it builds steadily, the product is not holding value over time, and the fix is different. You can also build behavioural cohorts, such as customers who did or did not complete a key action in their first week, to test which behaviours predict staying. ### Exit surveys and cancellation flows Numbers tell you how many people leave. Only customers can tell you why. ### Exit surveys Ask one required multiple-choice question at cancellation, with a free-text box after it. Keep the options concrete: too expensive, missing a feature, switched to another tool, no longer need it, too hard to use, temporary pause. Review the free text every month, not just the counts, because the most useful answers rarely fit a box. ### Cancellation flows A good cancellation flow offers a genuine alternative to the reason given: a pause for someone who is away, a cheaper plan for someone on a budget, a link to the missing feature if it exists. A bad one hides the cancel button or makes people phone in. That is a dark pattern, it damages trust, and regulators in the UK, EU and US have all taken an interest in how hard subscriptions are to cancel. ### Involuntary churn Some customers leave without deciding to, because a card expired or a payment failed. Retrying failed payments on a sensible schedule, emailing before a card expires and making it easy to update payment details can recover a meaningful share of these without any change to the product. ### How OpenHelm helps Much churn starts long before cancellation, when a new customer stalls in onboarding or hits the same problem twice. OpenHelm's journey analyst maps your product's key journeys from GA4 events and files a task with the evidence wherever users stall, and funnels and retention appear as charts in the same place. See [user funnels](/user-funnels). On the support side, each product gets a real inbox where a triage agent answers from what the product actually does and hands defects to the engineering agent, so a frustrated customer's bug report becomes a fix rather than a cancellation reason. You choose how much it does alone: an inbox can hold agent replies for your approval, send and notify you, or send automatically. See [customer support](/customer-support). ## Product market fit: what it means and how to measure it Source: https://www.openhelm.ai/guides/product-market-fit (updated 2026-09-24) Product market fit means a clearly defined group of customers wants your product enough to keep using it, pay for it and tell others about it without you pushing. The two most practical measures are the Sean Ellis test, where 40% or more of active users say they would be very disappointed without the product, and retention curves that flatten out instead of sliding towards zero. | Signal | How to measure it | What a good sign looks like | | --- | --- | --- | | Sean Ellis test | Survey active users: how would you feel if you could no longer use the product? | 40% or more answer "very disappointed" | | Retention curve | Share of each sign-up cohort still active week by week | The curve flattens to a stable level above zero | | Activation | Share of new sign-ups reaching the activation event | Rising as onboarding improves, without the curve dropping later | | Organic growth | Share of new users arriving by word of mouth, direct visits and search | Growing without a matching rise in paid spend | | Sales effort | Time and effort needed to close a customer | Shortening, with buyers arriving already convinced | | Qualitative pull | Support messages, feature requests, reaction to outages | People complain loudly when it breaks and ask for more | ### The Sean Ellis 40% test Sean Ellis, the growth marketer who coined the term "growth hacking", proposed a one-question survey: > How would you feel if you could no longer use this product? The answers are "very disappointed", "somewhat disappointed", "not disappointed" and "I no longer use it". His rule of thumb, drawn from comparing results across many startups, is that products where 40% or more answer "very disappointed" tend to find it much easier to grow. Treat the 40% as a useful line, not a law. How to run it well: - **Survey the right people.** Ask users who have experienced the core of the product, used it recently and used it more than once. Surveying everyone who ever signed up drags the score down with people who never activated. - **Wait for enough answers.** With a handful of responses, one or two people swing the result. Aim for a few dozen at minimum before reading much into it. - **Ask the follow-ups.** What is the main benefit you get? What type of person would benefit most? How could we improve it? The "very disappointed" group's answers tell you who your product is really for and what to protect. The score is most useful as a trend. Run it every quarter and segment it: a 25% overall score can hide a 50% score in one customer type, which is where to focus. ### Retention curves that flatten Surveys measure what people say. Retention measures what they do, which makes it the harder evidence. Plot a retention curve for each monthly sign-up cohort: the share of the cohort still active in week 1, 2, 3 and onwards. Every product loses people early. The question is what happens next. - **Curve slides towards zero.** Nearly everyone eventually leaves. Growth only continues while you pour new users in at the top. This is the clearest sign fit is not there yet. - **Curve flattens.** After an early drop, a stable share of each cohort keeps using the product month after month. That flat section is a group of people for whom the product works. - **Curve rises slightly over time.** Some users come back after lapsing, or usage deepens. This is rare and a strong signal. Two practical notes. Define "active" as doing the valuable thing, not just logging in; a login can be a user looking for the cancel button. And compare cohorts: if newer cohorts flatten at a higher level than older ones, the product is moving towards fit even if the overall numbers look flat. ### Activation and qualitative signals Retention tells you whether people stay. Activation tells you whether they get far enough to find out. If only a small share of sign-ups reach the product's core action, a weak retention curve may be an onboarding problem rather than a product problem. Find your activation event (see the [aha moment guide](/guides/aha-moment)) and check what share of new users reach it before judging fit. The qualitative signals are harder to chart but often arrive first: - Customers describe the product to others in words you did not give them. - Support messages shift from "how do I" to "can it also". - Users build workarounds to make the product do more than it was designed for. - An outage produces a flood of messages rather than silence. - Sales conversations get shorter because prospects already know what they want. - People who churned come back without being chased. Write these down as they happen, with dates. A log of real customer quotes is far more convincing to you and to anyone you are raising from than a general sense that things are going well. ### What product market fit is not Several things look like fit and are not. - **A launch spike.** A burst of sign-ups from a launch or a viral post measures curiosity. Check the retention curve for those cohorts a few months later. - **Revenue bought with discounts or paid acquisition.** If growth stops the moment spend stops, you have a marketing channel, not pull. - **One large customer.** A single enthusiastic account can carry the numbers, and its needs may not be anyone else's. - **Praise from friends, investors or other founders.** They are not the people who will pay. - **Feature requests alone.** People asking for more can mean they love it or that it does not yet do enough to be useful. Retention tells you which. - **A permanent state.** Markets move, competitors arrive and customer needs change. Fit you had two years ago needs checking again. Fit is also specific. It is fit between a product and a particular group of customers, which is why segmenting both the survey and the retention curve matters more than any single headline number. ### Keeping the evidence current The hardest part of judging fit is that the evidence goes stale. A survey from last spring and a retention chart someone built once in a spreadsheet will not tell you whether this month's cohorts are doing better. OpenHelm's journey analyst maps your product's key user journeys from the product itself and its GA4 events, and files a task with the evidence wherever users stall. Funnels, retention and audience appear as charts and data tables that the agents keep updated, so you are looking at current cohorts rather than an old export. If the product has no analytics yet, OpenHelm files a task and can create the GA4 property and data stream and wire the measurement ID into your deployment. The survey and the qualitative log are still yours to run, but the behavioural half of the evidence stays up to date without anyone rebuilding a spreadsheet. See [user funnels](/user-funnels). ## North star metric: what it is and how to choose yours Source: https://www.openhelm.ai/guides/north-star-metric (updated 2026-09-24) A north star metric is the single measure that best captures the value customers get from your product, chosen so that when it grows, long-term revenue tends to grow with it. It should be a leading indicator the whole team can influence, such as weekly active projects with at least one collaborator for a collaboration tool, and it is driven by a small set of input metrics. | Business model | Example north star metric | Example input metrics | | --- | --- | --- | | Collaboration tool | Weekly active projects with at least one collaborator | Projects created, invites sent, invites accepted | | Marketplace | Transactions completed per week | New listings, searches that return results, repeat buyers | | B2B analytics tool | Accounts viewing a report on their own data each week | Data sources connected, reports created, active seats per account | | Content or media | Weekly engaged reading or viewing time | Pieces published, returning visitors, newsletter sign-ups | | E-commerce | Repeat purchases per month | First orders, on-time deliveries, returns rate | | Developer tool or API | Successful API calls from active accounts | Sign-ups making a first call, integrations live, error rate | ### What makes a good north star metric A north star metric gives everyone on a team the same answer to "is the product getting more useful to more people?" It is not a replacement for revenue or for every other number you track. It is the number you reach for when two priorities compete. A good one passes most of these tests: - **It reflects value delivered to customers**, not value extracted from them. Time spent in an app can rise because the app is confusing; projects shipped with it rarely do. - **It leads revenue.** When it rises this quarter, revenue should tend to rise later. - **The team can move it.** Product, engineering, marketing and support should each be able to name something they could do to push it up. - **It is measurable often.** Weekly is ideal. A metric you can only calculate once a year cannot steer anything. - **It is simple to say.** If it takes a paragraph to explain, people will not use it to make decisions. - **It is hard to game.** Counting sign-ups invites low-quality sign-ups. Counting activated accounts is harder to inflate. Most good north star metrics combine a unit of value (a project, a transaction, a report) with a sign it was real (a collaborator, a completion, a return visit) and a time frame (weekly, monthly). ### Leading vs lagging indicators Revenue, churn and profit are **lagging** indicators. They are accurate, but they report the past. By the time monthly revenue dips, the customers who caused it stopped getting value weeks or months earlier. A north star metric should be a **leading** indicator: a measure of behaviour that happens before the money moves. Customers who get value keep paying, expand and refer others. Customers who stop getting value leave at the next renewal. This is why revenue itself usually makes a poor north star, even though it is what the business ultimately needs. It moves too late to act on, and it can be pushed up in ways that damage the product, such as raising prices or cutting a free tier, which feel like progress until churn catches up. Keep watching the lagging numbers. They confirm whether your leading indicator is the right one. If the north star metric has been climbing for two quarters and revenue has not followed, the metric is measuring something customers do not value enough to pay for, and it needs changing. ### Build an input metrics tree A north star metric is too broad for any one team to own. Input metrics break it into parts a team can work on directly. A common way to split it is into breadth, depth, frequency and efficiency. For a collaboration tool whose north star is weekly active projects with at least one collaborator, the tree might look like this: ``` Weekly active projects with at least one collaborator ├── Breadth: new projects created per week │ └── sign-ups who create a first project within 7 days ├── Depth: share of projects with a second member │ ├── invites sent per new project │ └── invite acceptance rate ├── Frequency: projects with activity on 2 or more days a week │ └── notifications that bring collaborators back └── Efficiency: time from sign-up to first shared project ``` Each branch should be something a team can change with a specific piece of work: a shorter onboarding flow moves efficiency; better invite emails move depth. Keep the tree small: three to five input metrics will do. If you have fifteen, you do not have a north star, you have a dashboard. ### How to choose yours 1. **Write down the value in one sentence.** What does a customer get when the product works? "Teams ship work together in one place" is a start. 2. **Find the moment that value happens.** Which action in your event data shows it actually occurred? This is often close to your activation event (see the [aha moment guide](/guides/aha-moment)). 3. **Add a quality bar and a time frame.** "Projects" becomes "projects with at least one collaborator, active this week". 4. **Check it against retention and revenue.** Using past data, confirm that accounts scoring high on the candidate metric retain and expand more than those scoring low. 5. **Draft the input tree.** If you cannot name three levers that move it, it is either too abstract or too narrow. 6. **Agree it and publish it.** Put it at the top of the weekly review with its input metrics underneath, and give each input metric an owner. 7. **Review it yearly.** Products change. A metric that suited a single-player tool may not suit it once teams are the main buyers. ### Common pitfalls - **Choosing a vanity metric.** Total sign-ups, page views or downloads only ever go up and say little about value. - **Picking a ratio.** Conversion rates and percentages can improve while the business shrinks, for example when fewer, better-qualified visitors arrive. Prefer counts, and track ratios as inputs. - **Using revenue.** It lags, and it is easy to raise in ways that hurt customers. - **Having several north stars.** Two headline metrics that pull in different directions put you back where you started. - **Changing it every quarter.** Teams stop trusting it. Change it deliberately, when evidence shows it no longer predicts retention or revenue. - **Forgetting the guardrails.** Pair the north star with a few measures that must not get worse, such as support volume, error rate or refund rate, so it cannot be hit at the product's expense. - **Measuring it by hand.** A metric someone recalculates in a spreadsheet when they remember will not steer anything. ### How OpenHelm helps OpenHelm has data tables that agents read and write, with charts, so a north star and its input metrics can sit next to the work meant to move them. Each agent carries goals with machine-checkable criteria, and every run is judged by a separate evaluator against the job's outcome contract, so progress is measured against the numbers rather than against an agent's own account of what it did. The journey analyst also maps your key journeys from GA4 events and files a task wherever users stall. Anything risky still waits for your approval, so the metric steers the agents without handing them the keys. Keeping the north star next to the work also makes it easier to notice when a busy week of activity did not move it at all. See [the platform](/platform) and [user funnels](/user-funnels). ## Postmortem template: a blameless incident postmortem you can copy Source: https://www.openhelm.ai/guides/postmortem-template (updated 2026-09-24) A postmortem template is a fixed structure for writing up an incident once it is resolved: a summary, the impact, a timeline, the root cause and contributing factors, and action items that each have an owner and a due date. Write it blamelessly, asking how the system and process allowed the failure rather than who made the mistake, and finish it within a few days while memories are fresh. | Section | What to include | Why it matters | | --- | --- | --- | | Summary | Two or three sentences: what broke, for how long, who was affected | Anyone can understand the incident in seconds | | Impact | Users affected, duration, errors, data loss, revenue or SLA effects | Sets the severity and how urgent the follow-ups are | | Timeline | Timestamped events from first signal to full resolution, with time zone | Shows gaps in detection, response and communication | | Root cause and contributing factors | The technical trigger plus the conditions that let it cause harm | Stops the same class of failure from happening again | | What went well and what did not | Detection, alerting, runbooks, tooling, communication | Improves the response, not only the code | | Action items | Specific tasks, each with one owner, a due date and a ticket link | Turns the review into real change | ### What a blameless postmortem is A postmortem (also called an incident review or post-incident review) is a written account of an incident and of what the team will change because of it. It is written after the incident is resolved, not during it. **Blameless** means the document looks for causes in systems and processes, not in people. The assumption is that everyone involved acted reasonably given what they knew at the time. If an engineer ran a command that took the database down, the useful questions are why that command was possible, why nothing warned them, and why recovery took as long as it did. This is not about being kind for its own sake. People who expect blame stop reporting near misses, leave out awkward details and fix symptoms quietly. People who expect a fair review tell you what really happened, which is the only way to find the real causes. A few habits help: - Name roles or systems in the timeline ("the on-call engineer", "the deploy pipeline") rather than individuals. - Replace "should have" with "what would have made the right action easier?" - Hold a short review meeting, but treat the written document as the record. - Share the finished incident postmortem widely. Others learn from it, and customers often appreciate a public version. ### The postmortem template Copy this into your docs tool or repository and fill it in. Delete any section that genuinely does not apply rather than writing "N/A" everywhere. ```markdown # Postmortem: [short incident title] Date of incident: YYYY-MM-DD Authors: [names or roles] Status: Draft / In review / Final Severity: [SEV1 / SEV2 / SEV3] ## Summary [2 to 3 sentences: what broke, for how long, who was affected, how it was fixed.] ## Impact - Duration: [start time to end time, with time zone] - Users or customers affected: [number or share] - Symptoms: [errors, slowness, data issues] - Data loss: [yes / no, details] - Business impact: [revenue, SLA credits, support volume] ## Timeline (all times in [time zone]) - HH:MM [First signal, e.g. alert fired or customer report] - HH:MM [Incident declared, responder assigned] - HH:MM [Key diagnosis steps and decisions] - HH:MM [Mitigation applied] - HH:MM [Service restored and confirmed] ## Root cause [The technical trigger, in plain language.] ## Contributing factors - [Condition that allowed the trigger to cause harm] - [Gap in testing, monitoring, process or documentation] ## Detection [How we found out, and how we could have found out sooner.] ## What went well - [...] ## What did not go well - [...] ## Where we got lucky - [...] ## Action items | Action | Type (prevent / detect / mitigate) | Owner | Due date | Ticket | |---|---|---|---|---| | [...] | [...] | [...] | [...] | [...] | ## Lessons learned [Anything worth sharing beyond this team.] ``` ### Writing the incident timeline The timeline is the backbone of the postmortem. Build it from records, not memory: alert history, deploy logs, error tracker events, chat messages in the incident channel and status page updates. - **Use one time zone** and say which at the top. Mixing UTC and local time is an easy mistake to make. - **Start before the incident was declared.** The first sign is often earlier than anyone realised: a warning in the logs, a spike in one error, a single customer email. The gap between first signal and declaration is one of the most useful things a postmortem can reveal. - **Record decisions, not just events.** "14:12 rolled back the deploy" is an event. "14:12 rolled back because error rates matched the deploy time; the migration was not yet suspected" explains why the next step was taken. - **Mark the key moments** so you can measure them: first signal, detection, response started, mitigated, resolved. - **Keep it factual.** Opinions and analysis belong in the root cause and contributing factors sections. From the timeline you can read off time to detect, time to mitigate and time to resolve. Tracking these across incidents shows whether your response is improving. ### Finding the root cause: five whys and contributing factors The **five whys** technique starts from the failure and asks "why?" repeatedly until you reach something you can change. Five is a guide, not a rule. 1. Why did checkout fail? The payment service returned errors. 2. Why? It could not reach its database. 3. Why? The connection pool was exhausted. 4. Why? A new background job opened connections and never released them. 5. Why was that not caught? The test environment runs with a far smaller workload, so the leak never filled the pool before tests finished. The last answer points at a fix that prevents a whole class of problem, not just this bug. Five whys has a known weakness: it produces a single chain, and real incidents rarely have one cause. Complex systems usually fail when several conditions line up. That is why many teams now record **contributing factors** alongside the root cause: the missing alert, the runbook that was out of date, the deploy that went out late on a Friday, the dashboard nobody checked. Each one is a place where the incident could have been prevented, caught sooner or made smaller. Stop asking why when the answer becomes "a person made a mistake". Ask instead what would have made the mistake impossible or harmless. ### Action items that actually get done A postmortem without completed action items is a story, not an improvement. Most teams find the writing easy and the follow-through hard. - **One owner per action.** A named person, not a team. Shared ownership usually means no ownership. - **A due date.** Urgent fixes in days, structural changes within a planned period. Without a date the item drifts behind feature work. - **A ticket.** Put each action in your normal issue tracker, linked from the postmortem, so it competes for priority like any other work. - **Specific and checkable.** "Improve monitoring" cannot be closed. "Alert when connection pool usage exceeds 80% for five minutes" can. - **A mix of types.** Label each as prevent, detect or mitigate. If every action is "prevent", you have not planned for the next incident that gets through. - **Few enough to finish.** Three to five well-chosen actions beat fifteen that nobody completes. Review open postmortem actions at a regular meeting until they are closed, and note in the document when each one ships. ### Worked example (fictional incident) _This is a made-up incident for illustration. The company, times and numbers are fictional._ **Summary.** On a Tuesday, sign-ups failed for 47 minutes because a configuration change removed the email provider's API key from production. New users saw an error on the final step. Rolling back the change restored service. **Impact.** 47 minutes. Roughly 130 sign-up attempts failed, and about 40 of those users retried successfully after the fix. No data was lost. **Timeline (UTC).** - 10:02 Configuration change deployed to rename environment variables. - 10:05 First customer email reports "error at the last step". - 10:31 Error tracker alert fires once the error count passes its threshold. - 10:36 On-call engineer links the errors to the 10:02 deploy. - 10:49 Rollback deployed and sign-ups confirmed working. **Root cause.** The rename changed the variable's name in code but not in the production environment settings, so the email client started without a key. **Contributing factors.** No startup check for required variables; the alert threshold was too high for a low-volume flow; the customer email sat in a shared inbox for 26 minutes. **Action items.** Fail the deploy if a required variable is missing (owner: platform lead, 2 weeks). Alert on any sign-up error, not a count (owner: on-call lead, 1 week). Route error reports from support straight to on-call (owner: support lead, 1 week). ### How OpenHelm handles the incident itself OpenHelm runs an incident agent for each live product. A Sentry issue, or a customer's bug report by email, wakes it straight away. It first checks the report is real, made in good faith and not in conflict with a decision already made, then reproduces the problem, fixes it, tests, deploys, verifies the fix in production and resolves the issue. If the fix is merged but not yet live, it leaves the issue open with a comment. If it cannot fix it, it files one task with what it found. A separate verifier judges each run from its tool-call record rather than from the agent's own summary. Each run also keeps a timestamped log, which is a useful starting point when you write the timeline for your postmortem. See [bug fixing](/bug-fixing). # Documentation ## Getting Started ### Installation Source: https://www.openhelm.ai/docs/installation ## System Requirements - macOS 13 (Ventura) or later - Apple Silicon or Intel Mac - Claude Code v2.0.0 or later, installed and authenticated No other dependencies required, the app is fully self-contained. ## Download Download the correct build for your Mac from the [releases page](https://github.com/maxbeech/openhelm/releases): - **Apple Silicon (M1/M2/M3/M4):** `OpenHelm_0.1.0_aarch64.dmg` - **Intel Mac:** `OpenHelm_0.1.0_x64.dmg` If you're unsure which chip you have: Apple menu → About This Mac → look for "Apple M" (Silicon) or "Intel" in the chip/processor line. ## Install 1. Open the downloaded `.dmg` file 2. Drag **OpenHelm** into your **Applications** folder 3. Launch from Applications (or Spotlight) On first launch, macOS may show a security prompt for an unverified developer. If that happens: System Settings → Privacy & Security → scroll to the Security section → click **Open Anyway**. ## Setting Up Claude Code OpenHelm requires Claude Code to be installed and authenticated on your machine. 1. [Install Claude Code](https://claude.ai/code) if you haven't already 2. Run `claude` in your terminal at least once to complete authentication 3. On first launch, OpenHelm auto-detects Claude Code in your PATH, Homebrew, and global npm paths If Claude Code is installed in a non-standard location, go to **Settings → Claude Code Path** and set the path manually. ## Verify Setup On first launch, OpenHelm shows a setup screen. Once Claude Code is detected and a green checkmark appears next to the version, you're ready to create your first project. ## Uninstall Drag **OpenHelm** from your Applications folder to the Trash. All app data is stored in `~/Library/Application Support/ai.openhelm.app/`, delete this directory to fully remove all data. ### Quick Start Source: https://www.openhelm.ai/docs/quick-start ## 1. Create a Project A project links OpenHelm to a directory on your Mac. Click **New Project** in the sidebar, give it a name, and select the directory Claude Code will work in. ## 2. Set a Goal Click **New Goal** and describe what you want in plain English. OpenHelm uses AI to turn your description into a structured job plan, or you can skip the planner and create jobs manually. **Using the AI planner:** Type your goal (e.g., "Run weekly SEO audits on my website and fix any issues found") and click **Generate Plan**. The AI creates a structured job plan with suggested schedules. Review each job, tweak if needed, then click **Approve Plan**. **Creating jobs manually:** Click **Build manually** to create jobs directly, write your prompt, pick a schedule type, and save. ## 3. Jobs Run on Schedule Once approved, jobs run automatically according to their schedules. A job set to run daily at 2am will fire at 2am, the app can run in the background while you're away. > **Note:** OpenHelm's scheduler runs while the app is open. Your Mac must also be awake when a job is scheduled to fire. For reliable unattended automation, keep your Mac plugged in and configure Energy Saver to prevent sleep, or use a Mac that stays on (Mac mini, Mac Studio). ## 4. Monitor Runs Click any job to see its run history, status, duration, logs, and exit code. Failed runs surface in the **Inbox** tab with options to retry, adjust, or dismiss. ## 5. Trigger a Run Immediately To test a job right now, click **Run now** on any job. The run is queued at highest priority and starts within the next scheduler tick (up to 60 seconds). ### Requirements Source: https://www.openhelm.ai/docs/requirements ## Claude Code Requirements OpenHelm runs Claude Code as its execution engine. You need: - Claude Code **v2.0.0 or later** - An active Anthropic account with API access - Claude Code authenticated (`claude` must work in your terminal) OpenHelm auto-detects Claude Code in the following locations: - System `PATH` - Homebrew (`/opt/homebrew/bin/claude`, `/usr/local/bin/claude`) - Global npm installations If your Claude Code binary is in a custom location, set it manually in **Settings → Claude Code Path**. ## macOS Permissions OpenHelm is a standard macOS desktop application. On first launch, macOS may request: - **Notifications** (optional), to notify you when jobs complete or fail No other special permissions are required. ## Hardware - macOS 13 (Ventura) or later - Apple Silicon (M1 or later) or Intel Mac - Recommended: 8 GB RAM when running multiple jobs concurrently ## Running Jobs Unattended OpenHelm's scheduler runs while the app is open. For fully automated background execution: - Keep the app running in the background, it uses minimal resources when idle - Ensure your Mac does not sleep during scheduled job windows - For reliable overnight automation, use a Mac that stays on (Mac mini, Mac Studio), or configure your MacBook's Energy Saver settings to prevent sleep when plugged in ## For Developers ### API Quickstart Source: https://www.openhelm.ai/docs/api-quickstart OpenHelm gives AI agents and your own backend a single place to run **hard, multi-step jobs**, work that takes minutes, hours, or runs on a schedule. Two front doors share one engine: - **REST API** (`/v1`), call it server-to-server from your product. - **MCP servers**, connect a remote URL from ChatGPT, Claude or Cursor (see [MCP servers](/docs/mcp-servers)). Both run work in isolated cloud sandboxes and return the same structured, evidence-backed result. ## 1. Get a key Create a Bearer key (`oh_live_…`) under **Settings → API & Webhooks** in your OpenHelm account. The key is shown once. ## 2. Run a task in one call ```bash curl https://api.openhelm.ai/v1/runs \ -H "Authorization: Bearer oh_live_..." \ -H "Content-Type: application/json" \ -d '{ "prompt": "Get the pricing tiers from stripe.com", "output_schema": { "type": "object", "properties": { "tiers": { "type": "array", "items": { "type": "string" } } } } }' ``` > The base URL shown in the [live API reference](/docs/api) is the source of truth, it is generated from the deployed OpenAPI spec. The response is **202 Accepted** with a `task_id`, a `poll_url`, and a `billing` cost estimate: ```json { "task_id": "run_2x9f4c...", "poll_url": "https://api.openhelm.ai/v1/runs/run_2x9f4c...", "billing": { "model": "sonnet", "estimated_cost_usd": { "low": 0.05, "high": 0.3 } } } ``` ## 3. Collect the result Poll `GET /v1/runs/{id}` until `status` is terminal, or supply a `callback_url` to get a webhook instead (see [Long-running & recurring jobs](/docs/long-running-jobs)). The completed envelope carries your structured `result`, `evidence`, `confidence`, and `usage.cost_usd`. ## What next - [Authentication & API keys](/docs/authentication) - [Runs & the result envelope](/docs/runs-and-results) - [Connections API](/docs/connections-api), give a task the credentials it needs - [Pricing & credits](/docs/pricing-credits) ### Authentication & API keys Source: https://www.openhelm.ai/docs/authentication Every `/v1` request authenticates with a Bearer API key. ``` Authorization: Bearer oh_live_... ``` ## Keys - Mint, name, and revoke keys under **Settings → API & Webhooks** (org owners/admins). - Keys are **org-scoped**. The full secret is shown once; OpenHelm stores only its SHA-256 hash. - `oh_live_…` runs against your real plan; `oh_test_…` is for test wiring. - Each key carries a **webhook signing secret** used to verify completion webhooks. ## Guardrails on a key - **Monthly cap**, set `monthly_cap_usd` per key; spend beyond it returns `402`. - **Project allowlist**, scope a key to specific projects. ## The MCP servers reuse your key When you connect an [MCP server](/docs/mcp-servers), the "Connect with OpenHelm" OAuth flow wraps your encrypted key in a signed token. The servers are stateless and store no secrets. ## Errors HTTP `4xx/5xx` is reserved for request, auth, and quota problems (`401` invalid key, `402` quota/subscription gate, `403` out-of-scope, `429` too many concurrent runs). A **task** that fails returns `200`/`202` with a structured `failure_reason`, see [Runs & the result envelope](/docs/runs-and-results). ### Runs & the result envelope Source: https://www.openhelm.ai/docs/runs-and-results ## Starting a run - `POST /v1/runs`, an **inline run** from a prompt (the one-call primitive). - `POST /v1/jobs/{id}/runs`, run a **saved job** (a reusable template whose prompt carries `{{placeholders}}`). Body fields: `prompt` (or the job's), `inputs` (fills `{{placeholders}}`), `output_schema` (JSON Schema for the shape you want back), `model` (`haiku` | `sonnet` | `opus`, default `sonnet`), `project_id` (optional, defaults to your org's auto-created **API Runs** project), `callback_url`, and `idempotency_key`. ## The result envelope `GET /v1/runs/{id}` returns: ```json { "task_id": "run_...", "status": "queued | running | succeeded | failed | cancelled", "result": { /* your output_schema shape, or null */ }, "confidence": "high | medium | low | null", "evidence": { "screenshot_url": "…7-day signed URL…", "matched_text": "…", "checked_at": "…" }, "failure_reason": "captcha | auth_required | site_down | timeout | ambiguous | not_found | null", "usage": { "duration_ms": 0, "input_tokens": 0, "output_tokens": 0, "cost_usd": 0 }, "created_at": "…", "finished_at": "…" } ``` - **`result`** conforms to your `output_schema` on a best-effort basis. - **`evidence`** lets you verify what the agent actually saw. - **`failure_reason`** is explicit, OpenHelm never fabricates a result. `auth_required` means the task needed a [connection](/docs/connections-api) that isn't set up. - **`usage.cost_usd`** is the **actual billed cost** (the 202 `billing` block was only an estimate). ## Idempotency Pass `idempotency_key` to make retries safe, a replay returns the original run instead of starting a new one. ### Long-running & recurring jobs Source: https://www.openhelm.ai/docs/long-running-jobs OpenHelm runs are asynchronous. There are three ways to consume results, matched to how long the work takes. ## 1. Seconds, inline Fast tasks settle quickly. Over MCP, the tool call bounded-waits (~75s) and returns the result in one turn; if it isn't ready it returns a `task_id` and you call `check_result`. ## 2. Minutes to hours, poll or webhook `POST /v1/runs` returns **202** immediately with a `task_id` and `poll_url`. Either: - **Poll** `GET /v1/runs/{id}` until `status` is terminal, or - Supply a **`callback_url`** and receive an HMAC-signed webhook on completion. ### Verifying the webhook The body is `{ "event": "run.completed" | "run.failed", "data": }`. The signature header is Stripe-style: ``` X-OpenHelm-Signature: t=, v1= signed_payload = `${t}.${rawBody}` expected = HMAC_SHA256(api_key.signing_secret, signed_payload) ``` Reject anything that doesn't match, and de-dupe on `data.task_id` (deliveries can repeat). ## 3. Recurring, register once, receive forever Create a **scheduled job** (`schedule_type` of `interval`, `cron`, or `email`) and it fires your webhook on **every run**. A long-lived monitor (a daily briefing, an inbox watcher, a weekly report) streams results back for weeks with no polling. List a job's history with `GET /v1/runs?job_id=…`. > Tip: webhooks beat polling for anything time-sensitive. Acknowledge fast (2xx), then process out-of-band. ### Connections API Source: https://www.openhelm.ai/docs/connections-api A **connection** is a credential or tool a run can use, a Gmail account, a GitHub token, a remote MCP server, an OAuth provider. Provision them without the dashboard. ## Direct: token & MCP connections ```bash # Store an API key/secret (encrypted in Vault) curl https://api.openhelm.ai/v1/connections \ -H "Authorization: Bearer oh_live_..." -H "Content-Type: application/json" \ -d '{ "name": "GitHub PAT", "type": "token", "secret": "ghp_...", "env_var_name": "GITHUB_TOKEN" }' # Register a remote HTTP/SSE MCP server (headers may use ${SECRET}) curl https://api.openhelm.ai/v1/connections \ -H "Authorization: Bearer oh_live_..." -H "Content-Type: application/json" \ -d '{ "name": "Acme MCP", "type": "mcp", "url": "https://acme.example/mcp", "transport": "http", "headers": { "Authorization": "Bearer ${SECRET}" }, "secret": "..." }' ``` Scope a connection to one project with `project_id`, or omit it to make it available to all the account's runs. The stored secret is **write-only**, it is never returned by `GET /v1/connections`. ## Hosted link: OAuth providers Providers that need a browser (Google, Notion, LinkedIn…) can't be created from a raw key. Mint a short-lived link instead: ```bash curl https://api.openhelm.ai/v1/connections/links \ -H "Authorization: Bearer oh_live_..." -H "Content-Type: application/json" \ -d '{ "provider": "google" }' # → { "url": "https://www.app.openhelm.ai/connections?add=google&grant=…", "expires_at": "…" } ``` Open the URL (signed in to the account that owns the key), complete authorisation, then poll `GET /v1/connections` until it shows `auth_status: "authenticated"`. ## When a run needs a connection that isn't there The run fails with `failure_reason: "auth_required"`, OpenHelm tells you what's missing rather than guessing. Set up the connection and re-run. ### MCP servers Source: https://www.openhelm.ai/docs/mcp-servers The OpenHelm MCP servers wrap the same `/v1` engine so any MCP client can drive it, no code. They are remote, Streamable-HTTP servers; you add a URL. ## The servers | Server | URL | For | |---|---|---| | General-purpose | `https://mcp.openhelm.ai/main/mcp` | Raw run/job/connection primitives | | Deep research | `https://mcp.openhelm.ai/research/mcp` | Company diligence, filings, comps | | SEO & GEO | `https://mcp.openhelm.ai/seo/mcp` | Keyword + content + AI-citation | | Email outreach | `https://mcp.openhelm.ai/email/mcp` | Send + handle replies | | Dev changes | `https://mcp.openhelm.ai/dev/mcp` | Open PRs, review, deps | See each on the [MCP & API hub](/mcp). ## Connect - **ChatGPT / Claude / Cursor:** add the URL as a remote connector. Approve the "Connect with OpenHelm" prompt (a card starts your free trial). - **stdio-only clients (Claude Desktop):** bridge it: ```json { "mcpServers": { "openhelm": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.openhelm.ai/main/mcp"] } } } ``` ## Long-running tasks The servers bounded-wait ~75 seconds, then return a `task_id`; your assistant calls `check_result` to retrieve the finished output, so a connection never hangs mid-run. ### Pricing & credits Source: https://www.openhelm.ai/docs/pricing-credits API and MCP usage draws from the **same credits** as the rest of your OpenHelm plan, there is no separate developer bill. - **1 credit = $0.05** of billed cost (a 20% markup is included). - Every started run returns a `billing` **estimate** (per-model band + your monthly cap). The **actual** cost is `usage.cost_usd` on the completed run. - **Per-key monthly cap** (`monthly_cap_usd`) and an **org daily cap** bound spend defensively. - New accounts add a card to start a **free trial**, you're not charged during it. This protects shared cloud compute from multi-account abuse on the public MCP servers. Manage your plan and usage under **Settings → Plan** and **Settings → Usage**. ### Deep research guide Source: https://www.openhelm.ai/docs/guides/deep-research Deep research covers one-off diligence and recurring briefings, grounded in official sources (SEC EDGAR, the live web), never fabricated. ## From an assistant (MCP) Connect `https://mcp.openhelm.ai/research/mcp` and call tools like `deep_research_company`, `earnings_triage`, `build_comp_set`, `monitor_sec_filings`, or `morning_notes`. Longer runs return a `task_id`; call `check_result`. ## As a recurring monitor Adopt the **Hedge Fund Deep Research** or **Thesis-Aware Morning Briefing** strategy in the app, or create a `cron` job over the API and supply a `callback_url`, you'll get a webhook every morning. See [Long-running & recurring jobs](/docs/long-running-jobs). > Disclosed trades are lagged and outputs are not investment advice. ### SEO & GEO guide Source: https://www.openhelm.ai/docs/guides/seo-geo The SEO & GEO server automates organic growth across traditional search **and** AI answer engines. ## Tools Connect `https://mcp.openhelm.ai/seo/mcp`: `find_keyword_opportunities`, `keyword_research`, `write_seo_blog_post`, `audit_onpage_seo`, `audit_technical_seo`, `seo_progress_report`, plus GEO tools `track_ai_answer_visibility`, `optimize_content_for_ai_citation`, and `geo_competitor_mentions`. ## Connections GSC and keyword data need real connections, set up Google Search Console and Google Ads (see [Connections API](/docs/connections-api)). The agent uses **real data only**: if GSC isn't connected it says so and stops rather than inventing numbers. ## Recurring Adopt the **Free-Tools SEO Growth** strategy for weekly publishing, audits, and reports on a schedule. ### Email outreach guide Source: https://www.openhelm.ai/docs/guides/email-outreach Unlike an inbox API, OpenHelm **runs the conversation**: research, send, then triage and respond to replies. ## Tools Connect `https://mcp.openhelm.ai/email/mcp`: `research_recipient`, `draft_outreach_email`, `send_outreach_email`, `triage_inbox`, and `draft_reply`. ## Connections Set up an email connection (Gmail, or your org's `relay.openhelm.ai` identity) so the agent can send and read replies. Reply detection runs **before** any new send, and the agent escalates rather than guessing when a reply asks something it can't verify. ## Always-on Adopt the **Email Outreach & Reply Handling** strategy for recurring sequences and a scheduled reply sweep. Real data only, it never fabricates a recipient, a send, or a fact about your organisation. ### Dev changes guide Source: https://www.openhelm.ai/docs/guides/dev-changes Describe a change; an agent clones the repo, makes a focused edit, runs the project's tests, **pushes first**, and opens a PR. ## Tools Connect `https://mcp.openhelm.ai/dev/mcp`: `open_pull_request`, `propose_change`, `triage_issue`, `review_pull_request`, and `dependency_audit`. ## Connections Set up a **GitHub** connection (and, in cloud, the repo's git URL). The agent secures work by pushing before any heavy build, and opens one focused PR per change. ## Externalised fixes If a request can only be fixed outside the code, missing credentials, an ambiguous spec, a product decision, the agent **refuses and explains the external fix** rather than hacking around it. It never fabricates a PR URL or a passing test. ## Recurring Adopt the **Repo & Developer Changes** strategy for scheduled dependency upkeep and housekeeping PRs. ## Core Concepts ### Projects & Goals Source: https://www.openhelm.ai/docs/concepts/projects-and-goals ## Projects A project is a named workspace linked to a directory on your Mac. Claude Code runs within the project's directory, it can read and modify files there according to the jobs you define. Create a project from the sidebar: click **New Project**, give it a name, and select the directory. ## Goals A goal is a high-level objective you want to achieve in a project. Goals contain one or more jobs, scheduled tasks that Claude Code executes to work toward that objective. **Goal statuses:** - `active`, goal is live; its jobs run on schedule - `paused`, goal is temporarily suspended; no new runs start - `archived`, goal and all jobs are preserved but inactive ## AI-Generated Goals Describe your goal in plain English and let the AI planner structure it into a concrete job plan. The planner generates 2–6 jobs with suggested prompts, schedules, and rationale. You review the entire plan before anything runs, approve as-is, edit individual jobs, or start over. ## Manual Goals Skip the AI planner entirely and build your own job list. This is the right choice when you know exactly what you want to automate and don't need the AI to interpret your goal. ## Writing Effective Goal Descriptions The quality of the AI-generated plan depends on the clarity of your description. **Be specific about the outcome, not the steps:** ``` Good: "Run a weekly audit of the /blog section for broken links, outdated content, and missing meta descriptions. Create a GitHub issue summarising each finding." Less useful: "Check my website" ``` **Include relevant constraints:** - "Don't touch files in the /vendor directory" - "Open a PR if changes pass tests; otherwise open an issue" - "Only report issues; don't automatically fix them" ### Jobs Source: https://www.openhelm.ai/docs/concepts/jobs ## What Is a Job? A job is a scheduled, executable task. When a job fires, OpenHelm runs Claude Code with the job's prompt in the project directory. Jobs are the atomic unit of work in OpenHelm. Each job has: - **Name**, human-readable label - **Prompt**, instructions sent to Claude Code when the job runs - **Schedule**, when and how often to run (see [Schedule Types](/docs/scheduling/schedule-types)) - **Model settings**, which Claude model to use and effort level - **Permission mode**, how much autonomy Claude Code has during execution ## Creating Jobs Jobs can be created two ways: 1. **Via the AI planner**, describe a goal; the AI generates a job plan for you to review and approve 2. **Manually**, click **New Job** and fill in the prompt, schedule, and settings yourself ## Job Settings ### Model The Claude model used for this job's execution. Defaults to Claude Sonnet 4.6. ### Effort (`low | medium | high`) Controls how much planning effort Claude Code uses before starting work. Higher effort means more thorough planning but more tokens consumed. ### Permission Mode Controls what Claude Code can do without prompting for confirmation: - `default`, standard Claude Code permissions - `acceptEdits`, auto-accepts file edits without prompting - `dontAsk`, does not prompt for confirmation on most actions - `bypassPermissions`, maximum automation; use with care ### Working Directory Override By default, jobs run in the project's root directory. Override this to run in a specific subdirectory or a different path entirely. ### Correction Note Optional text appended to the prompt of any corrective retry run. Use this to guide Claude Code when recovering from failures, for example, specifying which commands to run first or which files to check. ## Enabling and Disabling Jobs Toggle the switch on any job to pause or resume automatic scheduling. Disabled jobs can still be triggered manually. ### Runs Source: https://www.openhelm.ai/docs/concepts/runs ## What Is a Run? A run is a single execution attempt of a job. Every time a job fires, on schedule, manually triggered, or as a corrective retry, a new run record is created. ## Run Statuses | Status | Meaning | |--------|---------| | `deferred` | Manually triggered for a future time; waiting to start | | `queued` | Waiting for an available executor slot | | `running` | Claude Code is actively executing | | `succeeded` | Completed successfully (exit code 0) | | `failed` | Completed with an error (non-zero exit code) | | `permanent_failure` | Pre-flight check failed (e.g. binary not found, project directory missing) | | `cancelled` | Cancelled by the user before or during execution | ## Viewing Runs Click any job to see its run history. Each run shows: - Status and duration - Start and finish timestamps - Full stdout/stderr log stream - Exit code and trigger source (scheduled, manual, or corrective) ## Triggering Runs Manually Click **Run now** on any job to immediately queue a run. Manual runs are given the highest priority and execute before any scheduled or corrective runs. You can also defer a manual run to a specific future time, useful for queuing work without changing the job's recurring schedule. ## Cancelling Runs Click **Cancel** on any queued or running run: - **Queued runs**, removed from the queue immediately - **Running runs**, Claude Code receives SIGTERM; after a 5-second grace period, SIGKILL is sent if it hasn't stopped ## Resuming Runs in Terminal Every completed run records a Claude Code session ID. Click **Open in Terminal** on a completed run to launch Terminal, navigate to the project directory, and resume the session interactively with `claude --resume `. This lets you pick up where Claude Code left off or inspect what it did. ## Clearing Run History Run history is kept indefinitely. To clear history for a specific job, use **Clear history** in the job's settings menu. ### Licensing Source: https://www.openhelm.ai/docs/concepts/fair-source ## The OpenHelm Licence OpenHelm is commercial software with a generous free tier. Most personal and small-team use is free; commercial deployment and redistribution require a commercial licence. ## What You Can Do - Download and run OpenHelm for personal and commercial _use_ - Use it across as many of your own projects as you like ## What Requires a Commercial License - Offering OpenHelm as a hosted/managed service to others - Redistributing OpenHelm as part of a commercial product ## Pricing Tiers and Licensing - **Community**, Free for personal use, students, non-profits, and startups under $1M revenue - **Business**, $19/user/month. Commercial use license, self-hosted, priority support _(coming soon)_ - **Cloud**, $39/month. Managed hosting, team sharing, enterprise security _(coming soon)_ See the [Pricing page](/pricing) for full details. ## Scheduling ### Schedule Types Source: https://www.openhelm.ai/docs/scheduling/schedule-types ## Five Schedule Types OpenHelm supports five schedule types, selected when creating or editing a job. --- ### Once Runs the job exactly once at a specific date and time, then never again. | Field | Description | |-------|-------------| | Fire at | Date and time (local timezone) | **When to use:** One-off migrations, initial setup tasks, or any work that should happen exactly once. --- ### Interval Runs the job repeatedly at a fixed interval after the previous run completes. | Field | Description | |-------|-------------| | Amount | A number | | Unit | `minutes`, `hours`, or `days` | **Example:** Every 24 hours, every 30 minutes, every 7 days. **Note:** The interval is measured from the *completion time* of the previous run, not from the original fire time. This prevents queue pile-ups if a run takes longer than expected. --- ### Cron Runs the job on a standard 5-field cron expression. | Field | Description | |-------|-------------| | Expression | Standard cron format: `minute hour day month weekday` | **Examples:** ``` 0 9 * * 1-5 # 9am Monday–Friday 0 2 * * * # 2am every day 0 0 1 * * # midnight on the 1st of each month */30 * * * * # every 30 minutes ``` Cron times are interpreted in your local timezone. --- ### Calendar A human-friendly alternative to cron for common recurring patterns. | Field | Description | |-------|-------------| | Frequency | `daily`, `weekly`, or `monthly` | | Time | HH:MM (local time) | | Days of week | (weekly only) which days to run, e.g. Mon, Wed, Fri | | Day of month | (monthly only) which day, e.g. the 1st | **Examples:** - Daily at 2:00am - Weekly on Monday and Thursday at 9:00am - Monthly on the 1st at midnight --- ### Manual The job has no automatic schedule, it only runs when you explicitly click **Run now**. **When to use:** Jobs you want to control explicitly, ad-hoc tasks, or jobs that are part of a human-supervised workflow. --- ## How the Scheduler Works OpenHelm's built-in scheduler checks for due jobs every **60 seconds**. When a job's next scheduled fire time falls within the current minute, the scheduler creates a queued run. Jobs execute with configurable concurrency, by default one job at a time. Increase this to 2 or 3 in **Settings → Max Concurrent Runs** to run jobs in parallel. ## Next Fire Time The scheduler tracks a `nextFireAt` timestamp for each job: | Schedule type | How `nextFireAt` is updated | |---------------|------------------------------| | Once | Set to null after firing; never fires again | | Interval | Set to completion time + interval after each run | | Cron | Calculated as the next matching cron occurrence from now | | Calendar | Calculated as the next matching calendar occurrence from now | | Manual | Always null; never auto-fires | ### Manual Triggers Source: https://www.openhelm.ai/docs/scheduling/manual-triggers ## Manual Triggers Any job can be triggered immediately regardless of its schedule. **Run now:** Click the **Run now** button on any job. The run is queued immediately at the highest priority and executes before any scheduled runs. **Deferred trigger:** Trigger a run at a specific future time without changing the job's recurring schedule. Useful for scheduling a one-time urgent execution outside the normal cadence. ## Cancelling Runs Cancel any queued or running run from the run detail view: - **Queued runs**, removed from the queue immediately - **Running runs**, Claude Code receives SIGTERM; after a 5-second grace period, SIGKILL is sent if it has not stopped ## Run Priority Runs execute in priority order: | Priority | Trigger source | Notes | |----------|---------------|-------| | 0 (highest) | Manual | Runs triggered by **Run now** | | 1 | Scheduled | Regular scheduled fires | | 2 (lowest) | Corrective | Auto-generated self-correction retries | Within each priority level, runs execute in FIFO order. ## Concurrency By default, only one run executes at a time. Increase **Max Concurrent Runs** in Settings to 2 or 3 to allow parallel execution. This is useful when you have multiple independent projects running simultaneously. ## Features ### AI Planning Source: https://www.openhelm.ai/docs/features/ai-planning ## How AI Planning Works When you create a new goal, the AI planner turns your plain-English description into a structured job plan ready to review and approve. ### Step 1: Assessment The AI first assesses whether your goal is clear enough to plan without clarification. If it needs more information, it asks up to two targeted questions (multiple-choice format with a free-text option). ### Step 2: Plan Generation Once the goal is clear, the planner runs a full planning pass and returns a set of 2–6 jobs. Each proposed job includes: - A descriptive name - A concrete Claude Code prompt - A suggested schedule type and configuration - A rationale explaining why the job is structured this way ### Step 3: Review and Approval You see the complete plan before anything executes. You can: - Approve the plan as-is - Edit individual jobs (change the prompt, schedule, name) - Delete jobs you don't want - Add additional jobs manually Once you click **Approve Plan**, the goal and all its jobs are created in a single operation. Once-only jobs fire within the next scheduler tick; recurring jobs calculate their first fire time from the current moment. ## Planning Quality The quality of the generated plan depends heavily on the clarity of your goal description. See [Projects & Goals](/docs/concepts/projects-and-goals) for guidance on writing effective goal descriptions. ## Skipping the Planner Click **Build manually** at any point to skip AI planning and create jobs directly. The planner is a convenience, you always stay in full control. ### Self-Correction Source: https://www.openhelm.ai/docs/features/self-correction ## Automatic Self-Correction When a job run fails, OpenHelm can automatically create a *corrective run*, a follow-up execution that includes context about what went wrong and any correction guidance you've provided. ### How It Works 1. A run finishes with a non-zero exit code (failure) 2. OpenHelm queues a corrective run with the original prompt plus the failure context appended 3. The corrective run executes at the lowest priority, after all scheduled runs 4. If the corrective run also fails, the cycle repeats up to the configured retry limit 5. Once the retry limit is exhausted, the job is marked as `permanent_failure` and surfaced in the Inbox ### Correction Notes Each job has an optional **Correction note** field. Text entered here is appended to the prompt of every corrective run for that job. Use this to provide guidance for recovering from the specific failures that job tends to encounter: ``` If tests fail due to missing dependencies, run `npm install` first. Check .env.example for required environment variables that may need to be set. ``` ### Configuration Control self-correction in **Settings**: | Setting | Description | |---------|-------------| | Auto-correction enabled | Toggle automatic corrective runs on or off | | Max correction retries | How many times to retry before marking as permanent failure | ## The Inbox The **Inbox** surfaces runs that require human attention, jobs that have exhausted their automatic retries, and any run where Claude Code explicitly requested human input. For each inbox item, you can: - **Dismiss**, acknowledge the failure and take no further action - **Try again**, queue an immediate manual re-run with the original prompt - **Do something different**, provide new instructions and queue a corrective run incorporating your guidance ### Memory System Source: https://www.openhelm.ai/docs/features/memory-system ## Project Memory OpenHelm maintains a semantic memory store per project. As goals and jobs are created and runs complete, information is extracted and stored, building up a knowledge base that informs future planning and execution. ## Memory Types | Type | What it stores | |------|---------------| | `semantic` | Conceptual knowledge: API patterns, architecture, project conventions | | `episodic` | Events and outcomes: what ran, what failed, what was learned | | `procedural` | How-to knowledge: workflow steps and best practices discovered through runs | | `source` | Original documents: code snippets and documentation excerpts | ## How Memory Accumulates Memory is extracted automatically: - When a goal is created (from the goal description) - When a job is created (from the job prompt) - After a run completes (from outputs and outcomes) ## Semantic Search The memory system supports semantic search, finding relevant memories by meaning, not just keyword matching. This allows OpenHelm to surface related context even when the exact words don't match. ## Memory Tags Memories are tagged for organisation and retrieval. Default tags include: `goal`, `data-source`, `preference`, `workflow`, `error-pattern`, `tool-usage`, `architecture`, `convention` ## Viewing and Managing Memory Access the memory store from the project sidebar under **Memory**. From there you can: - Browse all memories for the project - Search by text or tag - Archive memories that are no longer relevant - Prune low-importance memories automatically ### Data Export & Import Source: https://www.openhelm.ai/docs/features/data-export ## Exporting Data Export all your OpenHelm data to a portable JSON file via **Settings → Export Data**. The export includes: - Projects, goals, jobs - Run history (and optionally, full run logs) - Inbox items and conversations - Memory store - Settings (excluding machine-specific paths like the Claude Code binary location) ## Importing Data Import a previously exported JSON file via **Settings → Import Data**. **Preview before import:** OpenHelm shows you what the file contains, record counts, export date, and app version, before making any changes. **Important:** Import is a full replacement. All existing data is overwritten with the imported data. This cannot be undone. The import is also blocked if there are any active or queued runs. After import, machine-specific settings (like the Claude Code path) are automatically preserved from your current installation rather than overwritten. ## Migrating Between Machines 1. On your old Mac: **Settings → Export Data** 2. Transfer the export file to your new Mac (AirDrop, iCloud, USB, etc.) 3. Install OpenHelm on the new Mac 4. **Settings → Import Data** and select the file 5. If your project directories are in different locations on the new Mac, use **Settings → Fix Project Paths** to update them ## What's Not Included - Claude Code itself and its authentication state (must be set up separately on the new Mac) - The Claude Code binary path setting (re-detected automatically after import) ## Reference ### App Settings Source: https://www.openhelm.ai/docs/reference/settings ## Accessing Settings Click the gear icon in the sidebar, or use the **OpenHelm → Settings** menu item. ## Claude Code | Setting | Description | |---------|-------------| | Claude Code path | Path to the `claude` binary. Auto-detected from PATH, Homebrew, and npm on first launch. | | Detected version | Shows the currently detected Claude Code version. Minimum required: v2.0.0. | To re-detect after updating Claude Code, click **Re-detect** next to the path field. ## Execution | Setting | Description | |---------|-------------| | Max concurrent runs | How many jobs can run simultaneously: 1, 2, or 3. Default: 1. | | Run timeout | Maximum minutes a run can execute before being force-stopped. Set to 0 for no limit. Default: no limit. | ## Notifications | Setting | Description | |---------|-------------| | Notification level | `never`, no notifications; `on_finish`, notify on all completions and failures; `alerts_only`, notify only on failures. | ## Self-Correction | Setting | Description | |---------|-------------| | Auto-correction enabled | Whether failed runs automatically generate corrective retries. | | Max correction retries | Maximum number of corrective attempts before marking a run as permanent failure. | ## Analytics | Setting | Description | |---------|-------------| | Analytics enabled | Send anonymised crash reports and usage data (powered by Sentry). Opt out at any time. | ## Data | Action | Description | |--------|-------------| | Export data | Export all data to a JSON file for backup or migration. | | Import data | Replace all data with a previously exported JSON file. | | Fix project paths | Update project directory paths after migrating to a new machine. | ### Troubleshooting Source: https://www.openhelm.ai/docs/reference/troubleshooting ## Claude Code Not Detected **Symptom:** Setup screen shows Claude Code as not found, or a red warning in Settings. **Solutions:** 1. Open Terminal and run `which claude`, if it returns a path, copy it and enter it manually in **Settings → Claude Code Path** 2. If `which claude` returns nothing, Claude Code is not installed. [Install it from claude.ai/code](https://claude.ai/code) 3. If installed via Homebrew or npm in a custom location, check those directories and set the path manually ## Claude Code Version Too Old **Symptom:** OpenHelm reports your Claude Code version does not meet the minimum requirement (v2.0.0). **Solution:** Update Claude Code. Run `claude update` in Terminal, or reinstall from [claude.ai/code](https://claude.ai/code). ## Jobs Not Running on Schedule **Symptom:** Jobs are enabled with a valid schedule, but expected runs are not appearing. **Solutions:** 1. **Is the app running?** The scheduler only runs while OpenHelm is open 2. **Was your Mac awake?** OpenHelm cannot wake a sleeping Mac, ensure your machine was on at the scheduled time 3. **Check the job's next fire time** in the job detail view, if it's in the past, the scheduler will pick it up within 60 seconds 4. **Verify the job is enabled**, the toggle on the job card must be on ## Run Stuck in "Running" State **Symptom:** A run shows as running but there is no new log output and it appears frozen. **Solutions:** 1. Wait up to 10 minutes, Claude Code may be silently processing or making API calls 2. If still stuck after 10 minutes, cancel the run from the run detail view 3. If the app was force-quit while a run was active, OpenHelm automatically marks orphaned running runs as failed on the next launch ## Job Always Fails **Solutions:** 1. Check the run logs for the specific error message 2. Ensure Claude Code can access the project directory, the path must exist and be readable 3. Use **Open in Terminal** on a completed run to resume the Claude Code session and inspect what happened interactively 4. Add a **Correction note** to the job with specific guidance for recovering from the failure ## App Won't Open (Security Warning) **Solution:** 1. Right-click OpenHelm in Applications and choose **Open** (bypasses Gatekeeper on first launch) 2. If still blocked: System Settings → Privacy & Security → scroll to the Security section → click **Open Anyway** ## Getting Help - [Contact us](/contact), bug reports, feature requests, and support questions - [Discord community](https://discord.gg/openhelm), community support and questions