Initial commit

This commit is contained in:
2026-03-09 00:14:40 -04:00
commit 099e5d3738
10 changed files with 460 additions and 0 deletions

117
bash/dot-bashrc Normal file
View File

@@ -0,0 +1,117 @@
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi

27
bash/dot-profile Normal file
View File

@@ -0,0 +1,27 @@
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.
# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi

162
claude/CLAUDE.md Normal file
View File

@@ -0,0 +1,162 @@
# Global Rules
- Do not start doing complicated things without the user's
explicit approval first.
- Do not try to be the project architect. The user is the
architect, you are the assistant.
- Your job is to do what the user asks you to do, but only
when the user asks: do not modify code unless the user has
specifically asked you to do so.
- Never check anything into git. Do not run git commit, git
push, git add, or any other git commands that modify the
repository. I will handle all git interactions myself.
- If a prompt ends with an ellipsis, it means the user has
more to type. In that case, only comment if you have
concerns.
## How Writing the API Docs helps you make the API better.
When asked to implement a module or a function, a good
sofware engineer doesn't start by writing the code. Instead,
you a write a block comment explaining the API to the
customer. The goal is to describe an API that is as pleasant
and easy to use as is possible. That's what you write: the
documentation for the greatest API ever. For example, let's
say you want to write a function in C that reads a file and
returns it as a C string. You write this:
```
/* Reads a file. Returns the content as a C string. */
```
Simple and easy to use. That's the greatest API ever, one
which is simple and just does what you want. So then you
write the code:
```
// Read a file. Returns a char* with the file content.
//
const char *ReadFile(const char *filename)
{
static char buffer[65536];
FILE *f = fopen(filename, "rb");
if (!f) return NULL;
size_t n = fread(buffer, 1, sizeof(buffer) - 1, f);
fclose(f);
if (n == sizeof(buffer) - 1) return NULL;
buffer[n] = '\0';
return buffer;
}
```
Then, after writing the code, you go back to the comment,
and you ask yourself: is this documentation truthful? Is
this really what the function does? In our example, it's
not. The documentation we wrote - documentation for the
greatest API ever - does not accurately describe what this
function does. Here's more accurate documentation:
```
/* Read a file. Returns a char* with the file content.
If the file is more than 65535 characters, returns
nullptr. Not thread-safe. */
```
Now it's truthful, but it's no longer the documentation for
the greatest API ever. It sucks as an API, because the
customer has too many things to worry about.
So now you have a struggle on your hands. You have to
figure out to make the code have a nicer API. So you
consider maybe using malloc for the buffer. That would get
rid of the 64k limit, and thread-safety issue. So, you go
back change the code to malloc a buffer. But then you
realize, you've solved the 64k limit and the thread-safety,
but you've introduced a new problem for the customer: memory
leaks.
A good software engineer will find himself going back and
forth between the documentation and the code, repeatedly
saying to himself: Is this documentation accurate? Could
it be simpler? Can I fix the code to make the API simpler?
A decent engineer will go back and forth several times.
## Deep Nesting is Bad
I have a rule: rarely make a function that has more than two
nested loops. Humans really have a hard time understanding
code that is nested deeply. So the rule is basically,
that this is OK:
```
if (x) {
while (y) {
...
}
}
```
That's two levels of nesting. But add another conditional
or loop inside the while, and it's too much.
Now, sometimes you need something like a namespace, which
adds another pair of braces: namespace { ... }. That
doesn't count as a level of nesting. The namespace increases
the indentation, but it's not increasing the code
complexity. Indentation isn't the problem. The problem is
that deeply nested loops and deeply nested conditionals are
hard to follow.
## Keeping Things Synchronized is Bad
Let's say I have an enum:
```
enum ShapeType { CIRCLE, SQUARE, TRIANGLE }
```
Then, somewhere else, in a completely different file,
I have this:
```
const char *ShapeString(ShapeType s) {
switch (shape) {
case CIRCLE: return "CIRCLE";
case SQUARE: return "SQUARE";
case TRIANGLE: return "TRIANGLE";
}
}
```
Now I have to keep these two synchronized. If I add another
shape, I have to add it in *two* places. Humans are
terrible at remembering that they have to update two places:
I honestly think AIs aren't any better. You can make this
a lot better if you put the 'ShapeString' function *right*
next to the enum. If you can put them right next to each
other, then anybody who edits the enum will also see that
they have to update the ShapeString function.
## A Recap of My Software Engineering Rules
1. Always write a block comment with the API docs before
writing a function or module. Make it the greatest API
ever: make it super easy-to-use.
2. After writing the API docs, write the code. Then,
begin a process of iteration in which you compare the
docs and the code, fixing both of them until they match,
but always prioritizing fixing the code to make the API
simpler, and not settling for documenting something that's
hard to use.
3. In functions, keep the nesting level of loops and
conditionals 2 deep or less.
4. Don't create a situation where you have to keep two
things synchronized, *especially* if the two things
are in separate files.

