@meffecta/agent 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,142 +1,109 @@
1
- # @meffecta/agent
1
+ # Meffecta Agent
2
2
 
3
- Set up and operate a **Meffecta Agent** deployment a self-hosted Claude Code job runner
4
- that wakes on a schedule, a webhook, or new mail, and runs a job against a fresh clone of
5
- your own content repo.
3
+ An AI colleague that runs in **your own Google Cloud**, on **your own jobs**, against your
4
+ own systems. It wakes on a schedule, a webhook, or an email, does a piece of real work, and
5
+ reports back then goes back to sleep costing nothing.
6
6
 
7
- The agent itself is a container image (`ghcr.io/meffecta/agent`). This package is the tool
8
- that stands one up and runs it, and it is all you need: the engine's source is private,
9
- and nothing here depends on it.
7
+ Work arrives finished, rather than waiting in a chat window for you to open it — though
8
+ you can also just ask it something when you want to.
10
9
 
11
- ```bash
12
- npx @meffecta/agent steps # the whole set-up, in order
13
- npx @meffecta/agent help # every command
14
- ```
10
+ ### → [agent.meffecta.com](https://agent.meffecta.com)
15
11
 
16
- ## What it does
12
+ What it is, what you need, and the whole set-up in order. This package (`@meffecta/agent`)
13
+ is the tool that stands one up and operates it.
17
14
 
18
- Run it from your **content repo** — the directory holding `deployment.env`, `jobs/`,
19
- `worlds/` and `SYSTEM.md`. That file says which GCP project and Cloud Run service this
20
- deployment is, so a command can never quietly act on the wrong one.
15
+ ## What people run it for
21
16
 
22
- ```bash
23
- npx @meffecta/agent create-project # a GCP project
24
- npx @meffecta/agent link-billing # attach billing
25
- npx @meffecta/agent setup-infra # registry, buckets, service account, service
26
- npx @meffecta/agent set-secret AGENT_API_SECRET --random
27
- npx @meffecta/agent set-env GIT_REPO_URL=https://github.com/you/your-content-repo.git
28
- npx @meffecta/agent deploy # roll out the engine
29
- npx @meffecta/agent sync-triggers # give it its triggers
30
- ```
17
+ A job is a page of plain-language instructions, so this is a sample rather than a menu —
18
+ the agent does what your jobs say.
31
19
 
32
- Giving it access to something Gmail, GA4, Grafana, PostHog, Cloudflare, an inbox
33
- trigger is ongoing work rather than set-up, and each has a walkthrough:
20
+ **Sales** find prospects and check them against your CRM, research each company and its
21
+ decision-maker, leave outreach drafts in the seller's own mailbox for them to send, and put
22
+ a next step on every priority account.
34
23
 
35
- ```bash
36
- npx @meffecta/agent connect # what can be connected
37
- npx @meffecta/agent connect gmail # what to do, in order, with the commands
38
- ```
24
+ **Marketing** — one weekly read across traffic, search, ads and campaigns. Website and
25
+ search audits with fixes proposed. Ad reviews, where changes happen only on request. Watches
26
+ form leads, contacts, and competitors' rankings.
39
27
 
40
- Then, day to day:
28
+ **Customer care** a support inbox that answers or hands over with the findings attached,
29
+ learns from the conversations, and keeps help pages current as things change.
41
30
 
42
- ```bash
43
- npx @meffecta/agent doctor # is anything quietly broken?
44
- npx @meffecta/agent status # revision, shape, triggers, queue
45
- npx @meffecta/agent jobs # what is registered, and what triggers it
46
- npx @meffecta/agent env # every setting (secret values never printed)
47
- npx @meffecta/agent secrets # what is stored, and what the service reads
48
- npx @meffecta/agent triggers # the Cloud Scheduler jobs and task queue
49
- npx @meffecta/agent logs --limit 100
50
- npx @meffecta/agent run morning-brief
51
- npx @meffecta/agent ask "how did search do last week"
52
- ```
31
+ **Compliance** — review an ISO 27001 document set against the standard, find what is overdue
32
+ or contradicts itself, and draft revisions for a person to approve — sized to your business
33
+ rather than to a template's idea of one. It never records that a control is in place: that
34
+ claim is what an audit tests.
53
35
 
54
- `doctor` is the one to run when something feels wrong. It judges rather than describes,
55
- and it is aimed at the failures that produce no error anywhere: a scaled-to-zero service
56
- with no triggers runs nothing while looking perfectly healthy, an always-on one with
57
- triggers runs every cron twice, a sweep whose cadence no longer matches the inbox poll
58
- interval checks mail on yesterday's schedule for ever, and a registry that expired the
59
- image your revision pins will fail at the next cold start rather than the next deploy.
60
- Every finding carries the command that fixes it, and it exits non-zero on a real problem
61
- so CI can run it.
36
+ **Engineering** overnight error triage with fixes proposed as pull requests, a verdict on
37
+ every proposed change, alerts traced to a likely cause, and weekly upkeep.
62
38
 
