Compare commits

..

1 Commits

Author SHA1 Message Date
Ashwin Bhat
ead501a4a9 Remove timeout-minutes from lock-closed-issues workflow
The 10-minute timeout is unnecessary for this workflow as it typically
completes quickly. Removing it allows the workflow to use the default
GitHub Actions timeout (6 hours for public repos, 72 hours for private),
providing more flexibility if the workflow needs to process a large
number of issues.

Also fixed trailing whitespace inconsistencies in the script.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-09 10:41:27 -07:00
9 changed files with 106 additions and 139 deletions

View File

@@ -65,8 +65,8 @@ ENV PATH=$PATH:/usr/local/share/npm-global/bin
ENV SHELL=/bin/zsh
# Set the default editor and visual
ENV EDITOR=nano
ENV VISUAL=nano
ENV EDITOR nano
ENV VISUAL nano
# Default powerline10k theme
ARG ZSH_IN_DOCKER_VERSION=1.2.0

View File

@@ -16,7 +16,6 @@
"customizations": {
"vscode": {
"extensions": [
"anthropic.claude-code",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"eamodio.gitlens"
@@ -52,6 +51,5 @@
},
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
"workspaceFolder": "/workspace",
"postStartCommand": "sudo /usr/local/bin/init-firewall.sh",
"waitFor": "postStartCommand"
"postCreateCommand": "sudo /usr/local/bin/init-firewall.sh"
}

View File

@@ -69,12 +69,9 @@ for domain in \
"api.anthropic.com" \
"sentry.io" \
"statsig.anthropic.com" \
"statsig.com" \
"marketplace.visualstudio.com" \
"vscode.blob.core.windows.net" \
"update.code.visualstudio.com"; do
"statsig.com"; do
echo "Resolving $domain..."
ips=$(dig +noall +answer A "$domain" | awk '$4 == "A" {print $5}')
ips=$(dig +short A "$domain")
if [ -z "$ips" ]; then
echo "ERROR: Failed to resolve $domain"
exit 1
@@ -116,9 +113,6 @@ iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Then allow only specific outbound traffic to allowed domains
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
# Explicitly REJECT all other outbound traffic for immediate feedback
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
echo "Firewall configuration complete"
echo "Verifying firewall rules..."
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then

View File

@@ -11,7 +11,7 @@ jobs:
timeout-minutes: 10
permissions:
contents: read
issues: write
issues: read
steps:
- name: Checkout repository

View File

@@ -1,40 +1,68 @@
name: Log Issue Events to Statsig
name: Log GitHub Issue Events
on:
issues:
types: [opened]
jobs:
log-to-statsig:
log-issue-created:
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
issues: read
steps:
- name: Log issue creation to Statsig
env:
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: |
# All values are now safely passed via environment variables
# No direct templating in the shell script to prevent injection attacks
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 }}"
curl -X POST "https://events.statsigapi.net/v1/log_event" \
-H "Content-Type: application/json" \
-H "statsig-api-key: $STATSIG_API_KEY" \
-d '{
"events": [{
"eventName": "github_issue_created",
"metadata": {
"issue_number": "'"$ISSUE_NUMBER"'",
"repository": "'"$REPO"'",
"title": "'"$(echo "$ISSUE_TITLE" | sed "s/\"/\\\\\"/g")"'",
"author": "'"$AUTHOR"'",
"created_at": "'"$CREATED_AT"'"
if [ -z "$STATSIG_API_KEY" ]; then
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": '"$(date +%s)000"'
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 "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 creation for issue #${ISSUE_NUMBER}"
else
echo "Failed to log issue creation for issue #${ISSUE_NUMBER}. HTTP ${HTTP_CODE}: ${BODY}"
fi

View File

@@ -1,80 +1,5 @@
# Changelog
## 1.0.93
- Windows: Add alt + v shortcut for pasting images from clipboard
## 1.0.90
- Settings file changes take effect immediately - no restart required
## 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
- Ask permissions: have Claude Code always ask for confirmation to use specific tools with /permissions
## 1.0.71
- Background commands: (Ctrl-b) to run any Bash command in the background so Claude can keep working (great for dev servers, tailing logs, etc.)

View File

@@ -24,10 +24,6 @@ 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).
## 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
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.

View File

@@ -40,18 +40,14 @@ Write-Host "Using backend: $($Backend)"
# --- Prerequisite Check ---
Write-Host "Checking for required commands..."
try {
if (-not (Get-Command $Backend -ErrorAction SilentlyContinue)) {
throw "Required command '$($Backend)' not found."
}
Get-Command $Backend -ErrorAction Stop | Out-Null
Write-Host "- $($Backend) command found."
if (-not (Get-Command devcontainer -ErrorAction SilentlyContinue)) {
throw "Required command 'devcontainer' not found."
}
Get-Command devcontainer -ErrorAction Stop | Out-Null
Write-Host "- devcontainer command found."
}
catch {
Write-Error "A required command is not installed or not in your PATH. $($_.Exception.Message)"
Write-Error "Please ensure both '$Backend' and 'devcontainer' are installed and accessible in your system's PATH."
Write-Error "A required command is not installed or not in your PATH."
Write-Error "Please ensure '$($_.Exception.Message.Split(':')[0])' and 'devcontainer' are installed and accessible."
exit 1
}

View File

@@ -47,21 +47,45 @@ async function githubRequest<T>(endpoint: string, token: string, method: string
}
function extractDuplicateIssueNumber(commentBody: string): number | null {
// Try to match #123 format first
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;
const match = commentBody.match(/#(\d+)/);
return match ? parseInt(match[1], 10) : 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(
owner: string,
@@ -76,8 +100,7 @@ async function closeIssueAsDuplicate(
'PATCH',
{
state: 'closed',
state_reason: 'duplicate',
labels: ['duplicate']
state_reason: 'not_planned'
}
);
@@ -94,6 +117,13 @@ 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> {