How I'm organised

One company, one capability, one result.

I run six products alone. Not by working faster: by separating what changes from what doesn't. A product brings its identity, a capability brings its method. Crossing the two is deterministic — same input, same output, every time.

COMPANY beedone + CAPABILITY outreachapp RÉSULTAT contacts.csv TRIGGER schedule · event
Two factors, one result. The dashed loop is the trigger: a schedule I set, or an event that lands. It doesn't change the equation, it replays it.

The first factor

A company owns its identity

A product, a brand, soon a client. What it owns, no capability duplicates — and the day the tone changes, it changes in exactly one place.

Identity

What it sells, to whom, with what promise.

project-context.md · context/brand/

Voice and art direction

The tone, the words used, the ones never used, the colors, the mascot.

context/voice/ · social-visual-context.md

The proof

The real numbers. The only legitimate source for a metric quoted anywhere.

context/proof/ · case-studies.md

Its per-capability config

Its caps, open channels, account, cadence.

lane.env · sources.env · newsletter.env

  • beedone productivity app
  • museotter journaling
  • evolum 7 years, ~€30k MRR
  • updrive ride-hailing SaaS
  • mindowl multiplayer quiz
  • youcefelkamel the personal brand

The second factor

A capability owns its method

One repo = one skill. It knows no product in particular: it takes a company as a parameter. Written once, it serves all six.

METHOD.md The doctrine What holds regardless of the product. If another file contradicts it, it wins.
engine/ The engine The mechanics, and above all the refusals. Stdlib only, runs on a bare cron.
listeners/ The ear What arrives from outside. Signature checked, event normalised, queued — never handled inside the request.
agent/sessions/ The recipes A named work slot an agent can execute. This is what a cron triggers.
AGENTS.md The contract Any agent's entry point. This is what makes the capability survivable.
  • shortapp short 9:16 videos
  • postapp multi-platform publishing
  • outreachapp cold Instagram DMs
  • minagapp capture and qualification
  • redditapp Reddit posting
  • adsapp Meta media buying
  • autocontentapp commits → post ideas
  • newsletterapp weekly newsletter
  • podcastapp 10-min episodes
  • seogeoboostapp SEO and answer engines
  • asoboostapp store listings
  • miniaturapp video thumbnails
  • landingapp landing pages and blogs
  • leadmagnetapp lead magnets

The junction

The same engine, a company as parameter

There is no “BeeDone” version of the outreach engine. There is one engine, reading the config of whichever company you name, writing to that company's ledger.

outreachapp / engine --company beedone lane.env plafonds · compte · envoi strategy.md ICP · barème · seuil dm-templates.md the two doors reads contacts.csv one row = one profile actions.csv append-only, holds the caps writes
Swap `beedone` for `museotter`: the engine doesn't move, it reads other files and writes to another ledger.

And the trigger

Two ways it starts without me

A schedule means I decide when. An event means the world does. Either way the trigger holds no method: it names a capability and a company, the rest is already written.

SCHEDULEI decide when

TRIGGER 30 8 * * 1-6
CAPABILITY --skill instagram-outreach --workdir ~/Tech/outreachapp
COMPANY Session `mining` puis `qualification` — company `beedone`.
RÉSULTAT run_summaries/2026-08-06-beedone-mining.json

EVENTthe world decides when

TRIGGER POST /webhook/socialhook · message.received
CAPABILITY webhookSocialhook → Cloud Tasks → socialhookWorker (functions/)
COMPANY Compte Instagram connecté — réponse auto contextuelle (webhookLeads/{username}).
RÉSULTAT webhookConversations/{conversationId} → auto_replied (Firestore)
  • REFUSED BEFORE PROCESSING
  • already seen
  • already answered
  • block list
  • past 24 h

This cron's prompt used to carry 1,100 characters of copied method. It now carries 223 — and the webhook carries none. The method moved to the capability, where it's reviewed and tested.

For real

Ten crossings running today

Each cell is a real pair, with the command that runs it and the file it produces.

beedone × outreachapp
engine/mine.py --company beedone --from-sources

410 contacts in a single ledger

apps/beedone/contacts.csv

beedone × redditapp
skill reddit-marketing · session casual

one post a day, account rotation

apps/beedone/subreddits.md

beedone × autocontentapp
engine/scan.py --company beedone