63
- ## Two things worth knowing
39
+ **Leadership** a morning brief tailored to each person's role, daily status on what is
40
+ live and in use, and weekly reviews that stay honest about flat weeks.
64
41
 
65
- **The version you install is the engine you deploy.** Each release records the engine build
66
- published alongside it, and `deploy` defaults to that image. Tooling and engine move
67
- together, so a script can never provision the wrong shape for the engine it is aimed at.
68
- `meffecta-agent version` tells you which pair you have.
42
+ **Assistant** email it anything: a lookup, a draft, a booking, a question. One calendar
43
+ across Google and Microsoft 365. Inbox digests and the week ahead.
69
44
 
70
- **Secret values are never printed.** `secrets` lists what exists and whether the service
71
- reads it; `env` names secret-backed settings without resolving them. Setting one takes the
72
- value from a pipe, a file, or a hidden prompt — never from your shell history.
45
+ ## What it can reach
73
46
 
74
- ## Writing a job
47
+ Shipped with the engine, pointed at your accounts by your jobs:
75
48
 
76
- ```bash
77
- meffecta-agent create-job "a marketing report every Wednesday at 2pm"
78
- ```
49
+ | | Reached out of the box |
50
+ |---|---|
51
+ | **Mail & calendar** | Gmail, Microsoft 365, Google Calendar |
52
+ | **Documents** | Drive, Sheets, Docs, Slides |
53
+ | **Your numbers** | GA4, Search Console, Google Ads, PostHog, Ahrefs |
54
+ | **Your data** | BigQuery, Elasticsearch, MongoDB — and logs from Grafana or Coralogix |
55
+ | **The market** | Google's live search results — real rankings, not a web search |
56
+ | **CRM** | HubSpot, reading and writing as separate abilities |
57
+ | **Work & content** | Linear issues and cycles; Webflow pages and CMS, staged before anything goes public |
58
+ | **Slack** | Posts, threads and reactions — and answers when someone @-mentions it |
59
+ | **Infrastructure** | Cloudflare, and a real headless browser for anything without an API |
60
+ | **Your code** | any Git repo as the working directory, with pull requests as the output |
79
61
 
80
- The model runs **on your deployment**, not on your laptopit already holds the Claude
81
- token, and more importantly its run has your content repo cloned and the engine's skills
82
- mounted, so it can read your existing jobs for house style, your worlds, and
83
- `systems/` for which systems this deployment can actually reach. It writes a file to
84
- `jobs/<name>.md` and stops: nothing is committed, pushed or deployed, because that prompt
85
- is something your agent will run and you should read it first.
62
+ Anything else is a skill you add to your own repo the engine never needs to know about it.
86
63
 
87
- What comes back is checked before it is written — a valid five-field cron in your
88
- deployment's timezone, a usable job name, no `inbox:` without `allowFrom:` (the engine
89
- refuses those, deliberately), an `effort:` the engine accepts, and no silent overwrite of
90
- an existing job. `--dry-run` prints without writing; `--name` overrides the chosen name.
64
+ ## How it works
91
65
 
92
- After you edit it by hand:
66
+ Your **content repo** holds the jobs, the facts about your business, and the register of
67
+ which systems this deployment may touch. Every run clones it fresh. Push a changed prompt
68
+ and the next run uses it; there is nothing to build and nothing to deploy.
93
69
 
94
- ```bash
95
- meffecta-agent check-jobs # the same checks, on every job file here
96
- ```
97
-
98
- ## Anonymous analytics
99
-
100
- On by default, and one command to stop:
101
-
102
- ```bash
103
- meffecta-agent analytics # exactly what is sent, and the current state
104
- meffecta-agent analytics off # or set DO_NOT_TRACK=1
105
- ```
106
-
107
- **Sent:** which command ran — matched against the built-in list, never a word you typed —
108
- whether it worked, how long it took, the class of any error, this CLI's version and the
109
- engine tag it deploys, Node version, OS and architecture, how you installed it, and whether
110
- a `deployment.env` was found. Plus a random id generated on your machine, so repeat runs
111
- count as one install.
70
+ Jobs are triggered by a **schedule**, a **webhook**, or **an email to an address you name**
71
+ and a job that runs out of time can hand the rest to a follow-up run of itself. Each job
72
+ keeps its own memory across runs, and every prompt, result and transcript lands in a
73
+ write-once audit bucket.
112
74
 
