Notes for anyone (human or agent) making changes to the @insforge/cli repo.
Read this before touching source files.
The codebase has well-established conventions — stay consistent with them rather than inventing new structures.
- Command layout. Every command lives under
src/commands/<group>/<cmd>.tsand exports aregisterXxxCommand(parent: Command)function that attaches itself to the parent Commander instance. The top-level registration happens insrc/index.ts. New commands must follow the same registration pattern. - API clients. Platform API calls go through
src/lib/api/platform.ts(platformFetch), OSS/self-hosted calls throughsrc/lib/api/oss.ts(ossFetch). Do not callfetchdirectly from command files — add a typed wrapper to the appropriate client module. - Config. Use helpers from
src/lib/config.ts(getProjectConfig,getPlatformApiUrl, etc.). Never read config files directly. - Errors. Throw
CLIError/AuthError/ProjectNotLinkedErrorfromsrc/lib/errors.ts. Always let the top-levelhandleError(err, json)in the command action render the error — don't print errors yourself. - Output. Use
outputJson/outputTable/outputSuccessfromsrc/lib/output.ts. Respect the--jsonflag viagetRootOpts(cmd). - Interactive prompts. Use
@clack/prompts(already imported in most command files). Never prompt when--jsonis set. - Imports. TypeScript ESM — imports must use
.jsextensions (e.g.from '../lib/config.js'), even for.tssource files.
When in doubt, find the closest existing command and copy its structure.
The CLI uses PostHog (wired up in src/lib/analytics.ts) to track which
commands and features are actually being used. This is the single source of
truth for product telemetry — do not add alternative analytics systems.
- Entry point. Import
captureEvent(or a typed helper liketrackDiagnose) fromsrc/lib/analytics.ts. Add a new helper there if several commands will share an event shape. - Distinct ID. Use
project_id(ororg_idwhere a project isn't yet linked, e.g. increate) as the distinct ID so events can be grouped per project/org. - Event names. Use the
cli_<feature>_<action>convention (e.g.cli_diagnose_invoked). Keep event names stable — renaming breaks dashboards. - Properties. Include only non-sensitive metadata:
project_id,project_name,org_id,region,subcommand, feature flags. Never send SQL, file contents, credentials, or user-entered free text. - Flush. Always call
await shutdownAnalytics()in afinallyblock so events are flushed before the process exits. PostHog Node SDK batches by default and will drop events on a hard exit. - Build-time key.
POSTHOG_API_KEYis injected at build time bytsup.config.tsviadefine. Local builds without the env var become a no-op automatically — the CLI itself stays functional.
Do not use reportCliUsage for new commands — that legacy OSS telemetry
path has been removed from create, link, and docs. PostHog is the path
going forward.
The CLI auto-installs agent skills via installSkills() in
src/lib/skills.ts. Those skills live in a separate repo
(InsForge/agent-skills) and teach AI coding agents how to use the InsForge
SDK and CLI.
When you add, rename, or change the behavior of a user-facing CLI command,
you almost certainly need to update the insforge-cli skill in the
agent-skills repo as well — otherwise the skill will be stale and agents
will generate wrong commands.
Checklist when changing a command:
- Does the
insforge-cliskill document this command? If yes, open a PR inInsForge/agent-skillsto update it in the same change set. - Did flags, defaults, or output shape change? Update the skill examples.
- Did a command get renamed or removed? Remove or rename in the skill.
- Did you add a new command? Decide whether agents should know about it and add it to the skill if so.
Mention the skill repo update in the CLI PR description so reviewers can cross-reference both PRs.
Releases are fully automated via GitHub Actions
(.github/workflows/publish.yml).
The CLI is published to npm as @insforge/cli whenever a version tag is
pushed.
Steps to ship a release:
- Bump the version in
package.json(e.g.0.1.41→0.1.42) on your feature branch or onmain. Follow semver — patch for fixes, minor for additive features, major for breaking changes. - Commit the bump with a message like
chore: bump version to X.Y.Z. - Merge to
mainvia PR as usual. - Create and push a tag matching the version on
main:git checkout main && git pull git tag vX.Y.Z git push origin vX.Y.Z - The
publishworkflow triggers on the tag push and:- Runs
npm run buildwithPOSTHOG_API_KEYinjected from repo secrets. - Runs
npm publish --access publicwithNPM_TOKENfrom repo secrets.
- Runs
- Verify the new version appears on
npmjs.com/package/@insforge/cli
and that
npx @insforge/cli@latest --versionreturns the expected version.
Do not publish manually from a local machine — that bypasses the CI build (and therefore the PostHog key injection) and leads to analytics being silently disabled in published artifacts.
If a release goes wrong, deprecate the bad version with npm deprecate rather
than unpublishing — unpublishing breaks downstream users who already installed
that version.