meffecta agent
Set-up

From an empty project
to a first run

Nine steps, each checkable before you go on. About an afternoon, and most of that is waiting for Google to enable things.

Before you begin

Have all of these on the machine you will operate from — macOS or Linux.

Nothing else to install. Every command below starts with npx, which fetches the tool for that one run:

npx @meffecta/agent version   # names the engine build it deploys

Pin it once you are running — npx @meffecta/agent@1.0.0 rather than plain npx. Each release of the tool deploys the engine image published alongside it, so the version you run is how you choose your engine: deliberately, rather than by surprise.

The set-up, in order

Nine steps. Each one is checkable before you go on.

01

Create a GCP project

Give the agent a project of its own, separate from any product project it will read: everything the agent runs as can read every password stored in this project, and your mail tokens should not sit where another system's machinery can reach them.

npx @meffecta/agent create-project
Note the project ID it prints. Project IDs are globally unique, so a plain name is often taken and you end up with a suffixed one (acme-agent-506513). The ID, not the display name, is what every later command needs.
02

Link a billing account

It lists the accounts you can use, marks closed ones as unselectable, links your choice, and then checks the project really is billed — because linking can report success and still leave it unbilled.

npx @meffecta/agent link-billing --project <PROJECT_ID>
It reports billingEnabled: true.
03

Create the content repo

A private GitHub repo holding everything about this deployment. Three lines make it and put you inside it, and the first is once ever — every command from here on runs from this folder, which is what says which deployment you mean.

gh auth login                                    # once, ever — opens your browser
gh repo create acme-agent-home --private --clone # creates it, copies it here
cd acme-agent-home                               # move into the folder it made

Now fill the folder:

npx @meffecta/agent init

Four files, and anything already there is left alone:

deployment.env       # which GCP project and service this is
SYSTEM.md            # who it works for — read at the start of every run
systems/example.md   # a file per system it may reach, and the variables
jobs/example.md      # a file per job: a few settings, then the prompt

That is a working repo. The two example files are the shape of the thing — rename them after something real, and delete what is left. What a job is and what a register entry is have the full shape of each.

Open SYSTEM.md now and say who the agent works for. It goes in front of every job's prompt, and a few honest sentences beat a page of instructions.

worlds/ is always a folder, and each thing inside it is one world — a business, product or brand the agent works on. A world holds what would otherwise be repeated in every job: who you sell to, what you may claim, who the competitors are. One world is either a single file (worlds/acme.md) or a folder of them (worlds/acme/) once there is more than a page of it. Most deployments have exactly one. Skip the whole thing to begin with; nothing depends on it.

Then fill in deployment.env. PROJECT is fixed — it is the ID Google handed you in step 1, and it has to match exactly. SERVICE and ARTIFACT_REPO are the opposite: nothing by those names exists yet, and you are inventing them. Anything you write works, and step 5 creates both under it. The examples below only keep them recognisable beside the project.

PROJECT=acme-agent-506513        # the project ID from step 1 — this one is given
SERVICE=acme-agent               # your name for the service the agent will run as
ARTIFACT_REPO=acme-agent-images  # your name for the store it gets the engine from
REGION=europe-west1              # which Google data centre all of it lives in

Two more are optional. TIMEZONE is the zone every job's schedule is read in — leave it out and they run on UTC. ACCOUNT pins every command to one Google login, which matters only if you are signed into several.

The whole file is committed. None of it is secret — secrets live in Google's Secret Manager, added in step 6 — so a clone of this repo is everything the next person needs to operate the deployment.

Then send it all to GitHub. These same three commands are how every later change reaches the agent — a new job, a reworded prompt, a fact it should know:

git add -A                       # take everything you just made
git commit -m "First set-up"     # save it, with a note to your future self
git push                         # send it to GitHub
Your terminal is inside the folder, and the files show up on your repository's page on github.com.
04

Mint the credentials

Two, and the service will not start without either.

npx @anthropic-ai/claude-code setup-token  # → CLAUDE_CODE_OAUTH_TOKEN, step 6
  • CLAUDE_CODE_OAUTH_TOKEN — your deployment bills its own runs
  • GITHUB_TOKEN — a fine-grained personal access token with contents: read on the content repo, plus contents: write and pull requests: write on any repo whose jobs open pull requests

Mail, analytics, a CRM, a database — anything the agent reaches — comes later and one at a time: Systems.

05

Provision the infrastructure

Safe to run as many times as you like — re-run it after any change. It switches on the Google APIs, creates the registry the engine image is served from, the login the agent itself acts as, a bucket for its memory, a write-once bucket for the audit trail (kept a year), the task queue that carries work to it, and the empty service the engine will run in.

If you would rather see it before it does anything, ask it first. This changes nothing at all — it just prints everything it would create and every permission it would grant, in your project:

npx @meffecta/agent setup-infra --dry-run

Then, for real:

npx @meffecta/agent setup-infra
The banner names the project from your deployment.env — if not, you are in the wrong directory.
06

Wire up the configuration

Secrets go into Google's Secret Manager and are connected to the service in one step; the value is never shown on screen, and never saved in your command history. Re-running one rotates it.