113
- **Never sent:** your GCP project or service name, region, repo URLs, account or email
114
- address, file paths, command arguments, secret names or values, job names, prompts — or any
115
- error *message*. Only the error's class, because messages routinely quote a project id, a
116
- path, or a line of `gcloud` output.
75
+ ## Built to be trusted with the keys
117
76
 
118
- Off automatically in CI. Nothing is written to your machine at all if you have opted out.
119
- It is one bounded request after the command's own work is finished, and a failure to send
120
- is silent — analytics can never delay or fail a deploy.
77
+ It runs in **your** GCP project, on **your** credentials, billed to **your** Claude
78
+ subscription. Nothing routes through Meffecta.
121
79
 
122
- ## Requirements
80
+ A job reaches only the systems your register lists, and reading and changing are separate
81
+ abilities — a reporting job loads the reader and never the writer.
123
82
 
124
- `gcloud` (authenticated), `docker` (to mirror engine images into your registry), `git`, and
125
- Node 20+ Node 24+ if you also run the `claude` CLI to mint the token. macOS or Linux.
83
+ One shipped skill exists to change a paid account, Google Ads, and it is the most
84
+ constrained thing here: every change is validated against the live account first and only
85
+ applied on a second, explicit run; budgets can only go *down*; a campaign can be paused but
86
+ never deleted; and the limits live in the script, not in the instructions, so no wording can
87
+ talk its way past them.
126
88
 
127
- ## Developing it
89
+ A job reachable by email must say who may reach it, or it refuses everyone — an omission is
90
+ not consent. Secret values are never printed, by any command.
128
91
 
129
- From a checkout of the engine repo:
92
+ ## Operating it
130
93
 
131
94
  ```bash
132
- cd cli && npm link # `meffecta-agent` now runs the working tree
95
+ npx @meffecta/agent steps # the set-up, in order
96
+ npx @meffecta/agent help # every command — each also takes --help
97
+ npx @meffecta/agent doctor # the one to run when something feels wrong
133
98
  ```
134
99
 
135
- The scripts and docs are vendored into this package only at pack time, so a linked
136
- checkout falls back to the engine repo's own copies edit either half and the next command
137
- picks it up. `npm rm -g @meffecta/agent` undoes it.
100
+ Run commands from your content repo the directory holding `deployment.env`, which says
101
+ which project and service this deployment is, so a command can never act on the wrong one.
102
+
103
+ **The version you install is the engine you deploy.** Each release records the engine build
104
+ published alongside it, and `deploy` defaults to that image, so tooling and engine cannot
105
+ drift apart. `meffecta-agent version` tells you which pair you have.
138
106
 
139
- ## Documentation
107
+ ## Licence
140
108
 
141
- `npx @meffecta/agent help` lists every command; `npx @meffecta/agent steps` is the whole
142
- set-up in order, with the command for each step. Every command takes `--help`.
109
+ UNLICENSED for use by Meffecta deployments.
package/engine.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "engineTag": "1.0.7",
3
- "builtFrom": "26157a11d57ec9821672a644bf2ea5b3da3e23f5"
2
+ "engineTag": "1.0.9",
3
+ "builtFrom": "4769315eb49ce1036f888ffafb03881ec4e91131"
4
4
  }
