mirror of
https://github.com/anthropics/claude-code.git
synced 2026-02-19 04:27:33 -08:00
Compare commits
27 Commits
boris/lptz
...
ashwin/tas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87e1022e09 | ||
|
|
eb0e43457b | ||
|
|
b417bfc532 | ||
|
|
239aeb55ee | ||
|
|
f4e707fdcc | ||
|
|
d2f88820c9 | ||
|
|
a3620cdd0b | ||
|
|
da6d2f715e | ||
|
|
f200ab3c5c | ||
|
|
fa29b8f9c0 | ||
|
|
2558619a83 | ||
|
|
80ceacaa78 | ||
|
|
4e63568abd | ||
|
|
5d0b81ae41 | ||
|
|
b1751f2e86 | ||
|
|
eb48d5e4a8 | ||
|
|
fc8c10995f | ||
|
|
01fb7af5b3 | ||
|
|
afb0fc9156 | ||
|
|
370a97d939 | ||
|
|
f54569efd2 | ||
|
|
d8cf5a874c | ||
|
|
e499db6e9e | ||
|
|
5300e12135 | ||
|
|
4a04589002 | ||
|
|
04cace9ec0 | ||
|
|
2dbf1e97a0 |
@@ -71,7 +71,7 @@ for domain in \
|
|||||||
"statsig.anthropic.com" \
|
"statsig.anthropic.com" \
|
||||||
"statsig.com"; do
|
"statsig.com"; do
|
||||||
echo "Resolving $domain..."
|
echo "Resolving $domain..."
|
||||||
ips=$(dig +short A "$domain")
|
ips=$(dig +noall +answer A "$domain" | awk '$4 == "A" {print $5}')
|
||||||
if [ -z "$ips" ]; then
|
if [ -z "$ips" ]; then
|
||||||
echo "ERROR: Failed to resolve $domain"
|
echo "ERROR: Failed to resolve $domain"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
2
.github/workflows/auto-close-duplicates.yml
vendored
2
.github/workflows/auto-close-duplicates.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
issues: read
|
issues: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
|
|||||||
186
.github/workflows/log-issue-events.yml
vendored
186
.github/workflows/log-issue-events.yml
vendored
@@ -1,180 +1,40 @@
|
|||||||
name: Log GitHub Issue Events
|
name: Log Issue Events to Statsig
|
||||||
|
|
||||||
on:
|
on:
|
||||||
issues:
|
issues:
|
||||||
types: [opened, closed]
|
types: [opened]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
log-issue-created:
|
log-to-statsig:
|
||||||
if: github.event.action == 'opened'
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 5
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
|
||||||
issues: read
|
issues: read
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Log issue creation to Statsig
|
- name: Log issue creation to Statsig
|
||||||
env:
|
env:
|
||||||
STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
|
STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
|
||||||
|
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||||
|
REPO: ${{ github.repository }}
|
||||||
|
ISSUE_TITLE: ${{ github.event.issue.title }}
|
||||||
|
AUTHOR: ${{ github.event.issue.user.login }}
|
||||||
|
CREATED_AT: ${{ github.event.issue.created_at }}
|
||||||
run: |
|
run: |
|
||||||
ISSUE_NUMBER=${{ github.event.issue.number }}
|
# All values are now safely passed via environment variables
|
||||||
REPO=${{ github.repository }}
|
# No direct templating in the shell script to prevent injection attacks
|
||||||
ISSUE_TITLE=$(echo '${{ github.event.issue.title }}' | sed "s/'/'\\\\''/g")
|
|
||||||
AUTHOR="${{ github.event.issue.user.login }}"
|
|
||||||
CREATED_AT="${{ github.event.issue.created_at }}"
|
|
||||||
|
|
||||||
if [ -z "$STATSIG_API_KEY" ]; then
|
curl -X POST "https://events.statsigapi.net/v1/log_event" \
|
||||||
echo "STATSIG_API_KEY not found, skipping Statsig logging"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prepare the event payload
|
|
||||||
EVENT_PAYLOAD=$(jq -n \
|
|
||||||
--arg issue_number "$ISSUE_NUMBER" \
|
|
||||||
--arg repo "$REPO" \
|
|
||||||
--arg title "$ISSUE_TITLE" \
|
|
||||||
--arg author "$AUTHOR" \
|
|
||||||
--arg created_at "$CREATED_AT" \
|
|
||||||
'{
|
|
||||||
events: [{
|
|
||||||
eventName: "github_issue_created",
|
|
||||||
value: 1,
|
|
||||||
metadata: {
|
|
||||||
repository: $repo,
|
|
||||||
issue_number: ($issue_number | tonumber),
|
|
||||||
issue_title: $title,
|
|
||||||
issue_author: $author,
|
|
||||||
created_at: $created_at
|
|
||||||
},
|
|
||||||
time: (now | floor | tostring)
|
|
||||||
}]
|
|
||||||
}')
|
|
||||||
|
|
||||||
# Send to Statsig API
|
|
||||||
echo "Logging issue creation to Statsig for issue #${ISSUE_NUMBER}"
|
|
||||||
|
|
||||||
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST https://events.statsigapi.net/v1/log_event \
|
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-H "STATSIG-API-KEY: ${STATSIG_API_KEY}" \
|
-H "statsig-api-key: $STATSIG_API_KEY" \
|
||||||
-d "$EVENT_PAYLOAD")
|
-d '{
|
||||||
|
"events": [{
|
||||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
"eventName": "github_issue_created",
|
||||||
BODY=$(echo "$RESPONSE" | head -n-1)
|
"metadata": {
|
||||||
|
"issue_number": "'"$ISSUE_NUMBER"'",
|
||||||
if [ "$HTTP_CODE" -eq 200 ] || [ "$HTTP_CODE" -eq 202 ]; then
|
"repository": "'"$REPO"'",
|
||||||
echo "Successfully logged issue creation for issue #${ISSUE_NUMBER}"
|
"title": "'"$(echo "$ISSUE_TITLE" | sed "s/\"/\\\\\"/g")"'",
|
||||||
else
|
"author": "'"$AUTHOR"'",
|
||||||
echo "Failed to log issue creation for issue #${ISSUE_NUMBER}. HTTP ${HTTP_CODE}: ${BODY}"
|
"created_at": "'"$CREATED_AT"'"
|
||||||
fi
|
|
||||||
|
|
||||||
log-issue-closed:
|
|
||||||
if: github.event.action == 'closed'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 5
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
issues: read
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Log issue closure to Statsig
|
|
||||||
env:
|
|
||||||
STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
ISSUE_NUMBER=${{ github.event.issue.number }}
|
|
||||||
REPO=${{ github.repository }}
|
|
||||||
ISSUE_TITLE=$(echo '${{ github.event.issue.title }}' | sed "s/'/'\\\\''/g")
|
|
||||||
CLOSED_BY="${{ github.event.issue.closed_by.login }}"
|
|
||||||
CLOSED_AT="${{ github.event.issue.closed_at }}"
|
|
||||||
STATE_REASON="${{ github.event.issue.state_reason }}"
|
|
||||||
|
|
||||||
if [ -z "$STATSIG_API_KEY" ]; then
|
|
||||||
echo "STATSIG_API_KEY not found, skipping Statsig logging"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get additional issue data via GitHub API
|
|
||||||
echo "Fetching additional issue data for #${ISSUE_NUMBER}"
|
|
||||||
ISSUE_DATA=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \
|
|
||||||
-H "Accept: application/vnd.github.v3+json" \
|
|
||||||
"https://api.github.com/repos/${REPO}/issues/${ISSUE_NUMBER}")
|
|
||||||
|
|
||||||
COMMENTS_COUNT=$(echo "$ISSUE_DATA" | jq -r '.comments')
|
|
||||||
|
|
||||||
# Get reactions data
|
|
||||||
REACTIONS_DATA=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \
|
|
||||||
-H "Accept: application/vnd.github.v3+json" \
|
|
||||||
"https://api.github.com/repos/${REPO}/issues/${ISSUE_NUMBER}/reactions")
|
|
||||||
|
|
||||||
REACTIONS_COUNT=$(echo "$REACTIONS_DATA" | jq '. | length')
|
|
||||||
|
|
||||||
# Check if issue was closed automatically (by checking if closed_by is a bot)
|
|
||||||
CLOSED_AUTOMATICALLY="false"
|
|
||||||
if [[ "$CLOSED_BY" == *"[bot]"* ]]; then
|
|
||||||
CLOSED_AUTOMATICALLY="true"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if closed as duplicate by looking for duplicate label or state_reason
|
|
||||||
CLOSED_AS_DUPLICATE="false"
|
|
||||||
if [ "$STATE_REASON" = "not_planned" ]; then
|
|
||||||
# Check if issue has duplicate label
|
|
||||||
LABELS=$(echo "$ISSUE_DATA" | jq -r '.labels[] | select(.name | test("duplicate"; "i")) | .name')
|
|
||||||
if [ -n "$LABELS" ]; then
|
|
||||||
CLOSED_AS_DUPLICATE="true"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prepare the event payload
|
|
||||||
EVENT_PAYLOAD=$(jq -n \
|
|
||||||
--arg issue_number "$ISSUE_NUMBER" \
|
|
||||||
--arg repo "$REPO" \
|
|
||||||
--arg title "$ISSUE_TITLE" \
|
|
||||||
--arg closed_by "$CLOSED_BY" \
|
|
||||||
--arg closed_at "$CLOSED_AT" \
|
|
||||||
--arg state_reason "$STATE_REASON" \
|
|
||||||
--arg comments_count "$COMMENTS_COUNT" \
|
|
||||||
--arg reactions_count "$REACTIONS_COUNT" \
|
|
||||||
--arg closed_automatically "$CLOSED_AUTOMATICALLY" \
|
|
||||||
--arg closed_as_duplicate "$CLOSED_AS_DUPLICATE" \
|
|
||||||
'{
|
|
||||||
events: [{
|
|
||||||
eventName: "github_issue_closed",
|
|
||||||
value: 1,
|
|
||||||
metadata: {
|
|
||||||
repository: $repo,
|
|
||||||
issue_number: ($issue_number | tonumber),
|
|
||||||
issue_title: $title,
|
|
||||||
closed_by: $closed_by,
|
|
||||||
closed_at: $closed_at,
|
|
||||||
state_reason: $state_reason,
|
|
||||||
comments_count: ($comments_count | tonumber),
|
|
||||||
reactions_count: ($reactions_count | tonumber),
|
|
||||||
closed_automatically: ($closed_automatically | test("true")),
|
|
||||||
closed_as_duplicate: ($closed_as_duplicate | test("true"))
|
|
||||||
},
|
},
|
||||||
time: (now | floor | tostring)
|
"time": '"$(date +%s)000"'
|
||||||
}]
|
}]
|
||||||
}')
|
}'
|
||||||
|
|
||||||
# Send to Statsig API
|
|
||||||
echo "Logging issue closure to Statsig for issue #${ISSUE_NUMBER}"
|
|
||||||
|
|
||||||
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST https://events.statsigapi.net/v1/log_event \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "STATSIG-API-KEY: ${STATSIG_API_KEY}" \
|
|
||||||
-d "$EVENT_PAYLOAD")
|
|
||||||
|
|
||||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
||||||
BODY=$(echo "$RESPONSE" | head -n-1)
|
|
||||||
|
|
||||||
if [ "$HTTP_CODE" -eq 200 ] || [ "$HTTP_CODE" -eq 202 ]; then
|
|
||||||
echo "Successfully logged issue closure for issue #${ISSUE_NUMBER}"
|
|
||||||
echo "Closed by: $CLOSED_BY"
|
|
||||||
echo "Comments: $COMMENTS_COUNT"
|
|
||||||
echo "Reactions: $REACTIONS_COUNT"
|
|
||||||
echo "Closed automatically: $CLOSED_AUTOMATICALLY"
|
|
||||||
echo "Closed as duplicate: $CLOSED_AS_DUPLICATE"
|
|
||||||
else
|
|
||||||
echo "Failed to log issue closure for issue #${ISSUE_NUMBER}. HTTP ${HTTP_CODE}: ${BODY}"
|
|
||||||
fi
|
|
||||||
42
.github/workflows/remove-autoclose-label.yml
vendored
Normal file
42
.github/workflows/remove-autoclose-label.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
name: "Remove Autoclose Label on Activity"
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
remove-autoclose:
|
||||||
|
# Only run if the issue has the autoclose label
|
||||||
|
if: |
|
||||||
|
github.event.issue.state == 'open' &&
|
||||||
|
contains(github.event.issue.labels.*.name, 'autoclose') &&
|
||||||
|
github.event.comment.user.login != 'github-actions[bot]'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Remove autoclose label
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
console.log(`Removing autoclose label from issue #${context.issue.number} due to new comment from ${context.payload.comment.user.login}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Remove the autoclose label
|
||||||
|
await github.rest.issues.removeLabel({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
name: 'autoclose'
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Successfully removed autoclose label from issue #${context.issue.number}`);
|
||||||
|
} catch (error) {
|
||||||
|
// If the label was already removed or doesn't exist, that's fine
|
||||||
|
if (error.status === 404) {
|
||||||
|
console.log(`Autoclose label was already removed from issue #${context.issue.number}`);
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
157
.github/workflows/stale-issue-manager.yml
vendored
Normal file
157
.github/workflows/stale-issue-manager.yml
vendored
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
name: "Manage Stale Issues"
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# 2am Pacific = 9am UTC (10am UTC during DST)
|
||||||
|
- cron: "0 10 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: stale-issue-manager
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
manage-stale-issues:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Manage stale issues
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const oneMonthAgo = new Date();
|
||||||
|
oneMonthAgo.setDate(oneMonthAgo.getDate() - 30);
|
||||||
|
|
||||||
|
const twoMonthsAgo = new Date();
|
||||||
|
twoMonthsAgo.setDate(twoMonthsAgo.getDate() - 60);
|
||||||
|
|
||||||
|
const warningComment = `This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.`;
|
||||||
|
|
||||||
|
const closingComment = `This issue has been automatically closed due to 60 days of inactivity. If you're still experiencing this issue, please open a new issue with updated information.`;
|
||||||
|
|
||||||
|
let page = 1;
|
||||||
|
let hasMore = true;
|
||||||
|
let totalWarned = 0;
|
||||||
|
let totalClosed = 0;
|
||||||
|
let totalLabeled = 0;
|
||||||
|
|
||||||
|
while (hasMore) {
|
||||||
|
// Get open issues sorted by last updated (oldest first)
|
||||||
|
const { data: issues } = await github.rest.issues.listForRepo({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
state: 'open',
|
||||||
|
sort: 'updated',
|
||||||
|
direction: 'asc',
|
||||||
|
per_page: 100,
|
||||||
|
page: page
|
||||||
|
});
|
||||||
|
|
||||||
|
if (issues.length === 0) {
|
||||||
|
hasMore = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const issue of issues) {
|
||||||
|
// Skip if already locked
|
||||||
|
if (issue.locked) continue;
|
||||||
|
|
||||||
|
// Skip pull requests
|
||||||
|
if (issue.pull_request) continue;
|
||||||
|
|
||||||
|
// Check if updated more recently than 30 days ago
|
||||||
|
const updatedAt = new Date(issue.updated_at);
|
||||||
|
if (updatedAt > oneMonthAgo) {
|
||||||
|
// Since issues are sorted by updated_at ascending,
|
||||||
|
// once we hit a recent issue, all remaining will be recent too
|
||||||
|
hasMore = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if issue has autoclose label
|
||||||
|
const hasAutocloseLabel = issue.labels.some(label =>
|
||||||
|
typeof label === 'object' && label.name === 'autoclose'
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get comments to check for existing warning
|
||||||
|
const { data: comments } = await github.rest.issues.listComments({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
per_page: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find the last comment from github-actions bot
|
||||||
|
const botComments = comments.filter(comment =>
|
||||||
|
comment.user && comment.user.login === 'github-actions[bot]' &&
|
||||||
|
comment.body && comment.body.includes('inactive for 30 days')
|
||||||
|
);
|
||||||
|
|
||||||
|
const lastBotComment = botComments[botComments.length - 1];
|
||||||
|
|
||||||
|
if (lastBotComment) {
|
||||||
|
// Check if the bot comment is older than 30 days (total 60 days of inactivity)
|
||||||
|
const botCommentDate = new Date(lastBotComment.created_at);
|
||||||
|
if (botCommentDate < oneMonthAgo) {
|
||||||
|
// Close the issue - it's been stale for 60+ days
|
||||||
|
console.log(`Closing issue #${issue.number} (stale for 60+ days): ${issue.title}`);
|
||||||
|
|
||||||
|
// Post closing comment
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
body: closingComment
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close the issue
|
||||||
|
await github.rest.issues.update({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
state: 'closed',
|
||||||
|
state_reason: 'not_planned'
|
||||||
|
});
|
||||||
|
|
||||||
|
totalClosed++;
|
||||||
|
}
|
||||||
|
// If bot comment exists but is recent, issue already has warning
|
||||||
|
} else if (updatedAt < oneMonthAgo) {
|
||||||
|
// No bot warning yet, issue is 30+ days old
|
||||||
|
console.log(`Warning issue #${issue.number} (stale for 30+ days): ${issue.title}`);
|
||||||
|
|
||||||
|
// Post warning comment
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
body: warningComment
|
||||||
|
});
|
||||||
|
|
||||||
|
totalWarned++;
|
||||||
|
|
||||||
|
// Add autoclose label if not present
|
||||||
|
if (!hasAutocloseLabel) {
|
||||||
|
await github.rest.issues.addLabels({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
labels: ['autoclose']
|
||||||
|
});
|
||||||
|
totalLabeled++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to process issue #${issue.number}: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Summary:`);
|
||||||
|
console.log(`- Issues warned (30 days stale): ${totalWarned}`);
|
||||||
|
console.log(`- Issues labeled with autoclose: ${totalLabeled}`);
|
||||||
|
console.log(`- Issues closed (60 days stale): ${totalClosed}`);
|
||||||
63
CHANGELOG.md
63
CHANGELOG.md
@@ -1,5 +1,68 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.0.88
|
||||||
|
|
||||||
|
- Fixed issue causing "OAuth authentication is currently not supported"
|
||||||
|
- Status line input now includes `exceeds_200k_tokens`
|
||||||
|
- Fixed incorrect usage tracking in /cost.
|
||||||
|
- Introduced `ANTHROPIC_DEFAULT_SONNET_MODEL` and `ANTHROPIC_DEFAULT_OPUS_MODEL` for controlling model aliases opusplan, opus, and sonnet.
|
||||||
|
- Bedrock: Updated default Sonnet model to Sonnet 4
|
||||||
|
|
||||||
|
## 1.0.86
|
||||||
|
|
||||||
|
- Added /context to help users self-serve debug context issues
|
||||||
|
- SDK: Added UUID support for all SDK messages
|
||||||
|
- SDK: Added `--replay-user-messages` to replay user messages back to stdout
|
||||||
|
|
||||||
|
## 1.0.85
|
||||||
|
|
||||||
|
- Status line input now includes session cost info
|
||||||
|
- Hooks: Introduced SessionEnd hook
|
||||||
|
|
||||||
|
## 1.0.84
|
||||||
|
|
||||||
|
- Fix tool_use/tool_result id mismatch error when network is unstable
|
||||||
|
- Fix Claude sometimes ignoring real-time steering when wrapping up a task
|
||||||
|
- @-mention: Add ~/.claude/\* files to suggestions for easier agent, output style, and slash command editing
|
||||||
|
- Use built-in ripgrep by default; to opt out of this behavior, set USE_BUILTIN_RIPGREP=0
|
||||||
|
|
||||||
|
## 1.0.83
|
||||||
|
|
||||||
|
- @-mention: Support files with spaces in path
|
||||||
|
- New shimmering spinner
|
||||||
|
|
||||||
|
## 1.0.82
|
||||||
|
|
||||||
|
- SDK: Add request cancellation support
|
||||||
|
- SDK: New additionalDirectories option to search custom paths, improved slash command processing
|
||||||
|
- Settings: Validation prevents invalid fields in .claude/settings.json files
|
||||||
|
- MCP: Improve tool name consistency
|
||||||
|
- Bash: Fix crash when Claude tries to automatically read large files
|
||||||
|
|
||||||
|
## 1.0.81
|
||||||
|
|
||||||
|
- Released output styles, including new built-in educational output styles "Explanatory" and "Learning". Docs: https://docs.anthropic.com/en/docs/claude-code/output-styles
|
||||||
|
- Agents: Fix custom agent loading when agent files are unparsable
|
||||||
|
|
||||||
|
## 1.0.80
|
||||||
|
|
||||||
|
- UI improvements: Fix text contrast for custom subagent colors and spinner rendering issues
|
||||||
|
|
||||||
|
## 1.0.77
|
||||||
|
|
||||||
|
- Bash tool: Fix heredoc and multiline string escaping, improve stderr redirection handling
|
||||||
|
- SDK: Add session support and permission denial tracking
|
||||||
|
- Fix token limit errors in conversation summarization
|
||||||
|
- Opus Plan Mode: New setting in `/model` to run Opus only in plan mode, Sonnet otherwise
|
||||||
|
|
||||||
|
## 1.0.73
|
||||||
|
|
||||||
|
- MCP: Support multiple config files with `--mcp-config file1.json file2.json`
|
||||||
|
- MCP: Press Esc to cancel OAuth authentication flows
|
||||||
|
- Bash: Improved command validation and reduced false security warnings
|
||||||
|
- UI: Enhanced spinner animations and status line visual hierarchy
|
||||||
|
- Linux: Added support for Alpine and musl-based distributions (requires separate ripgrep installation)
|
||||||
|
|
||||||
## 1.0.72
|
## 1.0.72
|
||||||
|
|
||||||
- Ask permissions: have Claude Code always ask for confirmation to use specific tools with /permissions
|
- Ask permissions: have Claude Code always ask for confirmation to use specific tools with /permissions
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ npm install -g @anthropic-ai/claude-code
|
|||||||
|
|
||||||
We welcome your feedback. Use the `/bug` command to report issues directly within Claude Code, or file a [GitHub issue](https://github.com/anthropics/claude-code/issues).
|
We welcome your feedback. Use the `/bug` command to report issues directly within Claude Code, or file a [GitHub issue](https://github.com/anthropics/claude-code/issues).
|
||||||
|
|
||||||
|
## Connect on Discord
|
||||||
|
|
||||||
|
Join the [Claude Developers Discord](https://anthropic.com/discord) to connect with other developers using Claude Code. Get help, share feedback, and discuss your projects with the community.
|
||||||
|
|
||||||
## Data collection, usage, and retention
|
## Data collection, usage, and retention
|
||||||
|
|
||||||
When you use Claude Code, we collect feedback, which includes usage data (such as code acceptance or rejections), associated conversation data, and user feedback submitted via the `/bug` command.
|
When you use Claude Code, we collect feedback, which includes usage data (such as code acceptance or rejections), associated conversation data, and user feedback submitted via the `/bug` command.
|
||||||
|
|||||||
@@ -47,45 +47,21 @@ async function githubRequest<T>(endpoint: string, token: string, method: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
function extractDuplicateIssueNumber(commentBody: string): number | null {
|
function extractDuplicateIssueNumber(commentBody: string): number | null {
|
||||||
const match = commentBody.match(/#(\d+)/);
|
// Try to match #123 format first
|
||||||
return match ? parseInt(match[1], 10) : null;
|
let match = commentBody.match(/#(\d+)/);
|
||||||
|
if (match) {
|
||||||
|
return parseInt(match[1], 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to match GitHub issue URL format: https://github.com/owner/repo/issues/123
|
||||||
|
match = commentBody.match(/github\.com\/[^\/]+\/[^\/]+\/issues\/(\d+)/);
|
||||||
|
if (match) {
|
||||||
|
return parseInt(match[1], 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logStatsigEvent(eventName: string, value: number, metadata: Record<string, any>): Promise<void> {
|
|
||||||
const statsigApiKey = process.env.STATSIG_API_KEY;
|
|
||||||
if (!statsigApiKey) {
|
|
||||||
console.log("[DEBUG] STATSIG_API_KEY not found, skipping Statsig logging");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const eventPayload = {
|
|
||||||
events: [{
|
|
||||||
eventName,
|
|
||||||
value,
|
|
||||||
metadata,
|
|
||||||
time: Math.floor(Date.now()).toString()
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch('https://events.statsigapi.net/v1/log_event', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'STATSIG-API-KEY': statsigApiKey
|
|
||||||
},
|
|
||||||
body: JSON.stringify(eventPayload)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
console.log(`[DEBUG] Successfully logged Statsig event: ${eventName}`);
|
|
||||||
} else {
|
|
||||||
console.log(`[DEBUG] Failed to log Statsig event: ${response.status} ${response.statusText}`);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(`[DEBUG] Error logging to Statsig: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function closeIssueAsDuplicate(
|
async function closeIssueAsDuplicate(
|
||||||
owner: string,
|
owner: string,
|
||||||
@@ -100,7 +76,8 @@ async function closeIssueAsDuplicate(
|
|||||||
'PATCH',
|
'PATCH',
|
||||||
{
|
{
|
||||||
state: 'closed',
|
state: 'closed',
|
||||||
state_reason: 'not_planned'
|
state_reason: 'duplicate',
|
||||||
|
labels: ['duplicate']
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -117,13 +94,6 @@ If this is incorrect, please re-open this issue or create a new one.
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Log to Statsig
|
|
||||||
await logStatsigEvent('github_issue_closed_as_duplicate', 1, {
|
|
||||||
repository: `${owner}/${repo}`,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
duplicate_of_issue: duplicateOfNumber,
|
|
||||||
closed_by: 'auto-close-script'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function autoCloseDuplicates(): Promise<void> {
|
async function autoCloseDuplicates(): Promise<void> {
|
||||||
|
|||||||
Reference in New Issue
Block a user