66
claude/settings.json Executable file
View File

@@ -0,0 +1,66 @@
{
"env": {
"CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION": "false"
},
"permissions": {
"allow": [
"Read",
"Read(~/*)",
"Glob(~/*)",
"Grep(~/*)",
"WebFetch",
"WebSearch",
"Bash(grep:*)",
"Bash(ls:*)",
"Bash(find:*)",
"Bash(code --goto:*)",
"Bash(git check-ignore:*)",
"Bash(head:*)",
"Bash(tail:*)",
"Bash(python3:*)",
"Bash(wc:*)",
"Bash(file:*)",
"Bash(stat:*)",
"Bash(du:*)",
"Bash(df:*)",
"Bash(which:*)",
"Bash(whereis:*)",
"Bash(type:*)",
"Bash(env:*)",
"Bash(printenv:*)",
"Bash(echo:*)",
"Bash(diff:*)",
"Bash(sort:*)",
"Bash(uniq:*)",
"Bash(tree:*)",
"Bash(git status:*)",
"Bash(git log:*)",
"Bash(git diff:*)",
"Bash(git show:*)"
],
"deny": [
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git push *)",
"Bash(git pull *)",
"Bash(git fetch *)",
"Bash(git merge *)",
"Bash(git rebase *)",
"Bash(git reset *)",
"Bash(git checkout *)",
"Bash(git switch *)",
"Bash(git branch *)",
"Bash(git stash *)",
"Bash(git cherry-pick *)",
"Bash(git revert *)",
"Bash(git tag *)",
"Bash(git clean *)",
"Bash(git restore *)",
"Bash(git rm *)",
"Bash(git mv *)",
"Bash(rm -rf *)"
],
"defaultMode": "acceptEdits"
},
"theme": "light"
}

1
emacs/dot-emacs Normal file
View File

@@ -0,0 +1 @@
(put 'erase-buffer 'disabled nil)

10
git/dot-gitconfig Normal file
View File

@@ -0,0 +1,10 @@
[filter "lfs"]
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
required = true
[user]
name = jyelon
email = jyelon@gmail.com
[credential]
helper = cache --timeout 43200

42
install.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
#
# Installs config files from this repo by creating symlinks.
# On first run, backs up originals to ~/.orig-config.
#
REPO_DIR="$HOME/jbashrc"
# The list of config files: "repo-relative-path:absolute-target"
FILES=(
"bash/dot-bashrc:$HOME/.bashrc"
"bash/dot-profile:$HOME/.profile"
"claude/CLAUDE.md:$HOME/.claude/CLAUDE.md"
"claude/settings.json:$HOME/.claude/settings.json"
"emacs/dot-emacs:$HOME/.emacs"
"git/dot-gitconfig:$HOME/.gitconfig"
"vscode/chatLanguageModels.json:$HOME/.config/Code/User/chatLanguageModels.json"
"vscode/keybindings.json:$HOME/.config/Code/User/keybindings.json"
"vscode/settings.json:$HOME/.config/Code/User/settings.json"
)
# Back up originals that haven't been backed up yet.
mkdir -p "$HOME/.orig-config"
for entry in "${FILES[@]}"; do
src_rel="${entry%%:*}"
target="${entry#*:}"
backup="$HOME/.orig-config/$src_rel"
if [ ! -e "$backup" ] && [ -e "$target" ] && [ ! -L "$target" ]; then
mkdir -p "$(dirname "$backup")"
cp "$target" "$backup"
echo "Backed up $target"
fi
done
# Create symlinks.
for entry in "${FILES[@]}"; do
src="$REPO_DIR/${entry%%:*}"
target="${entry#*:}"
mkdir -p "$(dirname "$target")"
ln -sf "$src" "$target"
echo "Linked $target -> $src"
done

View File

@@ -0,0 +1 @@
[]

23
vscode/keybindings.json Normal file
View File

@@ -0,0 +1,23 @@
// Place your key bindings in this file to override the defaults
[
{
"key": "ctrl+r",
"command": "-workbench.action.openRecent"
},
{
"key": "ctrl+r",
"command": "-workbench.action.terminal.runRecentCommand"
},
{
"key": "ctrl+r",
"command": "-workbench.action.quickOpenNavigateNextInRecentFilesPicker"
},
{
"key": "ctrl+r",
"command": "-workbench.action.terminal.chat.rerunRequest"
},
{
"key": "ctrl+r",
"command": "workbench.action.reloadWindow"
}
]

11
vscode/settings.json Normal file
View File

@@ -0,0 +1,11 @@
{
"editor.inlayHints.enabled": "off",
"editor.hover.enabled": "off",
"claudeCode.preferredLocation": "panel",
"workbench.editor.empty.hint": "hidden",
"editor.rulers": [
60,
78
],
"explorer.confirmDelete": false
}