GitClear offers the means for teams using Claude Code to get per-line granularity on which changes were LLM-authored, vs. human-authored. Our LLM calls this a "killer feature" because of the gap that currently exists between the "Claude Code Usage API" (which offers fairly limited stats as of Q2 2026) and what developers, CTOs, and VPs of Engineering have requested from GitClear.


The rest of this help page describes how to enable granular outcome tracking for teams using any version of Claude Code.


linkGitClear Telemetry for Claude Code: System Administrator Deployment Guide

This guide describes how to automatically retrieve per-line Claude Code data, for ultra-granular evaluation of which lines are AI-generated vs human-generated. Unlike connecting via Claude Code API, this method works with all Claude.ai subscription levels.


linkGoal

Capture file edits made by any LLM model via Claude Code, using a telemetry hook. Use it to improve Diff Delta evaluation, while enabling per-line authored_by_llm model tagging. The latter facilitates GitClear being able to provide detailed AI ROI stats for "defects," "teammate review time," "durable rate of code change," and similar metrics.


Developers do not need to do anything. The hook is only shown during initial startup. The after adjusting your managed settings to include the telemetry hook, there is a one-time confirmation for each developer who starts Claude Code:




As with all GitClear features, the hook is bound by GitClear's Developer-Friendly Analytics, so the data collected by this script can not be used to unfairly target individual developers.


linkPrerequisites

A Claude Team or Claude Enterprise subscription

Admin role in your Claude organization

A GitClear organization account with an API token

The claude-telemetry.mjs hook script (contact hello@gitclear.com, who can deliver the file from Amplenote)



linkChoose Your Deployment Method

Claude Code supports four managed-settings delivery mechanisms. Pick the one that matches your infrastructure. All four produce the same result: hooks that developers cannot override.

Method

Best for

Developer action required

Tamper resistance

A. Server-Managed (Admin Console)

Orgs without MDM, fastest setup

None

Client-side only

B. macOS MDM (Jamf / Kandji / Intune)

Mac-heavy shops with MDM

None

OS-level enforcement

C. Windows GPO / Intune

Windows shops

None

Registry-level enforcement

D. File-Based (Ansible / Chef / Puppet)

Linux fleets, mixed OS without MDM

None

File-permission enforcement

Precedence rule: If you use more than one method, the first source that delivers a non-empty configuration wins. They do not merge across tiers. Priority: Server-Managed > MDM/OS-level > File-based.


linkStep 1: Distribute the Hook Script

Before configuring managed settings, the hook script must exist on every developer machine at a consistent path. The managed settings JSON will reference this path.


Recommended install path:

OS

Path

macOS

/opt/gitclear/claude-telemetry.mjs

Linux

/opt/gitclear/claude-telemetry.mjs

Windows

C:\Program Files\GitClear\claude-telemetry.mjs


linkOption 1: Distribute via your config management tool

Ansible example:

- name: Deploy GitClear telemetry hook
hosts: developer_workstations
become: yes
tasks:
- name: Create GitClear directory
file:
path: /opt/gitclear
state: directory
mode: '0755'
 
- name: Copy telemetry hook
copy:
src: files/claude-telemetry.mjs
dest: /opt/gitclear/claude-telemetry.mjs
mode: '0755'
 

Chef example:

directory '/opt/gitclear' do
mode '0755'
end
 
cookbook_file '/opt/gitclear/claude-telemetry.mjs' do
source 'claude-telemetry.mjs'
mode '0755'
end
 


linkOption 2: Distribute via MDM (macOS)

Package the script into a .pkg installer and deploy via your MDM's software distribution. Tools like munkipkg or Jamf Composer can create the package.

# Create a flat package
mkdir -p /tmp/gitclear-pkg/opt/gitclear
cp gitclear-telemetry.mjs /tmp/gitclear-pkg/opt/gitclear/
pkgbuild --root /tmp/gitclear-pkg \
--identifier com.claude.telemetry \
--version 1.0 \
claude-telemetry.pkg
 