ideas traced back to the commit

companies/beedone/ideas.csv

museotter × asoboostapp
baseline · concurrents · métadonnées

before / after rankings

references/beedone-case-study.md

youcefelkamel × newsletterapp
engine/check.py --company youcefelkamel

“App World Weekly”, every Monday

companies/…/issues.csv

beedone × podcastapp
engine/episode.py new --company beedone

10 minutes, timed transcript, chapters

episodes/beedone/…/out/

evolum × landingapp
scaffold.mjs --project ~/Tech/evolum_app · audit.mjs

5 landings off the same engine: evolum, beedone, museotter, strive, this site

landing/ · landing.config.json

beedone × seogeoboostapp
seo-commit-mining → seo-app-articles · cron du lundi 7 h

6 FR+EN articles in 28 days, angle mined from the commits

landing/src/content/blog/

youcefelkamel × leadmagnetapp
une capacité en prod → page + article + carrousel + post

2 magnets live, measured numbers in the ledger

SHIPPED.md

youcefelkamel × miniaturapp
engine/generate.py --company youcefelkamel --variant jeff

3 takes judged at 120 px, A/B test open

companies/…/thumbnails.csv

Why it holds

Eight rules, never negotiated

These aren't style preferences. Each one fixes a failure I've actually lived through.

  1. 01

    One ledger, never two

    A capability owns its data and nobody copies it. An incoming event keeps its own, raw and immutable; the capability derives what it needs. You project, you never copy — otherwise two truths coexist, and what breaks next is an account.

  2. 02

    Everything lives in the repo

    No hidden memory inside an agent. What's learned is written to the relevant file: reviewable, versioned, still readable in six months.

  3. 03

    When in doubt, the repo wins

    An agent skill can drift from the method. The rule is written in every capability: the repo decides. That's what stops two truths coexisting.

  4. 04

    The engine refuses, by design

    A question over 35 words, a DM with no signal, an idea with no commit, a number with no source, a message already answered: refused. A refusal is fixed, never bypassed.

  5. 05

    The executor stores nothing

    The agent that triggers resolves a triple and runs it. It holds neither the method nor the data. It can be swapped on a Monday morning with nothing lost. Its only memory is the repo.

  6. 06

    Feedback becomes a rule

    Storing nothing doesn't mean writing nothing. A remark is never repeated twice: it becomes one line in the relevant file, short and checkable. That's what makes a capability improve instead of repeat itself.

  7. 07

    Nothing from outside is taken on trust

    An incoming event is signed, and the signature is checked against the raw body before reading it. No valid signature: 401, and nothing enters the books.

  8. 08

    Acknowledging isn't processing

    The receiver answers 200 immediately and queues — an agent thinking for ten seconds would make the delivery look failed. Every event carries an id: a retry never produces two actions.

What evolves

A remark isn't repeated, it's written down

The executor keeps nothing in memory, but it has one write permission: improving whatever just produced the result. Tell it the em dashes read as AI, and it doesn't jot that down somewhere — it opens the right file and adds one precise, checkable line. The only question is which of the two factors.

A matter of taste → the company

“Drop the em dashes in my posts, they read as AI.”

youcefelkamel/context/voice/linkedin.md
## WritingShort sentences, one idea per line.+ Never an em dash. Split the sentence in two.

Moves this brand only. The five other companies keep their voice.

A matter of method → the capability

“An idea without the commit that justifies it, I won't read.”

autocontentapp/METHOD.md
## RefusalsNo topic already covered this month.+ Refuse any idea whose source commit isn't cited.

Moves all six companies at once. Written once, applied everywhere.

The rule that says where a remark lands is itself in the repo. That's what makes forking viable: you don't leave with the machinery, you leave with the way it learns.

What this changes for a company

The same split works for you. Your context, your voice, your proof stay with you — in your repo, which you keep. The capabilities plugged into it bring the method and the guardrails. The day we stop working together, it all keeps running without me: that's the point, not a side effect.

Let's talk

P.S. — These repos are built to be forked, and to outgrow the pot. Yours will take your rules, your refusals, your voice, and six months in it won't really look like mine anymore. What I'd like to see is what it looks like a year in, once it has replaced enough Monday mornings to have opinions of its own. Do send me a photo of the roots.