package/lib/create-job.js CHANGED
@@ -180,7 +180,7 @@ function buildPrompt(description, { timezone, existing }) {
180
180
  "",
181
181
  "Before writing anything, read what this deployment actually is:",
182
182
  " - jobs/*.md in your working directory — the house style, and what already exists",
183
- " - systems/ (or ENVIRONMENT.md) — what this deployment can reach, and the variables for each",
183
+ " - systems/ — what this deployment can reach, one file per system, and the variables for each",
184
184
  " - worlds/ if present — the projects/products a job can be pointed at",
185
185
  " - your own available skills — use only skills that exist; never invent a capability",
186
186
  "",
@@ -40,8 +40,8 @@ PART 2 — this deployment's own systems.
40
40
 
41
41
  Part 1 tests what the ENGINE knows how to test. It cannot test a system belonging to this
42
42
  deployment specifically. The register of those is \`systems/\` in your working directory —
43
- one file per system or, in a deployment that has not moved to that yet, a single
44
- ENVIRONMENT.md table. Read whichever is present.
43
+ one file per system. If it is not there, say so and stop: a deployment with no register has
44
+ no systems of its own that anything can check.
45
45
 
46
46
  Each file's frontmatter says what to do:
47
47
  system: what it is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meffecta/agent",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Set up and operate a Meffecta Agent deployment — a self-hosted Claude Code job runner.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,6 +32,7 @@
32
32
  "url": "git+https://github.com/meffecta/agent.git",
33
33
  "directory": "cli"
34
34
  },
35
+ "homepage": "https://agent.meffecta.com",
35
36
  "scripts": {
36
37
  "prepack": "node prepack.mjs",
37
38
  "postpack": "node prepack.mjs --clean"
@@ -8,7 +8,8 @@
8
8
  // Never prints a credential value. Exits 1 if anything configured actually fails.
9
9
 
10
10
  import { execFile } from "node:child_process";
11
- import { readFileSync } from "node:fs";
11
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
12
+ import { join } from "node:path";
12
13
  import { fileURLToPath } from "node:url";
13
14
 
14
15
  const env = process.env;
@@ -674,8 +675,8 @@ results.sort((a, b) => a.name.localeCompare(b.name));
674
675
  // because this script ships to EVERY deployment and knows every integration the engine
675
676
  // supports — which is always more than any one deployment uses. Listing them individually
676
677
  // asks the operator "why is Kleer in my report?", and the honest answer is that it is not
677
- // theirs and never was. The deployment's own register of what it can reach is
678
- // ENVIRONMENT.md in its content repo; the catalogue of what it could add is `connect`.
678
+ // theirs and never was. The deployment's own register of what it can reach is `systems/`
679
+ // in its content repo; the catalogue of what it could add is `connect`.
679
680
  // Credentials this script has never heard of.
680
681
  //
681
682
  // A deployment adds its own systems, and their keys are just secrets bound to the service:
@@ -685,8 +686,8 @@ results.sort((a, b) => a.name.localeCompare(b.name));
685
686
  // "everything works" while a set-but-never-exercised key sits beside it.
686
687
  //
687
688
  // So: name them, say plainly that nothing here can test them, and let the run that called
688
- // this reconcile them against ENVIRONMENT.md — the deployment's own register does know
689
- // what they are and which skill reaches them.
689
+ // this reconcile them against `systems/` — the deployment's own register does know what
690
+ // they are and which skill reaches them.
690
691
  //
691
692
  // Known-ness is decided from this file's own source, so the list maintains itself: if the
692
693
  // script mentions the variable, or the family it belongs to, it knows about it.
@@ -736,9 +737,39 @@ console.log(`\n${configured.length - failures.length} working, ${failures.length
736
737
  if (unknownCredentials.length) {
737
738
  // Names only. This script never prints a value, and that holds hardest for the ones it
738
739
  // does not understand.
740
+ //
741
+ // Which of them are a PROBLEM, though, is a question this script can answer without
742
+ // knowing anything about the systems themselves: the register travels into every run, so
743
+ // it is right here in the working directory. A credential named in it is deliberate, and
744
+ // proving it works is Part 2's job; one named nowhere is a key no skill will ever reach
745
+ // for, however valid it is. Printing the whole list as a to-do told the operator to
746
+ // register things that were already registered, which is how a real gap gets skimmed
747
+ // past.
748
+ const registered = new Set();
749
+ const registerDir = join(process.cwd(), "systems");
750
+ if (existsSync(registerDir)) {
751
+ for (const entry of readdirSync(registerDir)) {
752
+ if (!entry.endsWith(".md")) continue;
753
+ const text = readFileSync(join(registerDir, entry), "utf8");
754
+ for (const name of unknownCredentials) {
755
+ if (text.includes(name)) registered.add(name);
756
+ }
757
+ }
758
+ }
759
+ const unregistered = unknownCredentials.filter((name) => !registered.has(name));
739
760
  console.log(`\nSet, but nothing here knows how to test them (${unknownCredentials.length}):`);
740
761
  console.log(` ${unknownCredentials.join(", ")}`);
741
- console.log(" Each should have a row in ENVIRONMENT.md saying which skill reaches it.");
762
+ if (!existsSync(registerDir)) {
763
+ // No register to read — say the general thing rather than accuse every one of them.
764
+ console.log(" Each needs a file in systems/ saying which skill reaches it.");
765
+ } else {
766
+ if (registered.size) {
767
+ console.log(` In systems/, so a job can reach them: ${[...registered].sort().join(", ")}`);
768
+ }
769
+ if (unregistered.length) {
770
+ console.log(` Not in systems/, so no skill will find them: ${unregistered.join(", ")}`);
771
+ }
772
+ }
742
773
  }
743
774
  if (unconfigured.length) {
744
775
  console.log(`\nNot set up here (${unconfigured.length}): ${unconfigured.map((r) => r.name).join(", ")}.`);