Upload the .pkg to your MDM and assign to your developer scope/group.


linkOption 3: Distribute via GPO / Intune (Windows)

Package as an .intunewin file or MSI, or use a PowerShell script deployment:

# Intune remediation script or GPO logon script
$dest = "C:\Program Files\GitClear"
if (-not (Test-Path $dest)) { New-Item -Path $dest -ItemType Directory -Force }
Copy-Item "\\fileserver\deploy\claude-telemetry.mjs" "$dest\claude-telemetry.mjs" -Force
 


linkStep 2: Configure Managed Settings

linkMethod A (Preferable): Server-Managed Settings (Admin Console)

This is the simplest method. No MDM required. Settings are delivered from Anthropic's servers and cached locally on each developer machine.



Sign in to claude.ai as an organization Admin.

Navigate to Admin Settings → Claude Code → Managed settings.

Paste the following JSON:

{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "node /opt/gitclear/claude-telemetry.mjs",
"timeout": 5
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "node /opt/gitclear/claude-telemetry.mjs --flush",
"async": true,
"timeout": 30
}
]
}
]
},
"allowManagedHooksOnly": true
}


Click Save.

Settings take effect on the next Claude Code session start. Existing sessions pick up changes within one hour (Claude Code polls for updates hourly).

Windows adjustment: Replace the command paths with: "node \"C:\\Program Files\\GitClear\\claude-telemetry.mjs\""

Limitation (current beta): Server-managed settings apply uniformly to all users in the organization. Per-group targeting is not yet supported. If you need different settings for different teams, use MDM or file-based deployment.


linkMethod B (More Complicated): macOS MDM (Jamf / Kandji / Intune)

Deploy a configuration profile targeting the com.anthropic.claudecode managed preferences domain. This provides OS-level enforcement that persists even if the developer has local admin rights.


Create a .mobileconfig file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadType</key>
<string>com.anthropic.claudecode</string>
<key>PayloadIdentifier</key>
<string>com.gitclear.claudecode.telemetry</string>
<key>PayloadUUID</key>
<string>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</string>
<key>PayloadVersion</key>
<integer>1</integer>
 
<key>Settings</key>
<string>{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit|MultiEdit",
"hooks": [{
"type": "command",
"command": "node /opt/gitclear/claude-telemetry.mjs",
"timeout": 5
}]
}],
"SessionEnd": [{
"hooks": [{
"type": "command",
"command": "node /opt/gitclear/claude-telemetry.mjs --flush",
"async": true,
"timeout": 30
}]
}]
},
"allowManagedHooksOnly": true
}</string>
</dict>
</array>
 
<key>PayloadDisplayName</key>
<string>GitClear Claude Code Telemetry</string>
<key>PayloadIdentifier</key>
<string>com.gitclear.claudecode.telemetry.profile</string>
<key>PayloadUUID</key>
<string>F1E2D3C4-B5A6-0987-FEDC-BA9876543210</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>
 

Deploy via Jamf Pro:

Go to Computers → Configuration Profiles → + New.

Under Application & Custom Settings, upload the .mobileconfig.

Scope to your developer Smart Group.

Save and distribute.

Deploy via Kandji:

Go to Library → Add New → Custom Profile.

Upload the .mobileconfig file.

Assign to your developer Blueprint.

Generate a unique PayloadUUID: Run uuidgen in Terminal and replace the placeholder UUIDs above. Each profile and each payload within it must have a unique UUID.

linkMethod C: Windows Group Policy / Intune

Deploy settings via the Windows registry at HKLM\SOFTWARE\Policies\ClaudeCode.


Group Policy (GPO) deployment:

Create a .reg file:

