@owlmetry/cli 0.1.2 → 0.1.6

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/dist/index.cjs CHANGED
@@ -6262,10 +6262,19 @@ projectsCommand.command("view <id>").description("View project details").action(
6262
6262
  const project = await client.getProject(id);
6263
6263
  output(globals.format, project, () => formatProjectDetail(project));
6264
6264
  });
6265
- projectsCommand.command("create").description("Create a new project").requiredOption("--team-id <id>", "Team ID").requiredOption("--name <name>", "Project name").requiredOption("--slug <slug>", "Project slug").action(async (opts, cmd) => {
6265
+ projectsCommand.command("create").description("Create a new project").option("--team-id <id>", "Team ID (defaults to active team)").requiredOption("--name <name>", "Project name").requiredOption("--slug <slug>", "Project slug").action(async (opts, cmd) => {
6266
6266
  const { client, globals } = createClient(cmd);
6267
+ let teamId = opts.teamId;
6268
+ if (!teamId) {
6269
+ const config = loadConfig();
6270
+ if (!config) {
6271
+ throw new Error("No team ID specified and no config found. Use --team-id or run `owlmetry auth verify` first.");
6272
+ }
6273
+ const resolved = getActiveProfile(config, globals.team);
6274
+ teamId = resolved.teamId;
6275
+ }
6267
6276
  const project = await client.createProject({
6268
- team_id: opts.teamId,
6277
+ team_id: teamId,
6269
6278
  name: opts.name,
6270
6279
  slug: opts.slug
6271
6280
  });
@@ -7174,7 +7183,7 @@ var switchCommand = new Command("switch").description("Switch active team profil
7174
7183
  });
7175
7184
 
7176
7185
  // src/index.ts
7177
- var program2 = new Command().name("owlmetry").version("0.1.2").description("OwlMetry CLI \u2014 query metrics and manage your apps from the terminal").addOption(
7186
+ var program2 = new Command().name("owlmetry").version("0.1.6").description("OwlMetry CLI \u2014 query metrics and manage your apps from the terminal").addOption(
7178
7187
  new Option("--format <format>", "Output format").choices(["table", "json", "log"]).default("table")
7179
7188
  ).option("--endpoint <url>", "OwlMetry API server URL").option("--api-key <key>", "API key").option("--ingest-endpoint <url>", "OwlMetry ingest endpoint URL (for SDKs; defaults to API endpoint for self-hosted)").option("--team <name-or-id>", "Use a specific team profile for this command");
7180
7189
  program2.addCommand(authCommand);
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: owlmetry-cli
3
- version: 0.1.0
3
+ version: 0.1.6
4
4
  description: >-
5
5
  Install the OwlMetry CLI, sign up, and manage projects, apps, metrics,
6
6
  funnels, and events. Use when adding OwlMetry to a project, querying
@@ -121,7 +121,7 @@ Projects group apps by product and scope metrics and funnels. Create one project
121
121
  ```bash
122
122
  owlmetry projects --format json # List all
123
123
  owlmetry projects view <id> --format json # View details + apps
124
- owlmetry projects create --team-id <id> --name <name> --slug <slug> --format json
124
+ owlmetry projects create --name <name> --slug <slug> [--team-id <id>] --format json
125
125
  owlmetry projects update <id> --name <new-name> --format json
126
126
  ```
127
127
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: owlmetry-node
3
- version: 0.1.0
3
+ version: 0.1.6
4
4
  description: >-
5
5
  Integrate the OwlMetry Node.js SDK into a backend service for server-side
6
6
  analytics, event tracking, metrics, funnels, and A/B experiments. Use when
@@ -37,6 +37,8 @@ Zero runtime dependencies. Node.js 20+. ESM only.
37
37
 
38
38
  ## Configure
39
39
 
40
+ Place `Owl.configure()` in the **main entry point** of your service — the root `index.ts`, `server.ts`, or `app.ts` file where your server starts. It must run once at process startup, before any other `Owl` calls. Do **not** put it in a helper/utility file — it should be alongside your other top-level initialization (e.g., `express()`, `Fastify()`, Firebase `setGlobalOptions`).
41
+
40
42
  ```typescript
41
43
  import { Owl } from '@owlmetry/node';
42
44
 
@@ -57,15 +59,25 @@ Owl.configure({
57
59
  - Generates a fresh `sessionId` (UUID) on each `configure()` call
58
60
  - Registers a `beforeExit` handler to auto-flush on graceful shutdown
59
61
 
62
+ **Serverless (Firebase Cloud Functions, AWS Lambda, Vercel):** After adding `Owl.configure()`, also wrap your exported handler functions with `Owl.wrapHandler()` to guarantee events are flushed before the runtime freezes. This is essential boilerplate for serverless — without it, buffered events are lost:
63
+
64
+ ```typescript
65
+ // Before:
66
+ export const myFunction = onCall(async (request) => { ... });
67
+
68
+ // After:
69
+ export const myFunction = onCall(Owl.wrapHandler(async (request) => { ... }));
70
+ ```
71
+
60
72
  ## Next Steps — Codebase Instrumentation
61
73
 
62
- Once `Owl.configure()` is in place and the project builds, **stop and ask the user** which area they'd like to instrument first. Present these three options:
74
+ Once `Owl.configure()` is in place and the project builds successfully, **you MUST stop here and ask the user** which area they'd like to instrument first — even if the user's original prompt asked you to "instrument the app." Do not proceed with any code changes until the user chooses. Present these three options:
63
75
 
64
76
  1. **Event & error logging** — Audit the codebase for request handlers, error paths, background jobs, and key operations. Add `Owl.info()`, `Owl.warn()`, `Owl.error()` calls at meaningful points throughout the service. This is SDK-only — no CLI setup required beyond what's already done.
65
77
  2. **Structured metrics** — Identify operations worth measuring (API response times, database queries, external service calls, etc.). Add `Owl.startOperation()` / `Owl.recordMetric()` to track durations and success rates. **Requires CLI first:** each metric slug must be defined on the server via `owlmetry metrics create` (use the `/owlmetry-cli` skill) before the SDK can emit events for it.
66
78
  3. **Funnel tracking** — Identify server-side user journeys (sign-up flow, payment processing, onboarding steps). Add `Owl.track()` calls at each step to measure drop-off. **Requires CLI first:** the funnel definition (with steps and event filters) must be created via `owlmetry funnels create` (use the `/owlmetry-cli` skill) before tracking makes sense.
67
79
 
68
- Wait for the user to choose before proceeding. For whichever option they pick, do a thorough audit of the entire codebase to find all relevant locations, then present a summary of proposed changes before making any edits.
80
+ After the user chooses, do a thorough audit of the entire codebase to find all relevant locations, then present a summary of proposed changes before making any edits.
69
81
 
70
82
  ## Buffering and Delivery
71
83
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: owlmetry-swift
3
- version: 0.1.0
3
+ version: 0.1.6
4
4
  description: >-
5
5
  Integrate the OwlMetry Swift SDK into an iOS or macOS app for analytics,
6
6
  event tracking, metrics, funnels, and A/B experiments. Use when
@@ -68,7 +68,7 @@ Once the user confirms the package is added, retry the build to verify, then pro
68
68
 
69
69
  ## Configure
70
70
 
71
- Configuration must happen once, before any other `Owl` calls typically in your `@main` App init or AppDelegate `didFinishLaunching`. Each `configure()` call generates a fresh `session_id` (UUID) that groups all subsequent events together. This means each app launch gets its own session, making it easy to see everything a user did in a single sitting.
71
+ Configuration must happen once, as early as possible — in the `@main` App `init()` or AppDelegate `didFinishLaunching`. **Do not defer it** to a later point (e.g., after async setup or user consent). The SDK measures app launch time (`_launch_ms`) from process start to the `configure()` call, so placing it early gives an accurate cold-start metric. It also ensures no events are dropped before configuration. Each `configure()` call generates a fresh `session_id` (UUID) that groups all subsequent events together.
72
72
 
73
73
  ```swift
74
74
  import OwlMetry
@@ -94,18 +94,92 @@ struct MyApp: App {
94
94
  - `apiKey: String` — client key, must start with `owl_client_` (required)
95
95
  - `flushOnBackground: Bool` — auto-flush when app backgrounds (default: `true`)
96
96
  - `compressionEnabled: Bool` — gzip request bodies (default: `true`)
97
+ - `networkTrackingEnabled: Bool` — auto-track URLSession HTTP requests (default: `true`)
97
98
 
98
99
  Auto-detects: bundle ID, debug mode (`#if DEBUG`). Auto-generates: session ID (fresh each launch).
99
100
 
101
+ ## User Identity (set up during initial configuration)
102
+
103
+ After adding `Owl.configure()`, find where the app handles authentication and add `Owl.setUser()` / `Owl.clearUser()`. This is part of the basic setup — do it now, before moving on to instrumentation.
104
+
105
+ Look for the auth state change handler (e.g., Firebase Auth listener, login/logout methods) and add:
106
+
107
+ ```swift
108
+ // After successful login — claims all previous anonymous events for this user
109
+ Owl.setUser(userId)
110
+
111
+ // On logout — reverts to anonymous tracking
112
+ Owl.clearUser()
113
+ ```
114
+
115
+ **Where to find it:** Search for login/logout methods, auth state listeners, or session management code. Look for patterns like setting a user ID on other services (crash reporting, analytics), storing auth tokens, or clearing user state. Place `Owl.setUser()` right after the user ID becomes available. Place `Owl.clearUser()` in the sign-out/logout handler.
116
+
117
+ The SDK automatically flushes buffered events before claiming identity, so anonymous events from before login are retroactively linked to the user.
118
+
100
119
  ## Next Steps — Codebase Instrumentation
101
120
 
102
- Once `Owl.configure()` is in place and the project builds, **stop and ask the user** which area they'd like to instrument first. Present these three options:
121
+ Once `Owl.configure()` is in place and the project builds successfully, **you MUST stop here and ask the user** which area they'd like to instrument first — even if the user's original prompt asked you to "instrument the app." Do not proceed with any code changes until the user chooses. Present these options:
122
+
123
+ 1. **Screen tracking** — Add `.owlScreen("ScreenName")` to every distinct screen in the app. This is the quickest win — automatic screen view and time-on-screen tracking with a single modifier per screen. No CLI setup needed.
124
+ 2. **Event & error logging** — Audit the codebase for user actions, error handling, and key flows. Add `Owl.info()`, `Owl.warn()`, `Owl.error()` calls at meaningful points. This is SDK-only — no CLI setup required beyond what's already done.
125
+ 3. **Structured metrics** — Identify operations worth measuring (data loading, image processing, etc.). Add `Owl.startOperation()` / `Owl.recordMetric()` to track durations and success rates. **Requires CLI first:** each metric slug must be defined on the server via `owlmetry metrics create` (use the `/owlmetry-cli` skill) before the SDK can emit events for it.
126
+ 4. **Funnel tracking** — Identify user journeys (onboarding, checkout, key conversions). Add `Owl.track()` calls at each step to measure drop-off. **Requires CLI first:** the funnel definition (with steps and event filters) must be created via `owlmetry funnels create` (use the `/owlmetry-cli` skill) before tracking makes sense.
127
+
128
+ After the user chooses, do a thorough audit of the entire codebase to find all relevant locations, then present a summary of proposed changes before making any edits.
129
+
130
+ ## Screen Tracking (`.owlScreen()`)
131
+
132
+ The SDK provides a SwiftUI view modifier that automatically tracks screen appearances and time-on-screen with zero manual event calls.
133
+
134
+ ```swift
135
+ struct HomeView: View {
136
+ var body: some View {
137
+ VStack { ... }
138
+ .owlScreen("Home")
139
+ }
140
+ }
141
+
142
+ struct SettingsView: View {
143
+ var body: some View {
144
+ Form { ... }
145
+ .owlScreen("Settings")
146
+ }
147
+ }
148
+ ```
149
+
150
+ **What it does automatically:**
151
+ - On appear: emits `sdk:screen_appeared` (info level) with `screenName` set — included in production data
152
+ - On disappear: emits `sdk:screen_disappeared` (debug level) with `screenName` set and `_duration_ms` attribute — only visible in dev data mode
153
+
154
+ **Where to place it:** Attach `.owlScreen("ScreenName")` to the outermost view of each screen — typically on the `NavigationStack`, `Form`, `ScrollView`, or root `VStack`. Use it on every distinct screen in the app. Choose names that are short, readable, and consistent (e.g., `"Home"`, `"Settings"`, `"Profile"`, `"Checkout"`).
155
+
156
+ **Prefer `.owlScreen()` over manual `Owl.info()` for screen views** — it handles both appear and disappear with duration tracking. Use manual `Owl.info()` with `screenName:` only for events within a screen (button taps, state changes), not for screen appearances themselves.
103
157
 
104
- 1. **Event & error logging** — Audit the codebase for user actions, screen views, error handling, and key flows. Add `Owl.info()`, `Owl.warn()`, `Owl.error()` calls at meaningful points. This is SDK-only — no CLI setup required beyond what's already done.
105
- 2. **Structured metrics** — Identify operations worth measuring (network requests, data loading, image processing, etc.). Add `Owl.startOperation()` / `Owl.recordMetric()` to track durations and success rates. **Requires CLI first:** each metric slug must be defined on the server via `owlmetry metrics create` (use the `/owlmetry-cli` skill) before the SDK can emit events for it.
106
- 3. **Funnel tracking** — Identify user journeys (onboarding, checkout, key conversions). Add `Owl.track()` calls at each step to measure drop-off. **Requires CLI first:** the funnel definition (with steps and event filters) must be created via `owlmetry funnels create` (use the `/owlmetry-cli` skill) before tracking makes sense.
158
+ ## Network Request Tracking
107
159
 
108
- Wait for the user to choose before proceeding. For whichever option they pick, do a thorough audit of the entire codebase to find all relevant locations, then present a summary of proposed changes before making any edits.
160
+ The SDK automatically tracks all URLSession HTTP requests made via completion handler APIs. This is **enabled by default** no code needed beyond `Owl.configure()`. To disable:
161
+
162
+ ```swift
163
+ try Owl.configure(
164
+ endpoint: "https://ingest.owlmetry.com",
165
+ apiKey: "owl_client_...",
166
+ networkTrackingEnabled: false
167
+ )
168
+ ```
169
+
170
+ **What it captures automatically:**
171
+ - `_http_method` — GET, POST, etc.
172
+ - `_http_url` — sanitized URL (scheme + host + path only, query params stripped for privacy)
173
+ - `_http_status` — response status code
174
+ - `_http_duration_ms` — request duration in milliseconds
175
+ - `_http_response_size` — response body size in bytes
176
+ - `_http_error` — error description (failures only)
177
+
178
+ **Log levels:** `.info` for 2xx/3xx responses, `.warn` for 4xx/5xx, `.error` for network failures (no response).
179
+
180
+ **Safety:** The SDK's own requests to the OwlMetry ingest endpoint are automatically filtered out. Query parameters are stripped from URLs to prevent accidental logging of tokens or user IDs.
181
+
182
+ **Coverage:** Tracks requests made with `URLSession.dataTask(with:completionHandler:)` (both URL and URLRequest overloads). Delegate-based and async/await requests are not tracked in this version.
109
183
 
110
184
  ## Log Events
111
185
 
@@ -251,8 +325,8 @@ Owl.clearExperiments()
251
325
  When instrumenting a new app, follow this priority:
252
326
 
253
327
  **Always instrument (events — no CLI setup needed):**
328
+ - Screen views (`.owlScreen("ScreenName")` on every distinct screen)
254
329
  - App launch / cold start (`info` in `init()` or `didFinishLaunching`)
255
- - Key screen views (`info` with `screenName` in `onAppear`)
256
330
  - Authentication events (login, logout, signup)
257
331
  - Errors and failures (`error` in `catch` blocks, error handlers)
258
332
  - Core business actions (purchase, share, create, delete)
@@ -266,7 +340,7 @@ When instrumenting a new app, follow this priority:
266
340
  - A/B experiments when testing alternative UI or flows
267
341
 
268
342
  **Where to place calls:**
269
- - Screen views: `.onAppear` modifiers in SwiftUI, `viewDidAppear` in UIKit
343
+ - Screen views: `.owlScreen("Name")` on the outermost view of each screen (SwiftUI), `viewDidAppear` in UIKit
270
344
  - User actions: button action handlers, gesture callbacks
271
345
  - Errors: `catch` blocks, `Result.failure` handlers
272
346
  - Metrics: wrap the async operation between `startOperation()` and `complete()`/`fail()`
@@ -296,3 +370,10 @@ Every event automatically includes:
296
370
  - `_connection` — network type (wifi, cellular, ethernet, offline) via `NWPathMonitor`
297
371
  - `experiments` — current A/B experiment assignments
298
372
  - `environment` — specific runtime (ios, ipados, macos)
373
+
374
+ **Auto-emitted lifecycle events** (no manual calls needed):
375
+ - `sdk:session_started` — on `configure()`, includes `_launch_ms` (time from process start to configure)
376
+ - `sdk:app_foregrounded` — when app enters foreground
377
+ - `sdk:app_backgrounded` — when app enters background
378
+ - `sdk:screen_appeared` (info) / `sdk:screen_disappeared` (debug) — when using `.owlScreen()` modifier (disappear includes `_duration_ms`)
379
+ - `sdk:network_request` (info/warn/error) — URLSession HTTP requests with method, URL, status, duration (enabled by default, disable with `networkTrackingEnabled: false`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmetry/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.6",
4
4
  "description": "OwlMetry CLI — manage projects, apps, metrics, funnels, and events from the terminal. Includes AI skill files for agent-assisted development.",
5
5
  "type": "module",
6
6
  "license": "MIT",