Skip to content
Draft
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
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"displayName": "PostHog",
"source": "./",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from your AI coding tool. Optionally capture Claude Code sessions to PostHog LLM Analytics.",
"version": "1.1.64",
"version": "1.1.65",
"author": {
"name": "PostHog",
"email": "hey@posthog.com",
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "posthog",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from your AI coding tool. Optionally capture Claude Code sessions to PostHog LLM Analytics.",
"version": "1.1.64",
"version": "1.1.65",
"author": {
"name": "PostHog",
"email": "hey@posthog.com",
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posthog",
"version": "1.0.61",
"version": "1.0.62",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from Codex",
"author": {
"name": "PostHog",
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "posthog",
"displayName": "PostHog",
"version": "1.1.57",
"version": "1.1.58",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from Cursor",
"author": {
"name": "PostHog",
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/sync-skills.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ jobs:
-o /tmp/context-mill.zip \
"https://github.com/PostHog/context-mill/releases/latest/download/skills-mcp-resources.zip"

- name: Regenerate MCP write-tool list
run: |
bash scripts/generate-write-tools.sh \
|| echo "::warning::write-tools.txt not regenerated; keeping the committed list"

- name: Sync skills directory
run: |
MANIFEST="skills/.sync-manifest"
Expand Down Expand Up @@ -91,7 +96,7 @@ jobs:
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
git add -A skills/ commands/*.toml gemini-extension.json
git add -A skills/ commands/*.toml gemini-extension.json hooks/write-tools.txt
if git diff --cached --quiet; then
echo "No changes detected."
echo "has_changes=false" >> "$GITHUB_OUTPUT"
Expand Down
2 changes: 1 addition & 1 deletion gemini-extension.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posthog",
"version": "1.0.59",
"version": "1.0.60",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from Gemini CLI",
"mcpServers": {
"posthog": {
Expand Down
31 changes: 24 additions & 7 deletions hooks/gate-exec-write.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
#
# export POSTHOG_MCP_EXEC_GATE_ALLOW="llma-skill-*,annotation-create"
#
# A tool counts as a write when it appears in `hooks/write-tools.txt` (every
# registry tool with readOnlyHint=false, regenerated by
# scripts/generate-write-tools.sh) or when its name carries a write verb from
# the regex below. The regex is the fallback for a missing list and for tools
# added to PostHog after the list was generated.
#
# Pure bash; no jq or other third-party tools required. Relies on the fact
# that PostHog tool names are kebab-case alphanumerics, so a narrow regex on
# the raw JSON payload is safe.
Expand Down Expand Up @@ -107,14 +113,16 @@ fi
# `mcp__posthog_posthog__exec`).
[[ "$tool_name" =~ __exec$ ]] || exit 0

# Extract the PostHog tool name from `"command":"call [--json] <tool>..."`.
# Tool names are kebab-case [a-zA-Z0-9_-]+ so the regex stops cleanly at the
# first space or escaped quote without needing to parse the trailing JSON.
# Extract the PostHog tool name from `"command":"call [--flag ...] <tool>..."`.
# `call` accepts several leading flags (`--json`, `--confirm`, `--no-skills`),
# so skip every `--` token before the name. Tool names are kebab-case
# [a-zA-Z0-9_-]+ so the regex stops cleanly at the first space or escaped quote
# without needing to parse the trailing JSON.
posthog_tool=""
if [[ "$input" =~ \"command\"[[:space:]]*:[[:space:]]*\"call[[:space:]]+(--json[[:space:]]+)?([a-zA-Z0-9_-]+) ]]; then
posthog_tool="${BASH_REMATCH[2]}"
if [[ "$input" =~ \"command\"[[:space:]]*:[[:space:]]*\"call[[:space:]]+((--[a-zA-Z-]+[[:space:]]+)*)([a-zA-Z0-9_-]+) ]]; then
posthog_tool="${BASH_REMATCH[3]}"
fi
[[ -n "$posthog_tool" ]] || exit 0
[[ -n "$posthog_tool" && "$posthog_tool" != -* ]] || exit 0

# Match write-verb fragments as whole hyphen-separated words within the tool
# name. Keep this list in sync with the PostHog MCP write surface.
Expand All @@ -135,8 +143,17 @@ matches_any_glob() {
return 1
}

write_tools_file="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/write-tools.txt"
write_tools=""
[[ -r "$write_tools_file" ]] && write_tools=$'\n'"$(<"$write_tools_file")"$'\n'

is_write_tool() {
[[ -n "$write_tools" && "$write_tools" == *$'\n'"$1"$'\n'* ]] && return 0
[[ "$1" =~ $write_re ]]
}

shopt -s nocasematch
if [[ "$posthog_tool" =~ $write_re ]]; then
if is_write_tool "$posthog_tool"; then
# Allowlist wins — skip the prompt for tools matching any glob in
# POSTHOG_MCP_EXEC_GATE_ALLOW. Patterns use bash glob syntax (`*`, `?`).
if [[ -n "${POSTHOG_MCP_EXEC_GATE_ALLOW:-}" ]]; then
Expand Down
Loading
Loading