Windows Registry Editor Version 5.00
 
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\ClaudeCode]
"Settings"="{\"hooks\":{\"PostToolUse\":[{\"matcher\":\"Write|Edit|MultiEdit\",\"hooks\":[{\"type\":\"command\",\"command\":\"node \\\"C:\\\\Program Files\\\\GitClear\\\\claude-telemetry.mjs\\\"\",\"timeout\":5}]}],\"SessionEnd\":[{\"hooks\":[{\"type\":\"command\",\"command\":\"node \\\"C:\\\\Program Files\\\\GitClear\\\\claude-telemetry.mjs\\\" --flush\",\"async\":true,\"timeout\":30}]}]},\"allowManagedHooksOnly\":true}"
 

Deploy via a GPO Computer Startup Script that imports the .reg.

Intune deployment (PowerShell remediation):

# Detection script
$path = "HKLM:\SOFTWARE\Policies\ClaudeCode"
$val = (Get-ItemProperty -Path $path -Name "Settings" -ErrorAction SilentlyContinue).Settings
if ($val -and $val -match "gitclear-telemetry") { exit 0 } else { exit 1 }
 
# Remediation script
$settingsJson = @'
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "node /opt/gitclear/gitclear-telemetry.mjs",
"timeout": 5
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "node /opt/gitclear/gitclear-telemetry.mjs --flush",
"async": true,
"timeout": 30
}
]
}
]
},
"allowManagedHooksOnly": true
}
'@
 
$path = "HKLM:\SOFTWARE\Policies\ClaudeCode"
if (-not (Test-Path $path)) { New-Item -Path $path -Force }
 
# Compact to single line for registry storage
$compact = ($settingsJson | ConvertFrom-Json | ConvertTo-Json -Depth 10 -Compress)
Set-ItemProperty -Path $path -Name "Settings" -Value $compact -Type String
 

linkMethod D: File-Based (Ansible / Chef / Puppet / Manual)

Deploy a managed-settings.json file to the system-level directory. Requires root/admin access to write, but is readable by the developer's user account.


File locations:

OS

Path

macOS

/Library/Application Support/ClaudeCode/managed-settings.json

Linux

/etc/claude-code/managed-settings.json

Windows

C:\Program Files\ClaudeCode\managed-settings.json

Ansible example (Linux + macOS):

- name: Deploy GitClear Claude Code managed settings
hosts: developer_workstations
become: yes
tasks:
- name: Create Claude Code managed settings directory (Linux)
file:
path: /etc/claude-code
state: directory
mode: '0755'
when: ansible_system == "Linux"
 
- name: Create Claude Code managed settings directory (macOS)
file:
path: "/Library/Application Support/ClaudeCode"
state: directory
mode: '0755'
when: ansible_system == "Darwin"
 
- name: Deploy managed-settings.json (Linux)
copy:
src: files/managed-settings.json
dest: /etc/claude-code/managed-settings.json
mode: '0644'
when: ansible_system == "Linux"
 
- name: Deploy managed-settings.json (macOS)
copy:
src: files/managed-settings.json
dest: "/Library/Application Support/ClaudeCode/managed-settings.json"
mode: '0644'
when: ansible_system == "Darwin"
 

Drop-in directory: You can also use managed-settings.d/ alongside the base file. Files in that directory are sorted alphabetically and deep-merged onto the base. This lets you ship the GitClear hook as an independent fragment (e.g., 20-claude-telemetry.json) without touching existing managed settings:

/etc/claude-code/
managed-settings.json # existing org security policy
managed-settings.d/
10-security.json # existing deny rules
20-claude-telemetry.json # your hook config (merged on top)
 

Arrays (like hooks.PostToolUse) are concatenated and deduplicated, so the GitClear hooks are added alongside any existing hooks without replacing them.


linkStep 3: Verify Deployment

linkOn a developer machine (non-invasive spot check)

Ask a developer to run the following inside Claude Code. They do not need to understand what this does — it is a diagnostic command:

/status

In the output, look for the managed settings source line. It should show one of:

