macaw-ai 0.9.14 → 0.9.15

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.
Files changed (3) hide show
  1. package/README.md +8 -7
  2. package/bin/macaw.js +21 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -4,14 +4,15 @@ Deterministic controls for agents. One command, and it asks what you want
4
4
  governed.
5
5
 
6
6
  ```bash
7
- npx macaw-ai install
7
+ npx macaw-ai install --system # every directory, for you; the sidecar runs as a service
8
+ npx macaw-ai install --local # this project only
8
9
  ```
9
10
 
10
11
  ```
11
- 1) Claude Code and Codex on this machine
12
+ 1) Claude Code and Codex
12
13
  every tool call stops at a hook and waits for a decision
13
- 2) a Python project
14
- the SDK and adapters, for agents you write yourself
14
+ 2) the MACAW SDK Client Library and secureAI adapters
15
+ drop-in adapters for popular agentic frameworks
15
16
  3) both
16
17
  ```
17
18
 
@@ -19,15 +20,15 @@ It installs nothing itself — it hands off to the package that does that one
19
20
  thing. Name the surface and it asks nothing:
20
21
 
21
22
  ```bash
22
- npx macaw-ai install --coding-agents
23
+ npx macaw-ai install --coding-agents --system
23
24
  npx macaw-ai install --client
24
25
  ```
25
26
 
26
27
  Or go straight there:
27
28
 
28
29
  ```bash
29
- npx @macaw-ai/coding-agents install
30
- npx @macaw-ai/client install
30
+ npm install -g @macaw-ai/coding-agents && macaw-sidecar install --system
31
+ npm install -g @macaw-ai/client && macaw-client install
31
32
  ```
32
33
 
33
34
  ## What each one does
package/bin/macaw.js CHANGED
@@ -9,6 +9,7 @@
9
9
  import { spawnSync } from "node:child_process";
10
10
  import { createInterface } from "node:readline/promises";
11
11
  import fs from "node:fs";
12
+ import os from "node:os";
12
13
  import path from "node:path";
13
14
 
14
15
  const SURFACES = [
@@ -19,6 +20,7 @@ const SURFACES = [
19
20
  detail: "every tool call stops at a hook and waits for a decision",
20
21
  command: "macaw-sidecar",
21
22
  subcommand: true,
23
+ hint: "install --local (or --system: every directory, as a service)",
22
24
  },
23
25
  {
24
26
  key: "2",
@@ -27,6 +29,7 @@ const SURFACES = [
27
29
  detail: "drop-in adapters for popular agentic frameworks",
28
30
  command: "macaw-client",
29
31
  subcommand: true,
32
+ hint: "install",
30
33
  },
31
34
  ];
32
35
 
@@ -51,17 +54,22 @@ function run(surface, args, env) {
51
54
  return sh(surface.command, rest, env);
52
55
  }
53
56
 
54
- // The coding-agents installer writes its key here. Reading it back lets the
55
- // second surface join that workspace without asking for a key the user
56
- // approved thirty seconds earlier.
57
- function keyFromThisDirectory() {
58
- try {
59
- const cfg = JSON.parse(fs.readFileSync(path.join(process.cwd(), ".macaw", "config.json"), "utf8"));
60
- if (typeof cfg?.api_key === "string" && cfg.api_key.startsWith("mw_")) {
61
- return { MACAW_API_KEY: cfg.api_key, MACAW_WORKSPACE: cfg.workspace || "" };
57
+ // The coding-agents installer writes its key here: in this directory for
58
+ // --local, in the home directory for --system. Reading it back lets the second
59
+ // surface join that workspace without asking for a key the user approved
60
+ // thirty seconds earlier. The scope decides which to read first, so a project
61
+ // install left in this directory cannot stand in for the one just made.
62
+ function keyFromInstall(args) {
63
+ const dirs = args.includes("--system") ? [os.homedir(), process.cwd()] : [process.cwd(), os.homedir()];
64
+ for (const dir of dirs) {
65
+ try {
66
+ const cfg = JSON.parse(fs.readFileSync(path.join(dir, ".macaw", "config.json"), "utf8"));
67
+ if (typeof cfg?.api_key === "string" && cfg.api_key.startsWith("mw_")) {
68
+ return { MACAW_API_KEY: cfg.api_key, MACAW_WORKSPACE: cfg.workspace || "" };
69
+ }
70
+ } catch {
71
+ // No install there, or not readable. The next installer asks, as it would.
62
72
  }
63
- } catch {
64
- // No install here, or not readable. The next installer asks, as it would.
65
73
  }
66
74
  return undefined;
67
75
  }
@@ -71,7 +79,7 @@ function keyFromThisDirectory() {
71
79
  // the client rather than asked for again.
72
80
  //
73
81
  // The order is load-bearing the other way too: coding-agents writes
74
- // $PWD/.macaw/config.json, which the client's lookup reads. The client writes
82
+ // .macaw/config.json where keyFromInstall looks for it. The client writes
75
83
  // into a subdirectory it chooses, which nothing else can be expected to find.
76
84
  function both(args) {
77
85
  const steps = args.length ? args : ["install"];
@@ -80,7 +88,7 @@ function both(args) {
80
88
  // restarted. Say which step this is.
81
89
  console.log("");
82
90
  console.log(`${C.b} ── ${i + 1} of ${SURFACES.length} · ${s.label} ──${C.x}`);
83
- const code = run(s, steps, i === 0 ? undefined : keyFromThisDirectory());
91
+ const code = run(s, steps, i === 0 ? undefined : keyFromInstall(steps));
84
92
  if (code !== 0) return code;
85
93
  }
86
94
  return 0;
@@ -120,7 +128,7 @@ async function main() {
120
128
  if (!process.stdin.isTTY) {
121
129
  console.log(" Nothing is attached to answer, so pick one directly:");
122
130
  for (const s of SURFACES) {
123
- console.log(` npm install -g ${s.pkg} && ${s.command}${s.subcommand ? " install" : ""}`);
131
+ console.log(` npm install -g ${s.pkg} && ${s.command} ${s.hint}`);
124
132
  }
125
133
  console.log("");
126
134
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "macaw-ai",
3
- "version": "0.9.14",
3
+ "version": "0.9.15",
4
4
  "description": "Deterministic controls for agents. Ask MACAW to govern your coding agent or your Python project, and it installs the right thing.",
5
5
  "type": "module",
6
6
  "bin": {