Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/salty-cases-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@calycode/cli": minor
---

feat: Posthog integration and basic telemetry collection
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"clean": "turbo run clean",
"build:docs": "pnpm run build && tsx scripts/generate-caly-cli-docs.ts",
"xano": "pnpm --filter @calycode/cli run xano",
"prepublishOnly": "pnpm run build:packages",
"prepublishOnly": "pnpm run build",
"serve-registry": "npx serve registry --listen 3030"
},
"private": true,
Expand Down
7 changes: 5 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@
"homepage": "https://github.com/calycode/xano-tools/tree/main/packages/cli#readme",
"devDependencies": {
"@calycode/core": "workspace:*",
"@clack/prompts": "^0.11.0",
"@repo/types": "workspace:*",
"@repo/utils": "workspace:*",
"shx": "^0.4.0",
"@clack/prompts": "^0.11.0",
"commander": "^14.0.0",
"js-yaml": "^4.1.0",
"shx": "^0.4.0",
"tar": "^7.4.3"
},
"scripts": {
Expand All @@ -58,5 +58,8 @@
"build:chmod": "shx chmod +x dist/index.cjs",
"build": "pnpm build:js && pnpm build:chmod && pnpm link -g",
"xano": "node dist/index.cjs"
},
"dependencies": {
"posthog-node": "^5.9.2"
}
}
20 changes: 19 additions & 1 deletion packages/cli/src/commands/setup-instance.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { intro, text, password, confirm } from '@clack/prompts';
import { intro, text, password, confirm, log } from '@clack/prompts';
import { sanitizeInstanceName } from '@repo/utils';
import { ensureGitignore, withErrorHandler } from '../utils/index';

Expand Down Expand Up @@ -41,6 +41,24 @@ async function setupInstanceWizard(core) {
})) as boolean;
}

log.info(
`
Thank you for using @calycode/cli! 🚀

To help us improve, we collect anonymous telemetry data via our PostHog instance.
Here’s exactly what we track:
• Command names (e.g., generate-oas)
• Command duration
• Technical data:
– IP address (IPv6)
– Timestamp
– PostHog library version

By continuing to use @calycode/cli, you consent to this data collection.
We appreciate your support and commitment to making @calycode/cli better!
`
);

// Run the core setup logic
await core.setupInstance({
name: instanceName,
Expand Down
24 changes: 23 additions & 1 deletion packages/cli/src/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { registerRegistryAddCommand, registerRegistryScaffoldCommand } from './c
import { registerOasServeCommand, registerRegistryServeCommand } from './commands/serve';
import { registerBuildXanoscriptRepoCommand } from './commands/generate-xanoscript-repo';
import { Caly } from '@calycode/core';
import { InitializedPostHog } from './utils/posthog/init';
import { nodeConfigStorage } from './node-config-storage';

const commandStartTimes = new WeakMap<Command, number>();
Expand All @@ -23,11 +24,22 @@ const program = new Command();
const core = new Caly(nodeConfigStorage);

// Store start time on the command object
program.hook('preAction', (thisCommand) => {
program.hook('preAction', (thisCommand, actionCommand) => {
console.log(actionCommand.name());
commandStartTimes.set(thisCommand, Date.now());
// [ ] Add some system information to the capture
InitializedPostHog.capture({
distinctId: 'anonymous',
event: 'command_started',
properties: {
"command": actionCommand.name()
}
});
InitializedPostHog.shutdown();
});

program.hook('postAction', (thisCommand, actionCommand) => {
console.log(actionCommand.name());
const start = commandStartTimes.get(thisCommand);
if (!start) {
// Could happen if preAction failed, or if there's a bug
Expand All @@ -42,6 +54,16 @@ program.hook('postAction', (thisCommand, actionCommand) => {
: actionCommand.name();

console.log(`\n⏱️ Command "${commandPath}" completed in ${duration}s`);
// [ ] Add some outcome capture in a very anonymous manner
InitializedPostHog.capture({
distinctId: 'anonymous',
event: 'command_finished',
properties: {
"command": actionCommand.name(),
duration: duration
}
});
InitializedPostHog.shutdown();
});

program
Expand Down
7 changes: 7 additions & 0 deletions packages/cli/src/utils/posthog/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { PostHog } from 'posthog-node';

const InitializedPostHog = new PostHog('phc_MrSAUUthn4y0PWjbxVt9a9ys7TrQKMQhdYvErJFPvE3', {
host: 'https://eu.i.posthog.com',
});

export { InitializedPostHog };