@owlmetry/cli 0.1.6 → 0.1.7

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
@@ -7183,7 +7183,7 @@ var switchCommand = new Command("switch").description("Switch active team profil
7183
7183
  });
7184
7184
 
7185
7185
  // src/index.ts
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(
7186
+ var program2 = new Command().name("owlmetry").version("0.1.7").description("OwlMetry CLI \u2014 query metrics and manage your apps from the terminal").addOption(
7187
7187
  new Option("--format <format>", "Output format").choices(["table", "json", "log"]).default("table")
7188
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");
7189
7189
  program2.addCommand(authCommand);
@@ -1,10 +1,12 @@
1
1
  ---
2
2
  name: owlmetry-cli
3
- version: 0.1.6
3
+ version: 0.1.7
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
7
7
  analytics, or when another OwlMetry skill needs CLI setup as a prerequisite.
8
+ IMPORTANT: You MUST load this skill before running ANY `owlmetry` CLI
9
+ command. The CLI has non-obvious subcommand syntax and flags — do not guess.
8
10
  allowed-tools: Bash
9
11
  ---
10
12
 
@@ -14,11 +16,13 @@ OwlMetry is a self-hosted analytics platform for mobile and backend apps. It cap
14
16
 
15
17
  The **CLI** is the management and query tool — it does not ingest events. You use it to create projects and apps, define metrics and funnels, query event data, and view analytics. SDKs handle event ingestion using client keys (`owl_client_...`). The CLI uses agent keys (`owl_agent_...`) for reading data and managing resources.
16
18
 
19
+ > **Do not guess CLI syntax.** The `owlmetry` command has specific subcommand patterns (e.g., `owlmetry apps` not `owlmetry apps list`, flags like `--format json` not `--message`). Always reference the command documentation in this skill file before running a command. If you haven't loaded this skill yet, load it first.
20
+
17
21
  ## Version Check
18
22
 
19
23
  Run these checks silently. Only inform the user if updates are available.
20
24
 
21
- 1. **Skill version**: `curl -sf https://raw.githubusercontent.com/Jasonvdb/owlmetry/main/skills/owlmetry-cli/SKILL.md | head -5` — compare the `version:` field to `0.1.0`. If newer, ask the user if they want to update the local skill file.
25
+ 1. **Skill version**: `curl -sf https://raw.githubusercontent.com/Jasonvdb/owlmetry/main/skills/owlmetry-cli/SKILL.md | head -5` — compare the remote `version:` field to this file's `version:` frontmatter above. If the remote version is newer, ask the user if they want to update the local skill file.
22
26
  2. **CLI version** (if installed): compare `owlmetry --version` to `npm view @owlmetry/cli version 2>/dev/null`. If a newer version exists, offer `npm install -g @owlmetry/cli@latest`.
23
27
 
24
28
  If everything is current or the remote is unreachable, continue silently.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: owlmetry-node
3
- version: 0.1.6
3
+ version: 0.1.7
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
@@ -18,7 +18,7 @@ The SDK has zero runtime dependencies. All calls are non-blocking — events are
18
18
 
19
19
  Run these checks silently. Only inform the user if updates are available.
20
20
 
21
- 1. **Skill version**: `curl -sf https://raw.githubusercontent.com/Jasonvdb/owlmetry/main/skills/owlmetry-node/SKILL.md | head -5` — compare the `version:` field to `0.1.0`. If newer, ask the user if they want to update.
21
+ 1. **Skill version**: `curl -sf https://raw.githubusercontent.com/Jasonvdb/owlmetry/main/skills/owlmetry-node/SKILL.md | head -5` — compare the remote `version:` field to this file's `version:` frontmatter above. If the remote version is newer, ask the user if they want to update.
22
22
  2. **SDK version**: `npm ls @owlmetry/node --json 2>/dev/null` for current version, `npm view @owlmetry/node version 2>/dev/null` for latest. If newer, offer `npm install @owlmetry/node@latest`.
23
23
 
24
24
  ## Prerequisite
@@ -27,6 +27,8 @@ You need an **ingest endpoint** and a **client key** (`owl_client_...`) for a ba
27
27
 
28
28
  If the user doesn't have these yet, follow the `/owlmetry-cli` skill first — it handles sign-up, project creation, and app creation. The ingest endpoint is saved to `~/.owlmetry/config.json` (`ingest_endpoint` field) and the client key is returned when creating an app.
29
29
 
30
+ > **Any time you need to run an `owlmetry` CLI command** (querying events, creating metrics/funnels, listing apps, etc.), **load the `/owlmetry-cli` skill first**. Do not guess CLI syntax — it has non-obvious subcommand patterns and flags.
31
+
30
32
  ## Install
31
33
 
32
34
  ```bash
@@ -62,13 +64,24 @@ Owl.configure({
62
64
  **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
65
 
64
66
  ```typescript
65
- // Before:
66
- export const myFunction = onCall(async (request) => { ... });
67
-
68
- // After:
69
- export const myFunction = onCall(Owl.wrapHandler(async (request) => { ... }));
67
+ // AWS Lambda / generic serverless:
68
+ export const handler = Owl.wrapHandler(async (event, context) => { ... });
69
+
70
+ // Firebase Cloud Functions v2:
71
+ // IMPORTANT: Explicitly type the request parameter TypeScript cannot infer
72
+ // the CallableRequest type through wrapHandler's generics.
73
+ import { onCall, type CallableRequest } from 'firebase-functions/v2/https';
74
+
75
+ export const myFunction = onCall(
76
+ Owl.wrapHandler(async (request: CallableRequest) => {
77
+ const { data, auth } = request; // works — TypeScript knows the type
78
+ // ...
79
+ })
80
+ );
70
81
  ```
71
82
 
83
+ **TypeScript note:** `wrapHandler()` uses generic rest parameters (`<TArgs extends unknown[]>`), which means TypeScript sometimes infers handler parameters as `unknown` when the outer function (like Firebase's `onCall`) expects a specific callback type. If you see type errors like `Property 'data' does not exist on type 'unknown'`, explicitly annotate the handler's parameters (e.g., `request: CallableRequest`, `event: APIGatewayEvent`).
84
+
72
85
  ## Next Steps — Codebase Instrumentation
73
86
 
74
87
  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:
@@ -97,16 +110,21 @@ Events are the core data unit. Use the four log levels to capture different kind
97
110
 
98
111
  - **`info`** — normal operations: server started, request handled, job completed, user action processed.
99
112
  - **`debug`** — verbose detail for development: cache lookups, query plans, config loading, intermediate state.
100
- - **`warn`** — recoverable problems: slow queries, rate limits approaching, fallback paths, deprecated API usage.
101
- - **`error`** — failures: database connection errors, external API failures, unhandled rejections, missing resources.
113
+ - **`warn`** — something didn't go as expected but the process can continue: failed validation, precondition checks that fail, slow queries, rate limits approaching, fallback paths, deprecated API usage, missing optional config.
114
+ - **`error`** — a caught exception or hard failure inside a `try`/`catch`: database connection errors, external API timeouts, unhandled rejections, file system errors. Reserve for actual thrown errors, not for anticipated validation outcomes.
102
115
 
103
116
  Choose **message strings** that are specific and searchable. Prefer `"Payment processing failed"` over `"error occurred"`. Use attributes for structured data you'll filter on later.
104
117
 
105
118
  ```typescript
106
119
  Owl.info('Server started', { port: 4000 });
107
120
  Owl.debug('Cache miss', { key: 'user:123' });
108
- Owl.warn('Slow query', { duration_ms: 2500, table: 'events' });
109
- Owl.error('Database connection failed', { host: 'db.example.com' });
121
+ Owl.warn('Invalid request payload', { field: 'email', reason: 'missing' });
122
+
123
+ try {
124
+ await db.connect();
125
+ } catch (err) {
126
+ Owl.error('Database connection failed', { host: 'db.example.com', error: String(err) });
127
+ }
110
128
  ```
111
129
 
112
130
  All methods: `Owl.info/debug/warn/error(message: string, attrs?: Record<string, unknown>)`.
@@ -118,7 +136,12 @@ Source module (file:line) is auto-captured from the call stack.
118
136
  Owl.info('Request handled', { method: 'POST', path: '/api/orders', status: 201 });
119
137
  Owl.info('Background job completed', { job: 'send-emails', processed: 150 });
120
138
  Owl.warn('Rate limit approaching', { current: 95, limit: 100, client_id: 'abc' });
121
- Owl.error('External API timeout', { service: 'stripe', endpoint: '/charges', timeout_ms: 10000 });
139
+
140
+ try {
141
+ await stripe.charges.create(params);
142
+ } catch (err) {
143
+ Owl.error('Stripe charge failed', { endpoint: '/charges', error: String(err) });
144
+ }
122
145
  ```
123
146
 
124
147
  ## Per-Request User Scoping
@@ -339,7 +362,8 @@ When instrumenting a backend service, follow this priority:
339
362
  **Always instrument (events — no CLI setup needed):**
340
363
  - Server startup and shutdown (`info`)
341
364
  - Request handling: key route hits, responses sent (`info` with method/path/status)
342
- - Errors and failures: catch blocks, unhandled rejections, external API failures (`error`)
365
+ - Caught exceptions: catch blocks, unhandled rejections, external API failures (`error`)
366
+ - Validation failures and pre-checks: bad input, missing optional config, rate limits (`warn`)
343
367
  - Authentication events: login, logout, token refresh (`info`)
344
368
  - Core business actions: order placed, payment processed, email sent (`info`)
345
369
  - Background jobs: started, completed, failed (`info`/`error`)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: owlmetry-swift
3
- version: 0.1.6
3
+ version: 0.1.7
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
@@ -18,7 +18,7 @@ The SDK is a static `Owl` enum with no external dependencies. All calls are non-
18
18
 
19
19
  Run these checks silently. Only inform the user if updates are available.
20
20
 
21
- 1. **Skill version**: `curl -sf https://raw.githubusercontent.com/Jasonvdb/owlmetry/main/skills/owlmetry-swift/SKILL.md | head -5` — compare the `version:` field to `0.1.0`. If newer, ask the user if they want to update.
21
+ 1. **Skill version**: `curl -sf https://raw.githubusercontent.com/Jasonvdb/owlmetry/main/skills/owlmetry-swift/SKILL.md | head -5` — compare the remote `version:` field to this file's `version:` frontmatter above. If the remote version is newer, ask the user if they want to update.
22
22
  2. **SDK version**: Read `Package.resolved` for the current resolved revision, then compare against `curl -sf https://api.github.com/repos/Jasonvdb/owlmetry/releases/latest | jq -r .tag_name`. If newer, inform the user.
23
23
 
24
24
  ## Prerequisite
@@ -27,9 +27,16 @@ You need an **ingest endpoint** and a **client key** (`owl_client_...`) for an A
27
27
 
28
28
  If the user doesn't have these yet, follow the `/owlmetry-cli` skill first — it handles sign-up, project creation, and app creation. The ingest endpoint is saved to `~/.owlmetry/config.json` (`ingest_endpoint` field) and the client key is returned when creating an app.
29
29
 
30
+ > **Any time you need to run an `owlmetry` CLI command** (querying events, creating metrics/funnels, listing apps, etc.), **load the `/owlmetry-cli` skill first**. Do not guess CLI syntax — it has non-obvious subcommand patterns and flags.
31
+
30
32
  ## Add Swift Package
31
33
 
32
- **Swift Package Manager (Package.swift):**
34
+ **Minimum platforms:** iOS 16.0, macOS 13.0. Zero external dependencies.
35
+
36
+ ### Option A — Package.swift projects
37
+
38
+ If the project has a `Package.swift`, add the dependency there:
39
+
33
40
  ```swift
34
41
  dependencies: [
35
42
  .package(url: "https://github.com/Jasonvdb/owlmetry.git", branch: "main")
@@ -42,29 +49,31 @@ Add to your target:
42
49
  ])
43
50
  ```
44
51
 
45
- **Xcode:** File > Add Package Dependencies > enter `https://github.com/Jasonvdb/owlmetry.git`, select branch `main`, add `OwlMetry` to your target.
52
+ Then run `swift package resolve` to fetch the dependency.
46
53
 
47
- **Minimum platforms:** iOS 16.0, macOS 13.0. Zero external dependencies.
54
+ ### Option B Xcode projects (.xcodeproj)
48
55
 
49
- ## Verify Package Integration
56
+ For `.xcodeproj`-based projects with no `Package.swift`, add the OwlMetry Swift package by editing `<Project>.xcodeproj/project.pbxproj` directly to add a remote Swift package reference for `https://github.com/Jasonvdb/owlmetry.git` (branch: `main`, product: `OwlMetry`). Do not ask the user to add it manually in Xcode.
50
57
 
51
- After adding the package, build the project to verify the dependency resolves and `import OwlMetry` compiles. Do not proceed with configuration until the build succeeds.
58
+ ### Option C Ask the user (last resort)
52
59
 
53
- If the build fails with a "No such module 'OwlMetry'" error, ask the user to add the package manually in Xcode:
60
+ If pbxproj editing fails or the project structure is too complex, ask the user to add the package in Xcode:
54
61
 
55
- 1. Open the `.xcodeproj` or `.xcworkspace` in Xcode
56
- 2. Select the project in the navigator (blue icon at the top)
57
- 3. Select the app target under "Targets"
58
- 4. Go to the "General" tab
59
- 5. Scroll to "Frameworks, Libraries, and Embedded Content"
60
- 6. Click the **+** button
61
- 7. Click "Add Other…" > "Add Package Dependency…"
62
- 8. Enter the URL: `https://github.com/Jasonvdb/owlmetry.git`
63
- 9. Set "Dependency Rule" to **Branch** → `main`
64
- 10. Click "Add Package"
65
- 11. Select the **OwlMetry** library and click "Add Package"
62
+ 1. File > Add Package Dependencies
63
+ 2. Enter URL: `https://github.com/Jasonvdb/owlmetry.git`
64
+ 3. Set rule to **Branch** > `main`
65
+ 4. Add **OwlMetry** to the app target
66
+
67
+ ## Verify Package Integration
66
68
 
67
- Once the user confirms the package is added, retry the build to verify, then proceed with configuration.
69
+ After adding the package, resolve dependencies and build:
70
+
71
+ ```bash
72
+ xcodebuild -resolvePackageDependencies -project <path>.xcodeproj -quiet
73
+ xcodebuild -project <path>.xcodeproj -scheme <SchemeName> -destination 'platform=iOS Simulator,name=iPhone 16' build -quiet
74
+ ```
75
+
76
+ If the build succeeds, proceed with configuration. The "No such module 'OwlMetry'" warning in editors (SourceKit) is expected and resolves during a real `xcodebuild`.
68
77
 
69
78
  ## Configure
70
79
 
@@ -187,16 +196,26 @@ Events are the core unit of data in OwlMetry. Use the four log levels to capture
187
196
 
188
197
  - **`info`** — normal operations worth recording: screen views, user actions, feature usage, successful completions. This is your default level.
189
198
  - **`debug`** — verbose detail useful only during development: cache hits, state transitions, intermediate values. These are filtered out in production data mode.
190
- - **`warn`** — something unexpected that the app recovered from: slow responses, fallback paths taken, retries needed.
191
- - **`error`** — something failed: network errors, parse failures, missing data, caught exceptions.
199
+ - **`warn`** — something didn't go as expected but the app can continue: failed validation, precondition checks that fail, slow responses, fallback paths taken, deprecated API usage, missing optional data.
200
+ - **`error`** — a caught exception or hard failure inside a `do`/`catch` block: network errors, JSON decode failures, file I/O errors, keychain access failures. Reserve for actual thrown errors, not for anticipated validation outcomes.
192
201
 
193
202
  Choose **message strings** that are specific and searchable. Prefer `"Failed to load profile image"` over `"error"`. Use `screenName` to tie events to where they happened in the UI. Use `customAttributes` for structured data you'll want to filter or search on later.
194
203
 
195
204
  ```swift
205
+ // In a screen context — pass screenName to tie the event to the screen
196
206
  Owl.info("User opened settings", screenName: "SettingsView")
197
207
  Owl.debug("Cache hit", screenName: "HomeView", customAttributes: ["key": "user_prefs"])
198
- Owl.warn("Slow network response", customAttributes: ["latency_ms": "1200"])
199
- Owl.error("Failed to load profile", screenName: "ProfileView")
208
+ Owl.warn("Invalid email format", screenName: "SignUpView", customAttributes: ["input": email])
209
+
210
+ do {
211
+ let profile = try await api.loadProfile(id: userId)
212
+ } catch {
213
+ Owl.error("Failed to load profile", screenName: "ProfileView", customAttributes: ["error": "\(error)"])
214
+ }
215
+
216
+ // Outside a screen context — omit screenName entirely
217
+ Owl.info("Background sync completed", customAttributes: ["items": "\(count)"])
218
+ Owl.error("Keychain write failed", customAttributes: ["error": "\(error)"])
200
219
  ```
201
220
 
202
221
  All logging methods share the same signature:
@@ -204,6 +223,8 @@ All logging methods share the same signature:
204
223
  Owl.info(_ message: String, screenName: String? = nil, customAttributes: [String: String]? = nil)
205
224
  ```
206
225
 
226
+ **`screenName` is optional.** Only pass it when the event originates from a specific screen in the UI (e.g., a button tap handler inside a view). **Do NOT pass `screenName`** when logging from utility functions, services, managers, network layers, background tasks, or anywhere that isn't directly tied to a visible screen. Passing a fabricated or guessed screen name is worse than omitting it — it pollutes screen-level analytics.
227
+
207
228
  Source file, function, and line are auto-captured.
208
229
 
209
230
  **Avoid logging PII** (emails, phone numbers, passwords) or high-frequency events (every frame, every scroll position). Focus on actions and outcomes.
@@ -328,7 +349,8 @@ When instrumenting a new app, follow this priority:
328
349
  - Screen views (`.owlScreen("ScreenName")` on every distinct screen)
329
350
  - App launch / cold start (`info` in `init()` or `didFinishLaunching`)
330
351
  - Authentication events (login, logout, signup)
331
- - Errors and failures (`error` in `catch` blocks, error handlers)
352
+ - Caught exceptions (`error` in `catch` blocks, error handlers)
353
+ - Validation failures and pre-checks (`warn` for bad input, missing optional data, fallback paths)
332
354
  - Core business actions (purchase, share, create, delete)
333
355
 
334
356
  **Instrument when relevant (metrics — requires CLI `owlmetry metrics create` first):**
@@ -341,8 +363,9 @@ When instrumenting a new app, follow this priority:
341
363
 
342
364
  **Where to place calls:**
343
365
  - Screen views: `.owlScreen("Name")` on the outermost view of each screen (SwiftUI), `viewDidAppear` in UIKit
344
- - User actions: button action handlers, gesture callbacks
345
- - Errors: `catch` blocks, `Result.failure` handlers
366
+ - User actions: button action handlers, gesture callbacks — pass `screenName` since you know which screen the user is on
367
+ - Errors: `catch` blocks, `Result.failure` handlers — pass `screenName` only if the error is caught inside a view; omit it if caught in a service, manager, or utility
368
+ - Services, utilities, background tasks: log freely but **never pass `screenName`** — these are not screen-bound
346
369
  - Metrics: wrap the async operation between `startOperation()` and `complete()`/`fail()`
347
370
 
348
371
  **What NOT to instrument:**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmetry/cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
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",