openboot 0.1.0 → 0.1.1

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,18 +1,20 @@
1
- # Boot
1
+ # Openboot
2
2
 
3
- Dev stack lifecycle manager. One command to setup, start, stop, and reboot your projects.
3
+ Every project has the same problem: a README that says "run these 12 commands to get started," a `start.sh` that half works, Docker containers you forgot to start, and env vars you didn't set. New teammates spend hours just trying to run the thing.
4
+
5
+ Then there's the AI problem: every tool wants its own instruction file — `.cursorrules`, `AGENTS.md`, `CLAUDE.md`. `SKILL.md`, `SOUL.md`, `copilot-instructions.md`, and you're copy-pasting the same conventions between projects and files.
6
+
7
+ Boot fixes both. One config file, one command, everything starts, and your AI agent context stays in sync across every tool and every project.
4
8
 
5
9
  ```
6
- boot init → creates boot.yaml (auto-detects your stack)
7
- boot setup → one-time setup (deps, DB, migrations)
8
- boot up → start everything (Docker + apps) in the background
9
- boot up -a start everything + stream logs (Ctrl+C detaches)
10
- boot dev interactive dev mode with live logs (Ctrl+C stops all)
11
- boot down stop everything
12
- boot reboot restart everything
13
- boot status show what's running
14
- boot logs → view service logs (boot logs api -f)
15
- boot clean → nuke deps, caches, build outputs for a fresh start
10
+ boot init → creates boot.yaml (auto-detects your stack)
11
+ boot setup → one-time setup (deps, DB, migrations)
12
+ boot up → start everything (Docker + apps)
13
+ boot dev interactive dev mode with live logs
14
+ boot down stop everything
15
+ boot status show what's running
16
+ boot logs view service logs
17
+ boot agent init generate AI agent context for your tools
16
18
  ```
17
19
 
18
20
  ## Install
@@ -21,252 +23,83 @@ boot clean → nuke deps, caches, build outputs for a fresh start
21
23
  npm install -g openboot
22
24
  ```
23
25
 
24
- Or use without installing:
26
+ ## Quick Start
25
27
 
26
28
  ```bash
27
- npx openboot init
29
+ boot init # auto-detects your stack, creates boot.yaml
30
+ boot setup # install deps, start DB, run migrations
31
+ boot dev # start everything with live logs (Ctrl+C stops all)
28
32
  ```
29
33
 
30
- ## Quick Start
34
+ That's it. Boot detects your Docker services, apps, package manager, env requirements, and generates the config.
35
+
36
+ ## AI Agent Context
37
+
38
+ Boot generates instruction files for AI coding tools — one source of truth, synced to `.cursorrules`, `AGENTS.md`, `CLAUDE.md`, and `.github/copilot-instructions.md`.
31
39
 
32
40
  ```bash
33
- # In any project
34
- boot init # creates boot.yaml by auto-detecting your stack
35
- boot setup # one-time: install deps, start DB, run migrations
36
- boot up # start Docker + all app processes
37
- boot dev # or: start + stream live logs (Ctrl+C stops all)
41
+ boot agent init # generate from your stack + config
42
+ boot agent sync # regenerate after editing boot.yaml
43
+ boot agent check # verify targets are in sync (CI-friendly)
44
+ boot agent remember # save patterns that carry across projects
45
+ boot agent save # push conventions to your global store
46
+ boot agent status # see what Boot knows about your project
38
47
  ```
39
48
 
40
- That's it. `boot init` detects your Docker setup, apps, package manager, env requirements, and generates the config.
49
+ Your conventions live in `~/.boot/agent/` and follow you to every project. When you run `boot agent init` in a new repo, your personal patterns are included automatically.
50
+
51
+ Import from another project:
52
+
53
+ ```bash
54
+ boot agent init --from ~/other-project
55
+ ```
41
56
 
42
57
  ## Config
43
58
 
44
- `boot init` creates a `boot.yaml` in your project root:
59
+ `boot init` creates a `boot.yaml`:
45
60
 
46
61
  ```yaml
47
62
  name: my-project
48
63
 
49
- env:
50
- file: .env
51
- required:
52
- - DATABASE_URL
53
- - JWT_SECRET
54
- reject:
55
- JWT_SECRET:
56
- - your-super-secret-jwt-key-change-this
57
-
58
64
  setup:
59
65
  - pnpm install
60
- - pnpm db:generate
61
66
  - pnpm db:push
