mirror of
https://github.com/anthropics/claude-code.git
synced 2026-05-05 21:52:41 +00:00
Compare commits
31 Commits
boris/adbf
...
workflow-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0a28eede9 | ||
|
|
81f65bea8a | ||
|
|
dc8f77c7ef | ||
|
|
786259a00c | ||
|
|
8e679e75f7 | ||
|
|
87560460bc | ||
|
|
07e13937b2 | ||
|
|
55988caadf | ||
|
|
8beb9b0c76 | ||
|
|
4607d83fa8 | ||
|
|
70d5361861 | ||
|
|
c792b7d4c7 | ||
|
|
5f52517c0b | ||
|
|
cc09d58e8e | ||
|
|
d820a4dbd7 | ||
|
|
eb0e43457b | ||
|
|
b417bfc532 | ||
|
|
2b46e47360 | ||
|
|
c58a7da257 | ||
|
|
239aeb55ee | ||
|
|
f4e707fdcc | ||
|
|
6d79459b16 | ||
|
|
d2f88820c9 | ||
|
|
a3620cdd0b | ||
|
|
da6d2f715e | ||
|
|
f200ab3c5c | ||
|
|
fa29b8f9c0 | ||
|
|
2558619a83 | ||
|
|
20ba9a34a5 | ||
|
|
eb48d5e4a8 | ||
|
|
10a1f7dab9 |
@@ -65,8 +65,8 @@ ENV PATH=$PATH:/usr/local/share/npm-global/bin
|
|||||||
ENV SHELL=/bin/zsh
|
ENV SHELL=/bin/zsh
|
||||||
|
|
||||||
# Set the default editor and visual
|
# Set the default editor and visual
|
||||||
ENV EDITOR nano
|
ENV EDITOR=nano
|
||||||
ENV VISUAL nano
|
ENV VISUAL=nano
|
||||||
|
|
||||||
# Default powerline10k theme
|
# Default powerline10k theme
|
||||||
ARG ZSH_IN_DOCKER_VERSION=1.2.0
|
ARG ZSH_IN_DOCKER_VERSION=1.2.0
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"extensions": [
|
"extensions": [
|
||||||
|
"anthropic.claude-code",
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"eamodio.gitlens"
|
"eamodio.gitlens"
|
||||||
@@ -51,5 +52,6 @@
|
|||||||
},
|
},
|
||||||
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
|
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
|
||||||
"workspaceFolder": "/workspace",
|
"workspaceFolder": "/workspace",
|
||||||
"postCreateCommand": "sudo /usr/local/bin/init-firewall.sh"
|
"postStartCommand": "sudo /usr/local/bin/init-firewall.sh",
|
||||||
|
"waitFor": "postStartCommand"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,9 +69,12 @@ for domain in \
|
|||||||
"api.anthropic.com" \
|
"api.anthropic.com" \
|
||||||
"sentry.io" \
|
"sentry.io" \
|
||||||
"statsig.anthropic.com" \
|
"statsig.anthropic.com" \
|
||||||
"statsig.com"; do
|
"statsig.com" \
|
||||||
|
"marketplace.visualstudio.com" \
|
||||||
|
"vscode.blob.core.windows.net" \
|
||||||
|
"update.code.visualstudio.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
|
||||||
@@ -113,6 +116,9 @@ iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|||||||
# Then allow only specific outbound traffic to allowed domains
|
# Then allow only specific outbound traffic to allowed domains
|
||||||
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
|
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 "Firewall configuration complete"
|
||||||
echo "Verifying firewall rules..."
|
echo "Verifying firewall rules..."
|
||||||
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
|
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
|
||||||
|
|||||||
59
.github/workflows/issue-notify.yml
vendored
Normal file
59
.github/workflows/issue-notify.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
name: Issue Notification
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [opened]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
notify:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 5
|
||||||
|
steps:
|
||||||
|
- name: Send notification
|
||||||
|
env:
|
||||||
|
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||||
|
ISSUE_TITLE: ${{ github.event.issue.title }}
|
||||||
|
ISSUE_BODY: ${{ github.event.issue.body }}
|
||||||
|
ISSUE_AUTHOR: ${{ github.event.issue.user.login }}
|
||||||
|
ISSUE_LABELS: ${{ toJSON(github.event.issue.labels) }}
|
||||||
|
ISSUE_URL: ${{ github.event.issue.html_url }}
|
||||||
|
ISSUE_CREATED_AT: ${{ github.event.issue.created_at }}
|
||||||
|
REPOSITORY: ${{ github.repository }}
|
||||||
|
DISPATCH_TOKEN: ${{ secrets.CROSS_REPO_TOKEN_CLAUDE_CODE }}
|
||||||
|
DISPATCH_ENDPOINT: ${{ secrets.DISPATCH_ENDPOINT }}
|
||||||
|
run: |
|
||||||
|
if [ -z "$DISPATCH_TOKEN" ] || [ -z "$DISPATCH_ENDPOINT" ]; then
|
||||||
|
echo "Dispatch configuration not complete, skipping notification"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prepare payload with issue metadata
|
||||||
|
PAYLOAD=$(cat <<EOF
|
||||||
|
{
|
||||||
|
"event_type": "issue_event",
|
||||||
|
"client_payload": {
|
||||||
|
"source_repo": "$REPOSITORY",
|
||||||
|
"issue_number": "$ISSUE_NUMBER",
|
||||||
|
"issue_title": $(echo "$ISSUE_TITLE" | jq -Rs .),
|
||||||
|
"issue_body": $(echo "$ISSUE_BODY" | jq -Rs .),
|
||||||
|
"issue_author": "$ISSUE_AUTHOR",
|
||||||
|
"issue_labels": $ISSUE_LABELS,
|
||||||
|
"issue_url": "$ISSUE_URL",
|
||||||
|
"issue_created_at": "$ISSUE_CREATED_AT",
|
||||||
|
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
# Send notification to configured endpoint
|
||||||
|
curl -X POST \
|
||||||
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
|
-H "Authorization: token $DISPATCH_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"$DISPATCH_ENDPOINT" \
|
||||||
|
-d "$PAYLOAD" \
|
||||||
|
--fail-with-body || echo "Notification sent"
|
||||||
2
.github/workflows/log-issue-events.yml
vendored
2
.github/workflows/log-issue-events.yml
vendored
@@ -2,7 +2,7 @@ name: Log Issue Events to Statsig
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
issues:
|
issues:
|
||||||
types: [opened]
|
types: [opened, closed]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
log-to-statsig:
|
log-to-statsig:
|
||||||
|
|||||||
51
CHANGELOG.md
51
CHANGELOG.md
@@ -1,5 +1,56 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.0.97
|
||||||
|
|
||||||
|
- Settings: /doctor now validates permission rule syntax and suggests corrections
|
||||||
|
|
||||||
|
## 1.0.94
|
||||||
|
|
||||||
|
- Vertex: add support for global endpoints for supported models
|
||||||
|
- /memory command now allows direct editing of all imported memory files
|
||||||
|
- SDK: Add custom tools as callbacks
|
||||||
|
- Added /todos command to list current todo items
|
||||||
|
|
||||||
|
## 1.0.93
|
||||||
|
|
||||||
|
- Windows: Add alt + v shortcut for pasting images from clipboard
|
||||||
|
- Support NO_PROXY environment variable to bypass proxy for specified hostnames and IPs
|
||||||
|
|
||||||
|
## 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
|
## 1.0.82
|
||||||
|
|
||||||
- SDK: Add request cancellation support
|
- SDK: Add request cancellation support
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -40,14 +40,18 @@ Write-Host "Using backend: $($Backend)"
|
|||||||
# --- Prerequisite Check ---
|
# --- Prerequisite Check ---
|
||||||
Write-Host "Checking for required commands..."
|
Write-Host "Checking for required commands..."
|
||||||
try {
|
try {
|
||||||
Get-Command $Backend -ErrorAction Stop | Out-Null
|
if (-not (Get-Command $Backend -ErrorAction SilentlyContinue)) {
|
||||||
|
throw "Required command '$($Backend)' not found."
|
||||||
|
}
|
||||||
Write-Host "- $($Backend) command found."
|
Write-Host "- $($Backend) command found."
|
||||||
Get-Command devcontainer -ErrorAction Stop | Out-Null
|
if (-not (Get-Command devcontainer -ErrorAction SilentlyContinue)) {
|
||||||
|
throw "Required command 'devcontainer' not found."
|
||||||
|
}
|
||||||
Write-Host "- devcontainer command found."
|
Write-Host "- devcontainer command found."
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Error "A required command is not installed or not in your PATH."
|
Write-Error "A required command is not installed or not in your PATH. $($_.Exception.Message)"
|
||||||
Write-Error "Please ensure '$($_.Exception.Message.Split(':')[0])' and 'devcontainer' are installed and accessible."
|
Write-Error "Please ensure both '$Backend' and 'devcontainer' are installed and accessible in your system's PATH."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,46 +82,61 @@ Usage:
|
|||||||
Environment Variables:
|
Environment Variables:
|
||||||
GITHUB_TOKEN - GitHub personal access token with repo and actions permissions (required)
|
GITHUB_TOKEN - GitHub personal access token with repo and actions permissions (required)
|
||||||
DRY_RUN - Set to "false" to actually trigger workflows (default: true for safety)
|
DRY_RUN - Set to "false" to actually trigger workflows (default: true for safety)
|
||||||
DAYS_BACK - How many days back to look for old issues (default: 90)`);
|
MAX_ISSUE_NUMBER - Only process issues with numbers less than this value (default: 4050)`);
|
||||||
}
|
}
|
||||||
console.log("[DEBUG] GitHub token found");
|
console.log("[DEBUG] GitHub token found");
|
||||||
|
|
||||||
const owner = "anthropics";
|
const owner = "anthropics";
|
||||||
const repo = "claude-code";
|
const repo = "claude-code";
|
||||||
const dryRun = process.env.DRY_RUN !== "false";
|
const dryRun = process.env.DRY_RUN !== "false";
|
||||||
const daysBack = parseInt(process.env.DAYS_BACK || "90", 10);
|
const maxIssueNumber = parseInt(process.env.MAX_ISSUE_NUMBER || "4050", 10);
|
||||||
|
const minIssueNumber = parseInt(process.env.MIN_ISSUE_NUMBER || "1", 10);
|
||||||
|
|
||||||
console.log(`[DEBUG] Repository: ${owner}/${repo}`);
|
console.log(`[DEBUG] Repository: ${owner}/${repo}`);
|
||||||
console.log(`[DEBUG] Dry run mode: ${dryRun}`);
|
console.log(`[DEBUG] Dry run mode: ${dryRun}`);
|
||||||
console.log(`[DEBUG] Looking back ${daysBack} days`);
|
console.log(`[DEBUG] Looking at issues between #${minIssueNumber} and #${maxIssueNumber}`);
|
||||||
|
|
||||||
const cutoffDate = new Date();
|
console.log(`[DEBUG] Fetching issues between #${minIssueNumber} and #${maxIssueNumber}...`);
|
||||||
cutoffDate.setDate(cutoffDate.getDate() - daysBack);
|
|
||||||
|
|
||||||
console.log(`[DEBUG] Fetching issues created since ${cutoffDate.toISOString()}...`);
|
|
||||||
const allIssues: GitHubIssue[] = [];
|
const allIssues: GitHubIssue[] = [];
|
||||||
let page = 1;
|
let page = 1;
|
||||||
const perPage = 100;
|
const perPage = 100;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const pageIssues: GitHubIssue[] = await githubRequest(
|
const pageIssues: GitHubIssue[] = await githubRequest(
|
||||||
`/repos/${owner}/${repo}/issues?state=all&per_page=${perPage}&page=${page}&since=${cutoffDate.toISOString()}`,
|
`/repos/${owner}/${repo}/issues?state=all&per_page=${perPage}&page=${page}&sort=created&direction=desc`,
|
||||||
token
|
token
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pageIssues.length === 0) break;
|
if (pageIssues.length === 0) break;
|
||||||
|
|
||||||
allIssues.push(...pageIssues);
|
// Filter to only include issues within the specified range
|
||||||
|
const filteredIssues = pageIssues.filter(issue =>
|
||||||
|
issue.number >= minIssueNumber && issue.number < maxIssueNumber
|
||||||
|
);
|
||||||
|
allIssues.push(...filteredIssues);
|
||||||
|
|
||||||
|
// If the oldest issue in this page is still above our minimum, we need to continue
|
||||||
|
// but if the oldest issue is below our minimum, we can stop
|
||||||
|
const oldestIssueInPage = pageIssues[pageIssues.length - 1];
|
||||||
|
if (oldestIssueInPage && oldestIssueInPage.number >= maxIssueNumber) {
|
||||||
|
console.log(`[DEBUG] Oldest issue in page #${page} is #${oldestIssueInPage.number}, continuing...`);
|
||||||
|
} else if (oldestIssueInPage && oldestIssueInPage.number < minIssueNumber) {
|
||||||
|
console.log(`[DEBUG] Oldest issue in page #${page} is #${oldestIssueInPage.number}, below minimum, stopping`);
|
||||||
|
break;
|
||||||
|
} else if (filteredIssues.length === 0 && pageIssues.length > 0) {
|
||||||
|
console.log(`[DEBUG] No issues in page #${page} are in range #${minIssueNumber}-#${maxIssueNumber}, continuing...`);
|
||||||
|
}
|
||||||
|
|
||||||
page++;
|
page++;
|
||||||
|
|
||||||
// Safety limit to avoid infinite loops
|
// Safety limit to avoid infinite loops
|
||||||
if (page > 100) {
|
if (page > 200) {
|
||||||
console.log("[DEBUG] Reached page limit, stopping pagination");
|
console.log("[DEBUG] Reached page limit, stopping pagination");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[DEBUG] Found ${allIssues.length} issues from the last ${daysBack} days`);
|
console.log(`[DEBUG] Found ${allIssues.length} issues between #${minIssueNumber} and #${maxIssueNumber}`);
|
||||||
|
|
||||||
let processedCount = 0;
|
let processedCount = 0;
|
||||||
let candidateCount = 0;
|
let candidateCount = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user