oneshot-gtm: an approval-gated outbound agent that bills per call
GTM agent for technical founders. Pay-per-result. Two surfaces: terminal CLI + local web dashboard.
At a glance
- What is it?
- oneshot-gtm is a self-hosted go-to-market agent for technical founders, shipping a terminal CLI and a local web dashboard over one SQLite ledger. It writes drafts a human approves, and it charges for the actions it takes rather than for seats.
- Who is it for?
- oneshot-gtm fits a founder who sells to identifiable companies and wants every message reviewed before it leaves, and who is willing to fund a per-call wallet and keep Bun installed. It does not fit a team that needs unattended sending, a shared multi-operator server, or Node.js.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A gate and a queue stand between a signal and a sent message
The premise of oneshot-gtm is narrow on purpose. The README puts it plainly: it is outbound for founders who have not earned scale yet. It finds people, the founder approves them, it writes, the founder sends. That is the entire loop, and each of those four verbs corresponds to a piece of machinery you can see in the description.
Finders watch public signals: a launch, a funding round, a new licence, a starred repo. A gate then judges each candidate person against the ICP defined in your profile, and rejects the ones who do not fit. You can overrule the gate when you disagree with it. Candidates then sit in a queue as rows, and approving a row sends nothing at all. Approval is a review step, not a trigger.
Each message opens with an offer specific to the recipient's firm, written from research and your product brief, in your voice. A prospect offer is documented as its own prompt input, and the drafts can be read before they go anywhere. Cadences follow up on their own schedule, and a reply on any channel stops the sequence. The value proposition for a technical founder is control over the exact moment a stranger is contacted, at the cost of running the queue yourself.
One SQLite ledger under a CLI and a web dashboard
The architecture is laid out as a monorepo with three surfaces over a set of shared packages. The CLI is built with commander. The server uses Bun.serve with SSE. The web dashboard is a Vite and React application. Beneath them sit packages for core, intel, plays, find, prompts, doctor and shared types, and under those sits the @oneshot-agent/sdk, which covers email, LinkedIn, SMS, voice, research, enrichment and receipts.
State lives in one place. The source of truth for both the CLI and the dashboard is a SQLite database at `~/.oneshot-gtm/ledger.sqlite`, and the `ONESHOT_GTM_HOME` environment variable moves it. Secrets sit in `~/.oneshot-gtm/.env` with mode 600, and the .env.example file shows the keys the runtime reads: an LLM provider key such as `OPENROUTER_API_KEY`, and either the Coinbase Developer Platform server wallet triple or a raw `AGENT_PRIVATE_KEY` for the OneShot wallet. Optional keys include `PORT`, `ONESHOT_GTM_NO_BROWSER` and `ONESHOT_GTM_TELEMETRY`.
The server is single user and bound to `127.0.0.1`, and the only routes meant for other systems are two webhooks. That is a sensible default for a founder running a tool on their own laptop, and it is also the reason the dashboard is not something you put behind a shared domain.
Bun is a hard requirement, not a preference
Installation has two paths and both require the Bun runtime. The quick path runs the dashboard package without any clone:
bunx oneshot-gtm-server # the dashboard, no cloneThe clone path installs Bun, pulls the repository and builds the dashboard once:
curl -fsSL https://bun.sh/install | bash # Bun is the runtime
git clone https://github.com/oneshot-agent/oneshot-gtm
cd oneshot-gtm && bun install
bun run cli -- init # profile and keys
bun run cli -- doctor # health check
bun run --cwd apps/web build # build the dashboard once
bun run cli -- ui # http://127.0.0.1:3030The runtime constraint is not a matter of taste. The documentation states plainly that the code uses `bun:sqlite` and fails under plain Node, and the root package.json declares `bun` as the engine at `>=1.3.0` with `[email protected]` as the package manager. If your company runs Node on every machine, that is the first integration cost you inherit.
`init` asks who you are and what you sell, and every field is optional. A blank field skips that beat in the draft rather than being invented, which matters for founders who cannot afford hallucinated case studies in an outbound email. `doctor` is the health check, and `ui` binds the dashboard to `http://127.0.0.1:3030`.
Ten a day, then ten more each week, then a stop
The sending rules are the most opinionated part of the project, and they exist because the README argues that most outbound tools assume product-market fit and optimise for sends while most founders using them do not have that fit yet. The limits are in the code rather than in a policy page.
A new mailbox sends 10 messages a day and earns 10 more each week, up to 50. Once the daily quota is used, nothing further sends until midnight. That is mailbox warmup expressed as arithmetic, and it caps the daily ceiling of the whole system regardless of how much of the queue you have approved. Every draft also passes a lint for machine writing, and a flagged draft is held rather than queued. A first touch never asks a stranger for a meeting. It says one useful thing and asks one line back, or says nothing at all.
There is a second guard at the scale-up moment. The `handoff` commands check your replies and deals before a scale move and say so when it is too early. The point is a founder who is invited to loosen the volume will get a refusal backed by their own ledger rather than by a general warning.
Finders, plays and the workspaces that keep products apart
A finder is a source with a schedule and a spend cap. The documented list includes Show HN, funding news, accelerator cohorts, job changes, open roles, GitHub stars, event guest lists, business registries, public tenders and any page that lists companies. Every finder starts off, so a fresh install sends nothing until you switch on the ones where your buyers actually appear, and you can apply an industry pack or bring your own list instead.
A play is one motion, defined by who it is for, what happened to them, what the first message says and how it follows up. Email and LinkedIn go out when you send them. X, Reddit and Hacker News drafts are posted by you and then marked sent, which keeps them in your hands rather than in an automated poster. Mail goes out through a pool of your own mailboxes and OneShot domains, and a prospect always hears from the address that wrote first. LinkedIn invites, messages and replies travel through the OneShot API from the connected account, never a browser bot.
Workspaces are the isolation unit. One workspace is one product with one voice, one ICP, one ledger and one sender pool:
bun run cli -- workspace create acme
bun run cli -- --workspace acme init
bun run cli -- --workspace acme uiThe workspace tables share one database of people, paid lookups and contact history, so two products do not cold-email the same person in the same week. The repository ships ready-made example lists under `examples/`, including `examples/accelerator-batch.json`, `examples/post-funding.json`, `examples/show-hn.json` and `examples/job-change.json`.
Pay per call, with a signed receipt for each one
The billing model is the commercial core of the project. OneShot supplies the actions: research, enrichment, email, LinkedIn, SMS, voice and letters, and bills per call. You bring the LLM key. Every paid call leaves a signed receipt, which the README describes as making spend per reply a record rather than an estimate. The site links to a separate page explaining what a signed receipt is.
That design pushes cost accounting into the ledger itself, and it is the cleanest part of the proposal for a founder who has been burned by seat-based tools. `config spend-ceiling` caps what a day of finder runs and drains may spend, and background monitoring keeps finders polling while the dashboard runs, with `ui --install-service` keeping it alive across restarts.
The contrast with the category is stated in the README itself. Most outbound tools assume product-market fit and optimise sends, while oneshot-gtm caps volume, holds flagged drafts and refuses to ask for a meeting on a first touch. Another difference sits in the LinkedIn path: invitations go through the vendor API from your own connected account rather than through a browser bot, which changes the failure modes you have to debug when an invite lands badly.
Where oneshot-gtm is the wrong tool
Several constraints make it a poor fit for some teams. The server is single user and bound to `127.0.0.1`, so a shared instance for several operators is out of scope as written. The Bun requirement rules out a standard Node shop without extra work. The warmup arithmetic caps a single new mailbox at 10 a day and 50 in steady state, so a founder with an urgent pipeline and a list of thousands is waiting on a schedule that the system, not the market, sets.
The billing model also front-loads risk. Every lookup is a paid call against a wallet you configure, and the LLM provider key is yours, so the total cost of a campaign is a function of how many candidates the gate lets through and how much research each one needs. Nothing in the setup steps caps that before the first run; `config spend-ceiling` has to be set deliberately.
On the maintenance side the repository is not archived and the last push was on 2026-10-20, with releases v0.11.0 on 2026-10-08, v0.10.0 on 2026-09-30 and v0.9.0 on 2026-09-26. The version numbers are still below 1.0, and the release notes for v0.9.0 mention measured angles, founder voice, latest accelerator cohorts and live research, which reads like a tool still moving quickly enough to change its own prompt design.
Editorial conclusion
oneshot-gtm fits a founder who sells to identifiable companies and wants every message reviewed before it leaves, and who is willing to fund a per-call wallet and keep Bun installed. It does not fit a team that needs unattended sending, a shared multi-operator server, or Node.js. Before adopting, check that the finders you actually need can be switched on, that the voice card reads like your own writing, and that the spend ceiling in `config spend-ceiling` matches what a day of finder runs is allowed to cost.
Frequently asked questions
Does oneshot-gtm run under Node.js?
No. The documentation states that the code uses `bun:sqlite` and fails under plain Node, and the root package.json declares `bun` at `>=1.3.0` with `[email protected]` as the package manager. Install Bun first, either with the installer script or by using `bunx oneshot-gtm-server`.
How much does oneshot-gtm cost to run outbound campaigns?
OneShot supplies the research, enrichment, email, LinkedIn, SMS, voice and letter actions and bills per call, while you bring the LLM provider key. Every paid call leaves a signed receipt, and `config spend-ceiling` caps what a day of finder runs and drains may spend.
Does oneshot-gtm send messages on its own once I approve them?
Approving a row sends nothing. You then send one message yourself or run a batch, and email and LinkedIn go out only when you send them, while X, Reddit and Hacker News drafts are posted by you and marked sent afterwards. Direct mail is proofed and approved by hand.
Can I use oneshot-gtm for more than one product?
Yes. A workspace holds one voice, one ICP, one ledger and one sender pool, and a second product gets a second workspace. Workspaces share one database of people, paid lookups and contact history so two products do not cold-email the same person in the same week.
How many messages can a new mailbox send in oneshot-gtm?
A new mailbox sends 10 a day and earns 10 more each week, up to 50. Once the day's quota is used, nothing more sends until midnight.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/oneshot-agent-oneshot-gtm)Was this useful?