62
67
 
63
68
  docker:
64
- # Option A: Docker Compose
65
69
  composeFile: docker-compose.yml
66
70
  services:
67
71
  - name: postgres
68
- container: my-project-postgres
69
72
  readyCheck: pg_isready -U postgres
70
- timeout: 30
71
-
72
- # Option B: Standalone containers (no compose needed)
73
- containers:
74
- - name: my-db
75
- image: postgres:15
76
- ports:
77
- - "5433:5432"
78
- env:
79
- POSTGRES_DB: myapp
80
- POSTGRES_PASSWORD: secret
81
- readyCheck: pg_isready -U postgres
82
- timeout: 30
83
73
 
84
74
  apps:
85
75
  - name: api
86
76
  path: apps/api
87
77
  command: pnpm dev
88
78
  port: 3001
89
- health: http://localhost:3001/health
90
79
  - name: web
91
80
  path: apps/web
92
81
  command: pnpm dev
93
82
  port: 3000
94
- health: http://localhost:3000
95
- ```
96
-
97
- ### Config Reference
98
-
99
- | Field | Description |
100
- |-------|-------------|
101
- | `name` | Project name (display only) |
102
- | `packageManager` | `pnpm`, `npm`, or `yarn` (auto-detected if omitted) |
103
- | **env** | |
104
- | `env.file` | Path to `.env` file (default: `.env`) |
105
- | `env.required` | Env vars that must be set — `boot up` fails if missing |
106
- | `env.reject` | Values to reject per key (blocks example/default secrets) |
107
- | **setup** | |
108
- | `setup` | Commands to run on `boot setup` |
109
- | **docker** | |
110
- | `docker.composeFile` | Path to compose file (default: `docker-compose.yml`) |
111
- | `docker.services[].name` | Compose service name |
112
- | `docker.services[].container` | Container name for `docker exec` |
113
- | `docker.services[].readyCheck` | Command to check if service is ready |
114
- | `docker.services[].timeout` | Seconds to wait for readiness (default: 30) |
115
- | `docker.containers[].name` | Standalone container name |
116
- | `docker.containers[].image` | Docker image (e.g. `postgres:15`) |
117
- | `docker.containers[].ports` | Port mappings (e.g. `"5433:5432"`) |
118
- | `docker.containers[].env` | Environment variables for the container |
119
- | `docker.containers[].volumes` | Volume mounts |
120
- | `docker.containers[].readyCheck` | Readiness check command |
121
- | `docker.containers[].timeout` | Seconds to wait (default: 30) |
122
- | **apps** | |
123
- | `apps[].name` | App name (used for logs and PID tracking) |
124
- | `apps[].path` | Working directory relative to project root |
125
- | `apps[].command` | Command to start the app |
126
- | `apps[].port` | Port the app listens on |
127
- | `apps[].health` | URL to poll for health check |
128
- | `apps[].env` | Extra environment variables |
129
-
130
- ## What `boot init` Auto-Detects
131
-
132
- - **Package manager** — from lockfiles (`pnpm-lock.yaml`, `yarn.lock`, `package-lock.json`)
133
- - **Docker Compose** — `docker-compose.yml` / `compose.yml`
134
- - **Raw Docker containers** — scans `scripts/*.sh` for `docker start` / `docker run` patterns
135
- - **Database services** — Postgres, MySQL, Redis (with appropriate readiness checks)
136
- - **Monorepo apps** — scans `apps/*/package.json` for dev scripts
137
- - **Sub-directory apps** — detects `dashboard/`, `frontend/`, `backend/`, `server/`, etc.
138
- - **Single-app projects** — detects `dev` or `start` scripts in root `package.json`
139
- - **Prisma** — detects `prisma/` directory and adds generate/push to setup
140
- - **Ports** — guesses 3000 for web/frontend, 3001 for api/server
141
- - **`.env` requirements** — parses `env.example` / `.env.example` for required and sensitive vars
142
-
143
- ## What Each Command Does
144
-
145
- ### `boot up`
146
-
147
- 1. Checks prerequisites (Node.js 18+, Docker if needed)
148
- 2. Auto-creates `.env` from template (`env.example` / `.env.example`) if missing
149
- 3. Validates `.env` file (required vars, rejects default secrets)
150
- 4. Ensures package manager is available (auto-enables pnpm/yarn via corepack)
151
- 5. Auto-installs root deps if `node_modules` is missing
152
- 6. Auto-installs per-app deps in monorepo sub-apps
153
- 7. Smart Prisma check — generates client only if `.prisma` is missing
154
- 8. Starts Docker (compose services and/or standalone containers)
155
- 9. Waits for each service's readiness check
156
- 10. Starts each app in the background
157
- 11. Polls health URLs until ready
158
- 12. Prints summary with URLs
159
-
160
- #### `boot up --attach` / `boot up -a`
161
-
162
- Same as `boot up` but after starting, streams all app logs to your terminal (color-coded by service). Press Ctrl+C to detach — services keep running in the background.
163
-
164
- ### `boot dev`
165
-
166
- Interactive development mode — the closest replacement for your old `start.sh` scripts:
167
83
 
168
- 1. Starts Docker services
169
- 2. Starts all apps
170
- 3. Streams live, color-coded logs for every service
171
- 4. **Ctrl+C gracefully stops everything** (apps + Docker)
172
-
173
- This is the "one terminal" experience. No separate tabs needed.
174
-
175
- ### `boot down`
176
-
177
- 1. Stops all tracked app processes (SIGTERM → SIGKILL)
178
- 2. Falls back to `pkill -f` if PID file is stale (catches orphan processes)
179
- 3. Force-kills anything still holding app ports
180
- 4. Stops standalone Docker containers
181
- 5. Stops Docker Compose services
182
-
183
- ### `boot status`
184
-
185
- Shows a table of all services with:
186
- - Status (running / stopped / port in use)
187
- - Port numbers
188
- - PIDs (with mismatch warnings if PID file ≠ port owner)
189
- - Process name (what binary is actually running, e.g. `node`, `nuxt`)
190
- - Live health checks (curl for apps, `pg_isready` / `redis-cli ping` for DBs)
191
- - Log file paths
192
-
193
- ### `boot clean`
194
-
195
- Nukes everything for a fresh start:
196
- 1. Removes `node_modules` in root and all sub-apps
197
- 2. Removes lockfiles (`package-lock.json`, `yarn.lock`)
198
- 3. Removes caches (`.nuxt`, `.next`, `.turbo`, `.vite`, `.parcel-cache`)
199
- 4. Removes build outputs (`dist/`, `build/`)
200
- 5. Removes `.boot/` runtime data (PIDs, logs)
201
- 6. Pass `--all` to also remove `pnpm-lock.yaml`
202
-
203
- ### `boot logs`
204
-
205
- View logs for any service:
206
- ```bash
207
- boot logs # show recent logs for all services
208
- boot logs api # show logs for a specific service
209
- boot logs api -f # follow mode (like tail -f)
210
- boot logs api -n 100 # last 100 lines
211
- boot logs postgres # Docker container logs too
212
- ```
213
-
214
- ### `boot setup`
215
-
216
- One-time setup with smart Prisma handling:
217
- 1. Checks prerequisites (Node.js, Docker)
218
- 2. Auto-creates `.env` from template
219
- 3. Starts Docker services (DB needs to be up for migrations)
220
- 4. Runs configured setup commands
221
- 5. Smart Prisma: generate client + migrations with fallback (`migrate deploy` → `db push`)
222
- 6. Non-fatal seed failures (skips gracefully)
223
-
224
- ### `boot reboot`
225
-
226
- Runs `down` then `up`.
227
-
228
- ## Development Workflow
229
-
230
- ```bash
231
- # Option 1: Background (CI-friendly, scriptable)
232
- boot up # starts everything, exits immediately
233
- boot logs api -f # follow one service's logs in another terminal
234
- boot down # stop when done
235
-
236
- # Option 2: Attach (start background + watch logs)
237
- boot up --attach # starts everything, streams logs; Ctrl+C detaches (services stay up)
238
- boot down # stop when done
84
+ env:
85
+ required:
86
+ - DATABASE_URL
87
+ - JWT_SECRET
239
88
 