Enterprise managed settings (remote) — Method A is active

Enterprise managed settings (plist) — Method B is active

Enterprise managed settings (HKLM) — Method C is active

Enterprise managed settings (file) — Method D is active

Then run:

/hooks

This lists all active hooks. You should see PostToolUse with matcher Write|Edit|MultiEdit sourced from "managed".

linkAutomated verification (fleet-wide)

macOS (via MDM Extension Attribute in Jamf):

#!/bin/bash
# Jamf Extension Attribute: GitClear Hook Status
LOG="$HOME/.gitclear/active.jsonl"
if [ -f "$LOG" ]; then
LINES=$(wc -l < "$LOG")
LAST=$(tail -1 "$LOG" | python3 -c "import sys,json; print(json.load(sys.stdin)['ts'])" 2>/dev/null)
echo "<result>Active: ${LINES} events, last: ${LAST}</result>"
else
echo "<result>No events recorded yet</result>"
fi
 

Linux / any OS (via Ansible ad-hoc):

ansible developer_workstations -a "wc -l ~/.gitclear/active.jsonl" --become-user={{ dev_user }}
 


linkStep 4: Secure the API Token

The GITCLEAR_API_TOKEN value in your managed settings is readable by the developer (they can inspect managed settings via /status or by reading the file). This is acceptable because:

The token is scoped to write-only telemetry ingestion — it cannot read GitClear data or modify settings.

The developer is already a member of the organization.

If your security policy requires stricter secret handling:

macOS MDM: Store the token in a separate managed preference or Keychain item, and modify the hook script to read from the Keychain at runtime.

Linux: Store in a root-owned file (/etc/gitclear/token) with mode 0644, and modify the hook to read from that file instead of the environment.

Windows: Store in a separate registry key under HKLM with restricted ACLs, and modify the hook to read from the registry.


linkUpdating the Hook

To push an updated version of claude-telemetry.mjs:

Distribute the new script file using the same mechanism as Step 1.

No changes to managed settings are needed (the settings reference the file path, not the file contents).

The updated script takes effect on the next hook invocation — no Claude Code restart required.

To update the managed settings (e.g., change flush interval or add new hook events):

Method A: Edit in the Admin Console. Changes propagate within one hour.

Methods B/C/D: Push the updated file/profile/registry via your existing deployment pipeline.




linkTroubleshooting

Symptom

Likely cause

Fix

/status shows no managed source

Settings file in wrong path, or MDM profile not scoped to machine

Verify file exists at the OS-specific path; check MDM scope

/hooks shows no PostToolUse hook

Managed settings JSON is malformed

Validate JSON syntax; check /status for parse errors

~/.gitclear/active.jsonl is not created

Hook script not found at referenced path

Verify node /opt/gitclear/claude-telemetry.mjs runs without error from the developer's shell

Events are cached but never uploaded

GITCLEAR_INGEST_URL or GITCLEAR_API_TOKEN not set, or network blocked

Check the env block in managed settings; verify outbound HTTPS to www.gitclear.com

Developer reports Claude Code is slow

Hook timeout too high, or script hanging on network call

The PostToolUse hook has a 5-second timeout; if it consistently hits this, check Node.js availability

Developer bypasses hooks with disableAllHooks

Known bug (GitHub #26637, Feb 2026)

Set allowManagedHooksOnly: true in managed settings (already included in the config above); monitor for upstream fix




linkWhat Developers Will See

Upon first opening claude:




Afterwards: Nothing. The hook runs silently after every file write/edit. It does not produce output, does not prompt for input, and does not slow down Claude Code (the 5-second timeout is a ceiling; typical execution is under 100ms). The only observable artifact is the ~/.gitclear/ directory on their machine, which contains the cached JSONL files.


If a developer runs /hooks, they will see the GitClear hooks listed as "managed" — this is by design and transparent. They cannot disable or modify these hooks.