Privacy-first telemetry and pairing tooling that measures workflow friction in AI-assisted engineering — metadata only, never source code, prompts, or file names. These are the collection surfaces for Ascenda; what the measurements do and do not establish is set out in What this measures.
Three surfaces, each one command. Pick the tools you actually use — they all report into the same paired installation, and any one of them works alone.
-
Open the Extensions pane — ⇧⌘X (macOS) or Ctrl+Shift+X (Windows/Linux).
-
Search Ascenda and click Install. (Publisher:
ascenda-one.) -
Open the Command Palette — ⇧⌘P / Ctrl+Shift+P — and run Ascenda: Connect App.
Same extension serves both editors; the host is detected at runtime. If you prefer the command line:
code --install-extension ascenda-one.ascenda # VS Code
cursor --install-extension ascenda-one.ascenda # CursorOn macOS those CLIs are not on PATH by default — run Shell Command: Install
'code' command in PATH from the Command Palette first, or just use the
Extensions pane above.
claude plugin marketplace add ascendaone-com/ai-engineer-tools
claude plugin install ascenda@ascenda-oneInstalls the work-signals skill, the lifecycle hooks, and the MCP server
together. From inside a session, use /plugin marketplace add … and
/plugin install … instead.
npx @ascenda-one/codex-hooks --helpThen register the hooks per ascenda-codex-hooks.
npx @ascenda-one/cursor-hooks setup
npx @ascenda-one/windsurf-hooks setup
npx @ascenda-one/gemini-hooks setupEach one pairs, installs its hook bundle and registers the hooks in the
agent's own config — no exports, nothing to hand-edit. status reports
whether everything is wired; uninstall reverses it.
Pairing. Every tool needs one pairing with the Ascenda app before it sends anything. Pair once in VS Code/Cursor (Ascenda: Connect App), and the CLI tools reuse that installation — see Pairing for what to carry across.
What it captures — real, running, and all this repo does. Named, observable events: context switches, AI prompt and correction loops, verification runs, tool-call density, context compaction, agent loop depth, after-hours activity. Counts and classifications, compared against your own trailing history.
The hypothesis under test. That friction of this kind rises measurably before a person consciously registers being overloaded, and that a personal baseline surfaces the rise earlier than self-report alone. That is the reason the collection layer exists — it is not a result the collection layer demonstrates.
What is not established. There is no peer-reviewed link between AI-tool operational metrics and any validated cognitive-load instrument, and our own calibration study has not been run. The demand signal is captured but is not yet an input to any state classifier. So: nothing here detects burnout, diagnoses a state, or predicts one. It counts things that happened and shows them against your own history.
Stating that plainly is deliberate. Implying the inference already works is the specific failure this design exists to avoid, and it would be a strange thing to fake in a repository whose whole argument is that you can read the source.
Wire contract: Tool Pairing API Reference.
| Package | Published as | What it does |
|---|---|---|
| ascenda-vscode-extension-telemetry |
ascenda-one.ascenda (VS Code Marketplace + Open VSX) |
IDE telemetry for VS Code and Cursor — one extension, runtime host detection; editor activity, terminal classification, sessions |
| ascenda-agent-skills |
ascenda@ascenda-one (Claude Code plugin) |
The Claude Code plugin — bundles the work-signals skill, hooks, and MCP server into one install. Also holds the Cursor rule and the emission criteria both share |
| ascenda-claude-code-hooks |
@ascenda-one/claude-code-hooks (npm) |
Claude Code agent hooks — prompts, tool calls, compaction, agent loops |
| ascenda-codex-hooks |
@ascenda-one/codex-hooks (npm) |
OpenAI Codex lifecycle hooks — same agent signals as Claude hooks, via Codex's hooks.json |
| ascenda-cursor-hooks |
@ascenda-one/cursor-hooks (npm) |
Cursor agent hooks — same signals via Cursor's hooks.json, with setup/status/uninstall
|
| ascenda-windsurf-hooks |
@ascenda-one/windsurf-hooks (npm) |
Windsurf Cascade hooks — partial upstream coverage, documented rather than faked |
| ascenda-gemini-hooks |
@ascenda-one/gemini-hooks (npm) |
Gemini CLI hooks — per-inference hooks deliberately left unregistered |
| ascenda-agent-mcp |
@ascenda-one/agent-mcp (npm) |
MCP server exposing ascenda_emit_work_signal — the one interface for agent-observed semantic patterns the deterministic hooks cannot see |
| ascenda-github-collector |
@ascenda-one/github-collector (npm) |
Collaboration signals from a code forge — your own review load and PR activity, never anyone else's |
| ascenda-pairing-sim | not published | Console app that simulates the mobile app for pairing tests (confirm / list / revoke / e2e) |
| ascenda-dev-server | not published | Local mock of the /v1 pairing + ingest contract — run any tool with no backend, phone, or DevAuth. Dev-only; binds to 127.0.0.1
|
The repo is an npm workspace. The installable tools above are thin shells over shared packages:
| Package | Role |
|---|---|
| packages/tool-contract | Canonical DTOs, event catalog, and constants — mirrors TOOL_PAIRING_API_REFERENCE.md; declared once, consumed everywhere |
| packages/tool-kit | vscode-free shared runtime: command classifier, buckets, after-hours calculation, token file store, /v1 HTTP client |
| packages/ide-extension-core | The single extension implementation; host identity (VS Code vs Cursor) is detected at runtime |
Pairing is what links a tool installation to your Ascenda account. It happens once per machine, and every tool on that machine reuses it.
-
In VS Code or Cursor, run Ascenda: Connect App (⇧⌘P / Ctrl+Shift+P). The editor shows a QR code and a six-digit code, good for a few minutes:
-
Confirm in the Ascenda app under Connections → Ingest telemetry — scan the QR, or paste the code into the pairing field. On Dev backends without a phone, ascenda-pairing-sim stands in for the app.
-
Run Ascenda: Show Status and note the
toolInstallationId.
The pairing code carries no personal data — it links this editor installation to your account so signals can be routed to your device, and nothing more. The panel states the same thing where you can see it at the time.
Each CLI agent sets itself up with one command — it pairs (printing a 6-digit code to confirm in the app), installs the hook bundle, and registers the hooks:
npx -y @ascenda-one/claude-code-hooks setup # or codex-, cursor-, gemini-, windsurf-hooksNothing to add to a shell profile: each agent's pairing lands under its own key
in ~/.ascenda/credentials.json, which is what lets several agents run on one
machine without one inheriting another's identity. (ASCENDA_TOOL_INSTALLATION_ID
still wins where it is set, so export it only if you mean it to cover every
agent on the machine.) The editor extension's own pairing cannot be reused here
— its token lives in the editor's private secret storage, by design — so the
CLI tools hold their own installation, paired against the same account.
You do not need this to use the tools — everything above installs prebuilt. It is here because "verify what you're running" is a reasonable thing to want from a telemetry tool, and this repo is Apache-2.0 precisely so you can.
npm install
npm run build # shared packages first, then tools
npm run verify # DRY guard rail (scripts/check-dry.sh) + full build + testsThe extension is bundled with esbuild at package time (npm run package), so
the shared packages are inlined; per-folder F5 debugging works after a root
build. Per-package development notes live in each package's own README.
The registry paths above are the normal ones. This section is the fallback for machines that cannot reach the Marketplace or npm, and for anyone who wants to verify a checksum before running anything.
Every tagged release attaches each shipped artifact plus a manifest.json. The
manifest is the only supported way to discover artifacts — resolve downloads
through it rather than from main. Requires Node 20+.
The newest release is always at a stable latest URL:
BASE=https://github.com/ascendaone-com/ai-engineer-tools/releases/latest/download
curl -fsSLO "$BASE/manifest.json"
cat manifest.json # { version, minNode, artifacts: [{ name, url, sha256 }] }1. Extension (VS Code / Cursor). One VSIX for both hosts. Download the version named in the manifest and install it headlessly — this works with no marketplace dependency:
curl -fsSLO "$BASE/ascenda-<version>.vsix"
code --install-extension ./ascenda-<version>.vsix # VS Code
cursor --install-extension ./ascenda-<version>.vsix # Cursor — same fileThe extension is on both the VS Code Marketplace and Open VSX, so installing from there is preferred — you get auto-updates. The VSIX is the universal fallback, not the recommended path.
2. Hook CLIs (Claude Code / Codex / Cursor / Windsurf / Gemini CLI). Published to npm, so the shortest path is:
npx @ascenda-one/codex-hooks --help
npx @ascenda-one/claude-code-hooks --helpThey are also attached to every release as self-contained single-file ESM
bundles — no npm install, no dependencies — for machines where you would
rather not go through npm at all:
mkdir -p ~/.ascenda/bin
curl -fsSL "$BASE/ascenda-codex-hooks.mjs" -o ~/.ascenda/bin/ascenda-codex-hook
chmod +x ~/.ascenda/bin/ascenda-codex-hook
export PATH="$HOME/.ascenda/bin:$PATH" # add to your shell rc~/.ascenda/bin is the install target rather than npm i -g: no sudo, and no
npm-global permission failures on locked-down machines.
3. Verify before you run. Check the checksum against the manifest, and optionally the build provenance:
shasum -a 256 ascenda-codex-hooks.mjs # must match sha256 in manifest.json
gh attestation verify ascenda-codex-hooks.mjs --repo ascendaone-com/ai-engineer-toolsReleases are built only by .github/workflows/release.yml,
gated on npm run verify, and signed with keyless Sigstore build provenance.
Run everything with no backend, phone, or DevAuth: see
TESTING.md — ./scripts/dev-quickstart.sh gets events flowing
against a local mock server (ascenda-dev-server) in
about two minutes. This is the fastest way to see the whole pipe work end to
end without touching a real backend.
Per-package development notes:
| Tool | Guide |
|---|---|
| VS Code / Cursor | ascenda-vscode-extension-telemetry |
| Claude Code | ascenda-claude-code-hooks · ascenda-agent-skills |
| Codex | ascenda-codex-hooks |
| Cursor agent | ascenda-cursor-hooks |
| Windsurf | ascenda-windsurf-hooks |
| Gemini CLI | ascenda-gemini-hooks |
| Semantic signals (MCP) | ascenda-agent-mcp |
| Pairing sim (app stand-in) | ascenda-pairing-sim |
To pair against a Dev backend without a phone:
ascenda-pairing-sim e2e --tool-type cursor_mcpPoint any tool at a non-default backend with ASCENDA_API_BASE_URL (CLIs) or
the ascenda.apiBaseUrl setting (extension) — http://localhost:5002 for a
local backend, or the Azure Dev host. Never commit tokens.
Verified on Azure Dev: ingest, tool-scoped renew, list, and revoke
(post-revoke ingest returns 401).
Workspace identifiers are hashed with a random salt generated on first run and stored only at ~/.ascenda/salt. It is never sent, so the hashes cannot be reversed to folder or repository names by anyone holding the telemetry. Deleting the file re-anonymises the machine.
Metadata-only by default. Not a medical device — it measures workload
patterns for self-awareness, not diagnosis or treatment, and makes no clinical
claim. Consent is scoped and separately revocable: ide_telemetry for editor
and agent signals, workflow_telemetry for collaboration signals, and
semantic_work_signals for the agent-observed patterns — granting one does not
grant the others.
What the metadata-only guarantee covers in practice, per surface, is listed in each package's own README under Privacy defaults. Where a guarantee is enforced by schema rather than convention — the semantic signal tool rejects free text outright — that is stated there too.