240
- # Option 3: Interactive (replaces start.sh)
241
- boot dev # starts everything + live logs; Ctrl+C stops everything
89
+ agent:
90
+ conventions:
91
+ - Use server components by default
92
+ - All DB access through Prisma
93
+ targets:
94
+ - .cursorrules
95
+ - AGENTS.md
96
+ - CLAUDE.md
97
+ - .github/copilot-instructions.md
242
98
  ```
243
99
 
244
- ## Docker Support
245
-
246
- Boot handles two styles of Docker usage:
247
-
248
- ### Docker Compose
249
- For projects with a `docker-compose.yml`:
250
- - `boot up` runs `docker compose up -d`
251
- - Detects port conflicts and auto-remaps to free ports
252
- - Reuses existing containers when possible
253
-
254
- ### Standalone Containers
255
- For projects that use raw `docker run` (no compose):
256
- - Starts existing stopped containers with `docker start`
257
- - Creates new containers with `docker run -d` if needed
258
- - Port conflict detection + auto-remap
259
-
260
- ## Process Management
261
-
262
- - App processes run in the background (detached)
263
- - PIDs are stored in `.boot/pids/`
264
- - Logs are written to `.boot/logs/`
265
- - `boot down` kills the full process tree (not just the parent)
266
- - Falls back to `pkill -f` for orphan process cleanup
267
- - Ports are freed before starting if occupied
100
+ ## Docs
268
101
 
269
- Add `.boot/` to your `.gitignore`.
102
+ See [DETAILED.md](DETAILED.md) for the full config reference, auto-detection list, and command details.
270
103
 
271
104
  ## License
272
105
 
package/dist/cli.js CHANGED
@@ -11,11 +11,12 @@ const status_1 = require("./commands/status");
11
11
  const clean_1 = require("./commands/clean");
12
12
  const logs_1 = require("./commands/logs");
13
13
  const dev_1 = require("./commands/dev");
14
+ const agent_1 = require("./commands/agent");
14
15
  const program = new commander_1.Command();
15
16
  program
16
17
  .name("boot")
17
18
  .description("Dev stack lifecycle manager. One command to setup, start, stop, and reboot your projects.")
18
- .version("0.1.0");
19
+ .version("0.1.1");
19
20
  program
20
21
  .command("init")
21
22
  .description("Auto-detect project structure and create boot.yaml")
@@ -128,5 +129,6 @@ program
128
129
  process.exit(1);
129
130
  }
130
131
  });
132
+ (0, agent_1.registerAgentCommands)(program);
131
133
  program.parse();
132
134
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * Register all `boot agent` subcommands on the program.
4
+ */
5
+ export declare function registerAgentCommands(program: Command): void;
6
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8R5D"}
@@ -0,0 +1,293 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.registerAgentCommands = registerAgentCommands;
37
+ const path = __importStar(require("path"));
38
+ const log_1 = require("../lib/log");
39
+ const config_1 = require("../lib/config");
40
+ const agent_1 = require("../lib/agent");
41
+ /**
42
+ * Register all `boot agent` subcommands on the program.
43
+ */
44
+ function registerAgentCommands(program) {
45
+ const agent = program
46
+ .command("agent")
47
+ .description("Manage AI agent context for your project");
48
+ // ─────────────────────────────────────────────
49
+ // boot agent init
50
+ // ─────────────────────────────────────────────
51
+ agent
52
+ .command("init")
53
+ .description("Generate AI agent context from your project stack")
54
+ .option("--from <path>", "Import conventions from another project")
55
+ .option("--no-global", "Exclude personal/global conventions from output")
56
+ .action(async (opts) => {
57
+ try {
58
+ const cwd = process.cwd();
59
+ log_1.log.header("boot agent init");
60
+ // Import from another project if --from specified
61
+ if (opts.from) {
62
+ const sourcePath = path.resolve(opts.from);
63
+ log_1.log.info(`Importing conventions from ${sourcePath}`);
64
+ const imported = (0, agent_1.importFromProject)(sourcePath);
65
+ if (imported.length > 0) {
66
+ (0, agent_1.saveGlobalConventions)(imported);
67
+ log_1.log.success(`Imported ${imported.length} conventions to global store`);
68
+ }
69
+ else {
70
+ log_1.log.warn("No conventions found in source project");
71
+ }
72
+ }
73
+ // Get or detect config
74
+ const config = (0, agent_1.getOrDetectConfig)(cwd);
75
+ // Show detected stack
76
+ const stack = (0, agent_1.detectStack)(cwd);
77
+ if (stack.length > 0) {
78
+ log_1.log.info(`Stack: ${stack.map(agent_1.formatStackName).join(", ")}`);
79
+ }
80
+ // Show detected agent files
81
+ const existingFiles = (0, agent_1.detectAgentFiles)(cwd);
82
+ if (existingFiles.length > 0) {
83
+ log_1.log.info(`Existing agent files: ${existingFiles.join(", ")}`);
84
+ }
85
+ // Add agent section to boot.yaml if it exists but has no agent config
86
+ const configPath = (0, config_1.findConfig)(cwd);
87
+ if (configPath && !config.agent) {
88
+ const defaultAgent = {
89
+ targets: agent_1.DEFAULT_TARGETS,
90
+ };
91
+ (0, agent_1.addAgentSection)(configPath, defaultAgent);
92
+ config.agent = defaultAgent;
93
+ log_1.log.success("Added agent section to boot.yaml");
94
+ }
95
+ // Generate and sync
96
+ const markdown = (0, agent_1.generateAgentMarkdown)(config, cwd, {
97
+ includeGlobal: opts.global,
98
+ });
99
+ const written = (0, agent_1.syncTargets)(config, markdown, cwd);
100
+ log_1.log.blank();
101
+ for (const file of written) {
102
+ log_1.log.success(`Wrote ${file}`);
103
+ }
104
+ log_1.log.blank();
105
+ log_1.log.step("Agent context synced to all targets.");
106
+ log_1.log.step("Edit the agent section in boot.yaml to add conventions.");
107
+ log_1.log.step("Run `boot agent sync` after making changes.");
108
+ log_1.log.blank();
109
+ }
110
+ catch (err) {
111
+ log_1.log.error(err.message);
112
+ process.exit(1);
113
+ }
114
+ });
115
+ // ─────────────────────────────────────────────
116
+ // boot agent sync
117
+ // ─────────────────────────────────────────────
118
+ agent
119
+ .command("sync")
120
+ .description("Regenerate and sync agent context to all target files")
121
+ .option("--no-global", "Exclude personal/global conventions from output")
122
+ .action(async (opts) => {
123
+ try {
124
+ const cwd = process.cwd();
125
+ const config = (0, agent_1.getOrDetectConfig)(cwd);
126
+ const markdown = (0, agent_1.generateAgentMarkdown)(config, cwd, {
127
+ includeGlobal: opts.global,
128
+ });
129
+ const written = (0, agent_1.syncTargets)(config, markdown, cwd);
130
+ for (const file of written) {
131
+ log_1.log.success(`Synced ${file}`);
132
+ }
133
+ }
134
+ catch (err) {
135
+ log_1.log.error(err.message);
136
+ process.exit(1);
137
+ }
138
+ });
139
+ // ─────────────────────────────────────────────
140
+ // boot agent check
141
+ // ─────────────────────────────────────────────
142
+ agent
143
+ .command("check")
144
+ .description("Check if agent target files are in sync with config")
145
+ .action(async () => {
146
+ try {
147
+ const cwd = process.cwd();
148
+ const config = (0, agent_1.getOrDetectConfig)(cwd);
149
+ const result = (0, agent_1.checkSync)(config, cwd);
150
+ for (const file of result.ok) {
151
+ log_1.log.success(`${file} — in sync`);
152
+ }
153
+ for (const file of result.stale) {
154
+ log_1.log.warn(`${file} — out of date`);
155
+ }
156
+ for (const file of result.missing) {
157
+ log_1.log.error(`${file} — missing`);
158
+ }
159
+ if (result.stale.length > 0 || result.missing.length > 0) {
160
+ log_1.log.blank();
161
+ log_1.log.step("Run `boot agent sync` to update all targets.");
162
+ process.exit(1);
163
+ }
164
+ }
165
+ catch (err) {
166
+ log_1.log.error(err.message);
167
+ process.exit(1);
168
+ }
169
+ });
170
+ // ─────────────────────────────────────────────
171
+ // boot agent save
172
+ // ─────────────────────────────────────────────
173
+ agent
174
+ .command("save")
175
+ .description("Save project conventions to your global store (~/.boot/agent/)")
176
+ .action(async () => {
177
+ try {
178
+ const cwd = process.cwd();
179
+ const config = (0, agent_1.getOrDetectConfig)(cwd);
180
+ if (!config.agent?.conventions ||
181
+ config.agent.conventions.length === 0) {
182
+ log_1.log.warn("No conventions defined in boot.yaml agent section.");
183
+ log_1.log.blank();
184
+ log_1.log.step("Add conventions to boot.yaml first:");
185
+ log_1.log.step("");
186
+ log_1.log.step(" agent:");
187
+ log_1.log.step(" conventions:");
188
+ log_1.log.step(' - "Your convention here"');
189
+ return;
190
+ }
191
+ (0, agent_1.saveGlobalConventions)(config.agent.conventions);
192
+ log_1.log.success(`Saved ${config.agent.conventions.length} conventions to global store`);
193
+ log_1.log.step(`Location: ${agent_1.AGENT_HOME}/conventions.md`);
194
+ }
195
+ catch (err) {
196
+ log_1.log.error(err.message);
197
+ process.exit(1);
198
+ }
199
+ });
200
+ // ─────────────────────────────────────────────
201
+ // boot agent remember
202
+ // ─────────────────────────────────────────────
203
+ agent
204
+ .command("remember <text...>")
205
+ .description("Remember a convention or pattern across all projects")
206
+ .action(async (textParts) => {
207
+ try {
208
+ const text = textParts.join(" ");
209
+ (0, agent_1.addMemory)(text);
210
+ log_1.log.success(`Remembered: ${text}`);
211
+ log_1.log.step("This will be included in all future agent context generation.");
212
+ }
213
+ catch (err) {
214
+ log_1.log.error(err.message);
215
+ process.exit(1);
216
+ }
217
+ });
218
+ // ─────────────────────────────────────────────
219
+ // boot agent status
220
+ // ─────────────────────────────────────────────
221
+ agent
222
+ .command("status")
223
+ .description("Show agent context status for this project")
224
+ .action(async () => {
225
+ try {
226
+ const cwd = process.cwd();
227
+ log_1.log.header("boot agent status");
228
+ // Stack
229
+ const stack = (0, agent_1.detectStack)(cwd);
230
+ if (stack.length > 0) {
231
+ log_1.log.info(`Stack: ${stack.map(agent_1.formatStackName).join(", ")}`);
232
+ }
233
+ else {
234
+ log_1.log.info("Stack: (none detected)");
235
+ }
236
+ // Existing agent files
237
+ const files = (0, agent_1.detectAgentFiles)(cwd);
238
+ if (files.length > 0) {
239
+ log_1.log.info(`Agent files: ${files.join(", ")}`);
240
+ }
241
+ else {
242
+ log_1.log.info("Agent files: (none found)");
243
+ }
244
+ // Config status
245
+ const configPath = (0, config_1.findConfig)(cwd);
246
+ if (configPath) {
247
+ const config = (0, config_1.loadConfig)(cwd);
248
+ if (config.agent) {
249
+ log_1.log.info("Config: boot.yaml has agent section");
250
+ if (config.agent.conventions?.length) {
251
+ log_1.log.step(` ${config.agent.conventions.length} project conventions`);
252
+ }
253
+ if (config.agent.targets?.length) {
254
+ log_1.log.step(` Targets: ${config.agent.targets.join(", ")}`);
255
+ }
256
+ }
257
+ else {
258
+ log_1.log.info("Config: boot.yaml exists but no agent section");
259
+ }
260
+ }
261
+ else {
262
+ log_1.log.info("Config: no boot.yaml (run `boot init` first)");
263
+ }
264
+ // Global store
265
+ const globalConv = (0, agent_1.loadGlobalConventions)();
266
+ const globalMem = (0, agent_1.loadGlobalMemory)();
267
+ log_1.log.info(`Global: ${globalConv.length} conventions, ${globalMem.length} remembered patterns`);
268
+ if (globalConv.length > 0 || globalMem.length > 0) {
269
+ log_1.log.step(` Location: ${agent_1.AGENT_HOME}`);
270
+ }
271
+ // Sync status
272
+ if (configPath) {
273
+ const config = (0, config_1.loadConfig)(cwd);
274
+ const sync = (0, agent_1.checkSync)(config, cwd);
275
+ log_1.log.blank();
276
+ if (sync.ok.length > 0) {
277
+ log_1.log.success(`${sync.ok.length} target(s) in sync`);
278
+ }
279
+ if (sync.stale.length > 0) {
280
+ log_1.log.warn(`${sync.stale.length} target(s) out of date — run \`boot agent sync\``);
281
+ }
282
+ if (sync.missing.length > 0) {
283
+ log_1.log.warn(`${sync.missing.length} target(s) missing — run \`boot agent sync\``);
284
+ }
285
+ }
286
+ }
287
+ catch (err) {
288
+ log_1.log.error(err.message);
289
+ process.exit(1);
290
+ }
291
+ });
292
+ }
293
+ //# sourceMappingURL=agent.js.map