feat: Add Colin's set of claude settings and my settings
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
These are Nicholas's personal preferences for Claude (and other coding agents). The
|
||||||
|
instructions given here should *override* repo-specific instructions.
|
||||||
|
|
||||||
|
# jj VCS Workflow
|
||||||
|
- Use jj (not git/gt) for all VCS operations. (If no .jj directory exists, then you may fall back to git.)
|
||||||
|
- Read @workflows/jj.md for details.
|
||||||
|
|
||||||
|
# PRs
|
||||||
|
- Read @workflows/prs.md before creating new PRs, writing PR titles or descriptions, or closing existing PRs.
|
||||||
|
|
||||||
|
# Writing comments/PRs/tickets as Claude via the user's accounts
|
||||||
|
- Read @workflows/writing-as-claude.md before writing any text that will appear with the user's identity (e.g. GitHub, Linear, Slack).
|
||||||
|
|
||||||
|
# Coding guidelines
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
- Comments should only describe the final code's intent, not the decisions/changes that produced it.
|
||||||
|
- Read @coding-guidelines/comments.md before writing code in any language.
|
||||||
|
|
||||||
|
## Bash / shell scripts
|
||||||
|
- Read @coding-guidelines/bash.md before writing any standalone Bash or shell scripts.
|
||||||
|
|
||||||
|
# Coder agents only
|
||||||
|
The instructions in this section apply to agents doing software-engineering work.
|
||||||
|
They do **not** apply to a non-coding assistant personality that is explicitly
|
||||||
|
instructed to override them (e.g. a PM assistant).
|
||||||
|
|
||||||
|
## Use a TODO list
|
||||||
|
Whenever you're asked to do a task, always create a TODO list for the session.
|
||||||
|
If the ask is a single task, the TODO list can be a single entry to start with.
|
||||||
|
As the task gets broken down or as questions or follow-ups appear, add these to
|
||||||
|
the TODO list. This makes sure you never forget to address some follow-up later.
|
||||||
|
|
||||||
|
## Be proactive by default
|
||||||
|
Unless otherwise specified, you should create draft PR(s) for the work you did and then
|
||||||
|
monitor them (using the babysit-stack skill) until they are merged. Once they are passing
|
||||||
|
CI and initial review comments are resolved, the monitoring cadence can slow to once per
|
||||||
|
hour, but you should continue to check for new review comments periodically until told to
|
||||||
|
stop (or the PR merges).
|
||||||
|
|
||||||
|
## Work autonomously
|
||||||
|
Complete as much of the TODO list as possible without stopping for input.
|
||||||
|
For things that need Nicholas's input, make sure they are captured by a new or existing TODO
|
||||||
|
item, then make progress on other things before stopping. If a decision is
|
||||||
|
saftey-critical or really blocks all remaining progress, then it's okay to stop. But if
|
||||||
|
it's possible to use a placeholder or reasonable default and continue, do so (making sure
|
||||||
|
to leave a TODO item to confirm/revisit later). If no more progress can be made on the TODO
|
||||||
|
items, default to babysitting the current stack.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Coding guidelines for Bash / shell scripts
|
||||||
|
|
||||||
|
- Write all shell scripts for modern Bash — use Bashisms like `&>` and `[[ ... ]]` whenever possible.
|
||||||
|
|
||||||
|
## Avoid "Bash strict mode"
|
||||||
|
- By default, don't set any options at the top of the script.
|
||||||
|
- Add `set -u` globally if the script becomes complex enough (rough guideline: more than 4 variables).
|
||||||
|
- Use `set -o pipefail` only locally when needed.
|
||||||
|
|
||||||
|
## Executable scripts
|
||||||
|
If a script is directly executable, it should:
|
||||||
|
- have no file extension
|
||||||
|
- use `#!/usr/bin/env bash`
|
||||||
|
|
||||||
|
If a script is not directly executable, it should have a ".bash" file extension and no shebang line (when possible).
|
||||||
|
|
||||||
|
## Style guide
|
||||||
|
|
||||||
|
- Avoid spaces after redirection operators: `>/dev/null`, `2>&1`, `&>"$logfile"`
|
||||||
|
- When logging to stderr, prefer to place the `>&2` redirection immediately after the command name: `printf >&2 %s "Blah blah..."`
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Coding guidelines for comments (in any language)
|
||||||
|
|
||||||
|
Comments describe the final code's intent, invariants, or non-obvious constraints — as if the code had been written that way from the start. They are read by people who have no idea what the PR or commit looked like.
|
||||||
|
|
||||||
|
Don't reference any of these in a comment:
|
||||||
|
- What the previous version of the code did ("was previously X", "used to do Y")
|
||||||
|
- What an alternative approach would do ("instead of Promise.all", "rather than recursion")
|
||||||
|
- What a reviewer suggested or asked
|
||||||
|
- Why a particular change was made (that belongs in the commit message or PR description)
|
||||||
|
|
||||||
|
Litmus test: would this comment read as natural rationale to someone who has never seen the PR, commit history, or review thread? If not, rewrite or delete it.
|
||||||
|
|
||||||
|
This applies to all comments — new code, code added in response to review, refactors, anything. The temptation is highest when addressing review feedback: the change is fresh, the reasoning is loaded, and it's tempting to leave a paper trail in the source. Don't.
|
||||||
|
|
||||||
|
Comments should also be concise. Edit them aggressively to remove unnecessary explanations and details that can be easily determined by reading the code itself. Prefer one comment at the top of a function/class over scattered inline notes, unless a specific line is genuinely surprising.
|
||||||
|
|
||||||
|
If a comment clarifies the meaning of a name in the code (a variable, function, parameter, etc.), then, if possible, that name should be changed to be clear enough to eliminate the need for the comment.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Self-review instructions
|
||||||
|
|
||||||
|
The Stop hook points here so I do a focused review pass over the code I changed
|
||||||
|
before finishing. Read every added/changed line in the diff and fix anything that
|
||||||
|
violates the rules below.
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
Ensure all comments adhere to the guidelines in coding-guidelines/comments.md.
|
||||||
|
|
||||||
|
## Bash / shell scripts
|
||||||
|
|
||||||
|
Ensure all bash / shell scripts adhere to the guidelines in coding-guidelines/bash.md.
|
||||||
Executable
+25
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Stop hook: prompt one self-review pass over changed code against Nicholas's
|
||||||
|
# guidelines before finishing. Blocks the stop once per distinct working-copy diff
|
||||||
|
# (fingerprint dedup), so each set of changes earns exactly one review and an
|
||||||
|
# unchanged tree never loops.
|
||||||
|
if [[ -e .no-review-hook ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Working-copy diff: jj if this is a jj repo, else git.
|
||||||
|
diff=$(jj diff --git 2>/dev/null)
|
||||||
|
[[ -z "$diff" ]] && diff=$(git diff HEAD 2>/dev/null)
|
||||||
|
[[ -n "$diff" ]] || exit 0
|
||||||
|
|
||||||
|
# Block only once per distinct diff: re-blocks when the diff changes (e.g. after an
|
||||||
|
# edit made during the review) and converges once it stops changing.
|
||||||
|
fp=$(printf '%s' "$diff" | sha1sum | cut -d" " -f1)
|
||||||
|
key=$(printf '%s' "$PWD" | sha1sum | cut -d" " -f1)
|
||||||
|
statefile="${TMPDIR:-/tmp}/claude-code-review-$key"
|
||||||
|
[[ -f "$statefile" && "$(cat "$statefile" 2>/dev/null)" == "$fp" ]] && exit 0
|
||||||
|
printf '%s' "$fp" >"$statefile"
|
||||||
|
|
||||||
|
reason="Before stopping, do a review pass over the code you changed this session, per the guidelines in ~/.claude/coding-guidelines/review.md. Read that file, then re-read the added/changed lines and fix any violations. If it already complies, say so briefly and stop."
|
||||||
|
|
||||||
|
jq -n --arg r "$reason" '{decision: "block", reason: $r}'
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
||||||
|
"env": {
|
||||||
|
"CLAUDE_CODE_USE_BEDROCK": "1",
|
||||||
|
"CLAUDE_CODE_ENABLE_AUTO_MODE": "1",
|
||||||
|
"AWS_REGION": "us-west-1",
|
||||||
|
"AWS_PROFILE": "default",
|
||||||
|
"ANTHROPIC_DEFAULT_SONNET_MODEL": "us.anthropic.claude-sonnet-5",
|
||||||
|
"ANTHROPIC_DEFAULT_OPUS_MODEL": "us.anthropic.claude-opus-5",
|
||||||
|
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "us.anthropic.claude-haiku-5"
|
||||||
|
},
|
||||||
|
"model": "opus",
|
||||||
|
"effortLevel": "high",
|
||||||
|
"skipDangerousModePermissionPrompt": true,
|
||||||
|
"skipWorkflowUsageWarning": true,
|
||||||
|
"includeCoAuthoredBy": false,
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(gh *)",
|
||||||
|
"Fetch(*)",
|
||||||
|
"mcp__claude_ai_Linear__get_issue",
|
||||||
|
"mcp__claude_ai_Linear__list_comments",
|
||||||
|
"mcp__claude_ai_Linear__save_comment",
|
||||||
|
"mcp__claude_ai_Linear__save_issue",
|
||||||
|
"mcp__claude_ai_Linear__save_project"
|
||||||
|
],
|
||||||
|
"deny": [
|
||||||
|
"Bash(gt *)"
|
||||||
|
],
|
||||||
|
"defaultMode": "auto"
|
||||||
|
},
|
||||||
|
"skillOverrides": {
|
||||||
|
"address-reviewer-feedback": "off",
|
||||||
|
"link-stack-to-linear": "off",
|
||||||
|
"monitor-pr": "off",
|
||||||
|
"new-pr": "off",
|
||||||
|
"new-worktree": "off",
|
||||||
|
"repair-ci-failures": "off",
|
||||||
|
"resolve-merge-conflicts": "off"
|
||||||
|
},
|
||||||
|
"awaySummaryEnabled": false,
|
||||||
|
"tui": "fullscreen",
|
||||||
|
"theme": "dark-ansi",
|
||||||
|
"preferredNotifChannel": "terminal_bell",
|
||||||
|
"skipAutoPermissionPrompt": true,
|
||||||
|
"useAutoModeDuringPlan": true
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
name: babysit-stack
|
||||||
|
description: Watch a stack of PRs, addressing test failures and responding to comments, until the stack is fully green.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Babysit Stack
|
||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
- Accept input as a jj revset. If not given, use `stack`.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
In a loop, do the following:
|
||||||
|
|
||||||
|
1. Compare each local commit message with the corresponding PR's title & description. If any information has been added to the local commit message, determine whether it belongs in the PR description (following the PR description guidance) — if so, add it there. Then, reconcile the PR's title with the commit's summary line (following the PR title guidance). Finally, reduce the commit message to the summary line only (this makes it clear that the PR description is the source of truth) plus the PR number in parentheses "(#12345)".
|
||||||
|
|
||||||
|
2. If any of the PRs have not already had Claude review requested, comment with "@claude review" to request it.
|
||||||
|
|
||||||
|
3. Use the handle-pr-feedback skill to handle comments on the PRs in the stack.
|
||||||
|
|
||||||
|
4. Check CI for each PR in the stack. Consider only the most recent run per check. If the `require-tests-pre-merge` job (`braid` repo only) has a failure, add the `pr/force-ci` label to the PR to resolve (and move to the next PR for now since adding the label will trigger tests to run, which will take a while). If a job is failing due to a missing ticket number in the PR title, leave it failing — there is a separate automated job which will eventually link a ticket.
|
||||||
|
|
||||||
|
5. If there are legitimate failures, investigate and fix.
|
||||||
|
|
||||||
|
6. If any changes were made in the earlier steps, push the changes using `jfd` (Graphite repos) or `jj git push -c stack` (non-Graphite repos).
|
||||||
|
|
||||||
|
7. Exit when: no new unhandled review comments and CI jobs have succeeded on all the PRs.
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
name: handle-pr-feedback
|
||||||
|
description: Address feedback from reviewers for a set of commits by fetching comments from GitHub, making changes, and writing a list of the changes made.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Handle PR Feedback
|
||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
- Accept input as a jj revset. If not given, use `stack`.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
Starting at the root commit of the revset, do the following:
|
||||||
|
|
||||||
|
1. Use the jj bookmark for the current commit (`jj log -r <id> --no-graph -T 'local_bookmarks.map(|b| b.name())'`) to look up the corresponding GitHub PR: `gh pr view <bookmark>`
|
||||||
|
|
||||||
|
2. Build a comment ledger with: `change_id`, `branch`, `pr_number`, `comment_url`, `author`, `file_line`, `summary`, `action_type`, `status`, and `notes`. Give this a heading with the commit's change ID and branch name, and append it to the file: `<repo>/scratch/handle-pr-feedback-<session>.md`.
|
||||||
|
|
||||||
|
3. Build context:
|
||||||
|
- Read nearby code and comments.
|
||||||
|
- Read surrounding commits in the stack and note where each concern is most logically fixed.
|
||||||
|
- Group comments that describe the same root issue and resolve them together.
|
||||||
|
|
||||||
|
3. Choose an action for each comment (and record it in the ledger):
|
||||||
|
- `fix`: change code/tests/docs, summarize what was changed.
|
||||||
|
- `comment`: leave a comment explaining why the review comment doesn't need to be addressed or pointing to a different commit where the issue is resolved.
|
||||||
|
- `ignore`: do nothing (e.g. because the comment is stale or marked as resolved).
|
||||||
|
|
||||||
|
4. Implement fixes holistically:
|
||||||
|
- Apply fixes by concern area, not comment order, to avoid conflicting patches.
|
||||||
|
- Keep changes minimal and local unless the comment requires broader refactor.
|
||||||
|
- For stack-wide concerns, place the fix in the lowest PR where it logically belongs.
|
||||||
|
- Summarize changes made in the ledger.
|
||||||
|
|
||||||
|
5. Validate:
|
||||||
|
- If code changes were made, use `$verify-changes` for tests, lint, typechecks, and build steps.
|
||||||
|
- If no code changes are needed, validate by tracing the exact code path and checking current behavior against reviewer intent.
|
||||||
|
|
||||||
|
6. Mark comments resolved:
|
||||||
|
- For each comment that was resolved by making a code change, mark the comment resolved (no need to leave a reply).
|
||||||
|
- For each comment that was resolved by replying to it, mark the comment resolved.
|
||||||
|
|
||||||
|
7. Final pass:
|
||||||
|
- Confirm every ledger row is `addressed`.
|
||||||
|
- If code changes were made, confirm `$verify-changes` succeeded or clearly report any blocker.
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
- Return a concise summary of the actions taken and point to the ledger file for details.
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
Use `jj` instead of `git` or `gt` for all version control operations.
|
||||||
|
|
||||||
|
Custom revsets:
|
||||||
|
- `stack` represents all the commits in the current stack (works even when the current commit is an empty child created by `jj new`)
|
||||||
|
|
||||||
|
Other key commands:
|
||||||
|
- `jj squash --from <id> --into <id> -- <paths>` to move whole files between commits
|
||||||
|
- `jj split -r <id> -m <message> -- <paths>` to split a commit (selected files stay, rest go to new child)
|
||||||
|
- `jj describe <id> -m <message>` to rename a commit
|
||||||
|
- `jj diff -r <id> -- <path>` to see a specific file's diff in a commit
|
||||||
|
- `jj diff -r <id> --name-only` to list changed files
|
||||||
|
- `jj log -r stack` to see the current stack (stack is a custom revset described above)
|
||||||
|
|
||||||
|
Rebasing and conflicts:
|
||||||
|
- jj automatically rebases descendants when editing earlier commits. Expect cascading conflicts after modifying earlier commits, and resolve them working down the stack.
|
||||||
|
- Use the `new`, ..., `squash` sequence when resolving conflicts.
|
||||||
|
|
||||||
|
Things to avoid:
|
||||||
|
- Avoid `jj absorb` -- in a complex stack, it's likely to lose changes or put things into the wrong commits.
|
||||||
|
- Avoid `jj edit <id>` -- always prefer to open a new commit (`jj new <id>`) first.
|
||||||
|
|
||||||
|
## Editing files
|
||||||
|
|
||||||
|
**Before editing any files, always consider which new or existing commit the edits should be part of!**
|
||||||
|
|
||||||
|
Edits should always be made in a new commit, and then squashed once they are finalized:
|
||||||
|
- `jj new <id>` to open a new child of an existing commit
|
||||||
|
- make the changes
|
||||||
|
- `jj squash --into <id> --use-destination-message` to squash into the existing commit
|
||||||
|
|
||||||
|
If the intent is to *add* a new commit rather than edit an existing one:
|
||||||
|
- use `jj new <id>` where <id> is the top commit of the stack
|
||||||
|
- or use `jj new --insert-before <id>` or `jj new --insert-after <id>` to insert a new commit mid-stack
|
||||||
|
|
||||||
|
When squashing or splitting, make sure that bookmarks stay attached to their original commits (because bookmarks map to PRs).
|
||||||
|
|
||||||
|
## Pushing changes to GitHub/Graphite
|
||||||
|
|
||||||
|
Verify the stack first: Before pushing changes, always verify that there are no lingering temporary commits included in the `stack` revset. New commits that were intentionally introduced (intended to become new PRs) are fine. If there are lingering temporary commits, **do not push**; either resolve or get help from the user.
|
||||||
|
|
||||||
|
After verifying the stack:
|
||||||
|
- If the repo uses Graphite: use `jfd` to push to Graphite. This submits all commits in the `stack` revset as a 1:1 mapping of PRs to commits.
|
||||||
|
- If the repo does not use Graphite: use `jj git push -c stack` to push all commits in the stack (this creates an automatically-named branch for each commit). Then use `gh` to create a PR for each branch.
|
||||||
|
|
||||||
|
To push a fresh commit (e.g. to retrigger CI), use `jj metaedit --force-rewrite <id>` to get a fresh commit hash, then push normally.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# PR Titles
|
||||||
|
|
||||||
|
Sample PR title: `[SG-100] [wip] api: Move feature-flags into a separate package`
|
||||||
|
|
||||||
|
1. Linked ticket number, if the ticket is known. If the ticket isn't known, just omit the ticket number. Never ask the user for ticket numbers. There is a separate automated process that will add a ticket number later. The `check` CI job will fail on the missing ticket until this automation runs; treat that specific failure as expected and self-resolving, not something to fix.
|
||||||
|
2. Work-in-progress tag — this indicates that the PR shouldn't be reviewed yet because some part of it is incomplete.
|
||||||
|
3. Commit title (using standard Git conventions)
|
||||||
|
|
||||||
|
# Draft status
|
||||||
|
|
||||||
|
Always create PRs as drafts. Never automatically move PRs out of draft status. Nicholas will promote PRs out of draft status when he is ready for them to be reviewed by others.
|
||||||
|
|
||||||
|
# PR Descriptions
|
||||||
|
|
||||||
|
PR descriptions always follow this template:
|
||||||
|
|
||||||
|
```
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
[overview here]
|
||||||
|
|
||||||
|
## Customer visible changes
|
||||||
|
|
||||||
|
N/A
|
||||||
|
|
||||||
|
## How did you test these changes?
|
||||||
|
|
||||||
|
[testing steps here]
|
||||||
|
```
|
||||||
|
|
||||||
|
The default template that Graphite uses for new PRs should be ignored entirely — don't keep the placeholders or the checkboxes in the testing section.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
The overview should be terse and should not explain implementation details except at a *very* high level (anything lower level should be omitted because it can be determined by looking at the code itself). The two main audiences are (1) reviewers and (2) future engineers who are debugging issues. The primary goal is to explain the *why* of the change. What's the goal/benefit? What bug is being fixed? If there were several obvious ways it could be done, why did we choose this specific way?
|
||||||
|
|
||||||
|
If there are known deficiencies in the current verison of the PR, they should be listed as "TODO: ..." at the end of the Overview.
|
||||||
|
|
||||||
|
## How did you test
|
||||||
|
The testing steps should be concise but precise. "All changes are covered by unit tests" can be sufficient if it's true. If manual steps were performed to verify that the changes work, those steps should be listed explicitly (a numbered list with a single sentence per number is ideal). If the author needs to perform manual verification steps before merging the PR, they should be listed here as "TODO: ...".
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
Always identify yourself explicitly as Claude when writing things that will appear with the user's identity:
|
||||||
|
- PR titles: No identification required — the "Co-Authored-By" line in the commit message is sufficient.
|
||||||
|
- PR comments: Start the comment with "[claude]:"
|
||||||
|
- Linear tickets: Start the description with "[claude]:"
|
||||||
|
- Linear comments: Start the comment with "[claude]:"
|
||||||
|
- Commit messages: End the commit message with "Co-Authored-By: [model]"
|
||||||
|
|
||||||
|
When you are acting on direct instruction from the user, include that as justification (e.g. "[claude]: closing this at Nicholas's request").
|
||||||
|
|
||||||
|
Don't nitpick errors in other people's comments when the intent is clear. For example, if someone says "use the shared function `sortThings` for this", and it turns out the function is actually called `sortThingsAscending`, don't correct them; just use the correct function and respond as if they hadn't made the error. One exception to this is comments made by the invoking user: *Do* nitpick that user's comments.
|
||||||
Reference in New Issue
Block a user