npx @meffecta/agent set-secret AGENT_API_SECRET --random   # generated for you
npx @meffecta/agent set-secret CLAUDE_CODE_OAUTH_TOKEN     # prompts, hidden
npx @meffecta/agent set-secret GITHUB_TOKEN

Non-secret settings go through set-env. The service will not boot without GIT_REPO_URL:

npx @meffecta/agent set-env GIT_REPO_URL=https://github.com/<owner>/<repo>.git

That is everything the engine needs. Anything else — Gmail, analytics, logs, a CRM — is one credential each, added whenever you want the ability, not now.

07

Deploy the engine, and its triggers

Rolls out the engine build this version of the tool was published with, and sets the service's size and scaling from deployment.env — so a setting changed by hand in the console cannot quietly survive a deploy. --tag <version> goes to a different build, which is also how you roll back.

npx @meffecta/agent deploy --dry-run   # see the target first
npx @meffecta/agent deploy

It then creates the triggers, because the service sleeps when nothing is happening and is only awake while answering a request — so nothing inside it can run on a timer of its own. One Cloud Scheduler job per cron: in your jobs, and a housekeeping sweep. It can only do this after the engine is running, since the running engine is the only thing that knows which jobs exist.

It reports one trigger per cron job, plus <service>-sweep, and npx @meffecta/agent triggers agrees.

Every later rollout re-syncs them, so a changed cron: needs nothing extra. To re-sync without a rollout — the only time you need it on its own — run npx @meffecta/agent sync-triggers.

08

Verify

npx @meffecta/agent status
npx @meffecta/agent jobs
npx @meffecta/agent doctor

Seeing your jobs listed is what proves the service could read your content repo. An empty list means GIT_REPO_URL is wrong or GITHUB_TOKEN cannot clone it.

To see what all of this actually created inside Google Cloud — and what each piece is for, in plain words — there is one more:

npx @meffecta/agent resources

It lists everything, says which parts cost anything, and gives you a link straight into the Google Cloud console for each one. Nothing you have to remember the name of.

Then test every connection you have set up, from inside the deployment:

npx @meffecta/agent verify-credentials
Each one reports ok or skip, and none reports FAIL — skip only means you have not set that one up yet.

The same thing has a web page, for anyone who would rather not use a terminal: open /ask on the service URL that status printed. Any username, the secret as the password.

09

The first run

The job init scaffolded touches nothing real. It reports who it works for, which systems it can and cannot reach, and where its memory is — which is every part of the path a real job depends on.

npx @meffecta/agent run example
npx @meffecta/agent logs --limit 50
It answers with your own company from SYSTEM.md, and with the systems you have registered.

Then write a real one. create-job writes the file from a sentence, and Jobs is the full reference. Read what the first one produces before giving it a cron:.

What lives in your content repo

Everything about your deployment. Nothing about the engine.

acme-agent-home/
deployment.env       # which GCP project and service your deployment is
SYSTEM.md            # the rules every job gets, before its own instructions
jobs/                # one file per job
  morning-brief.md
  weekly-review.md
systems/             # one file per system it can reach
  gmail.md
  google-analytics.md
worlds/              # optional — what it should know about the business
  acme.md
skills/              # optional — procedures of your own, or overrides
  accounting/SKILL.md
deployment.envWhich GCP project, service, region and image repository this is. Committed on purpose — none of it is secret, so a clone of the repo is everything the next operator needs.
SYSTEM.mdRules, not facts. It goes in front of every job: who the agent serves, how it should write, what it must never do. The engine adds its own baseline after yours, so the safety rules you cannot switch off stay on. It applies to every run including one working inside another repo.
jobs/*.mdA few settings, then a page of plain-language instructions — Jobs.
systems/*.mdThe register. One file per system, naming the skill that reaches it, the variables holding its credential, what access is allowed, and the cheapest read that proves it works. A system with no file here is a system the agent does not have — the credential can be perfectly valid and still no job will ever use it. The shape of an entry.
worlds/One world per business, product or brand — each either a single file (worlds/acme.md) or a folder of them. Facts that outlive any one job, and that travel with the agent when a job runs inside one of your other repos. Every run is told which worlds exist.
skills/A procedure of your own. A folder named after one of the built-in skills replaces it — the folder name is what decides, so renaming one quietly stops it overriding anything.
CLAUDE.mdOptional, and different from the rest: claude loads it from the working directory by itself, so it reaches every run in this clone without the engine composing it. Keep it short and about the repo; rules belong in SYSTEM.md, which outranks it.

What is effective when

On pushPrompts, run settings, SYSTEM.md, systems/, worlds/, skills/. Live on the next run — there is nothing to build and nothing to deploy.
On deployWhether a job exists, and when it fires: a new job file, a renamed one, or a changed cron:, webhook:, inbox: or allowFrom:. These are read once when the service starts, so it has to restart to see them.
On engine deployThe engine's own code and its built-in skills. Those ship in the image, so a new capability from us arrives when you choose to move versions.

Renaming a job file makes a new job. Its memory is kept under its name, so the old name keeps the history and the new one starts blank — worth doing deliberately rather than while tidying up.

Next