Compare commits
10 Commits
18766caffd
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 8934a1e71f | |||
| 86f9c8126d | |||
| 243b378712 | |||
| 81f3a2ae5e | |||
| 4b234990af | |||
| e6b48bf14b | |||
| b324ce9e98 | |||
| e9fb3398fc | |||
| 444d04b0cb | |||
| 20adde9cdd |
@@ -42,3 +42,4 @@ ENV/
|
|||||||
# OS
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.python-version
|
.python-version
|
||||||
|
ai-tools/claude/settings.json
|
||||||
|
|||||||
@@ -8,25 +8,13 @@ Scripts and tools to set up and manage the terminal environment across systems.
|
|||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Run this tool from the checked-out repo. Do **not** install it with `uv tool install`,
|
|
||||||
because `cli-tools install helpers` symlinks shell files from `scripts/`.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /path/to/cli-tools
|
git clone <repo> && cd cli-tools
|
||||||
uv run cli-tools --help
|
source init.sh # installs uv if needed, syncs deps, activates venv
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cli-tools install bootstrap # install everything (first-time setup)
|
cli-tools install --help # show available commands
|
||||||
cli-tools install apt-packages # git, curl, ripgrep, fd, btop, tldr, ...
|
|
||||||
cli-tools install uv # uv package manager
|
|
||||||
cli-tools install fzf # fzf + bat
|
|
||||||
cli-tools install zoxide # zoxide (z navigation)
|
|
||||||
cli-tools install eza # modern ls replacement
|
|
||||||
cli-tools install lazygit # terminal UI for git
|
|
||||||
cli-tools install docker # Docker + add user to group
|
|
||||||
cli-tools install claude # Claude Code
|
|
||||||
cli-tools install helpers # symlink bash_helpers.sh + aliases.sh into ~
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"Bash(uv sync:*)",
|
|
||||||
"Bash(uv run pytest:*)",
|
|
||||||
"Bash(inv lint:*)",
|
|
||||||
"Bash(inv test:*)"
|
|
||||||
],
|
|
||||||
"deny": [
|
|
||||||
"Read(./.venv/**)",
|
|
||||||
"Read(./__pycache__/**)",
|
|
||||||
"Read(./.env*)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"skipDangerousModePermissionPrompt": true
|
|
||||||
}
|
|
||||||
@@ -1,17 +1,16 @@
|
|||||||
FROM python:3.13
|
FROM python:3.13
|
||||||
|
|
||||||
ARG USERNAME=dev
|
|
||||||
ARG UID=1000
|
ARG UID=1000
|
||||||
ARG GID=1000
|
ARG GID=1000
|
||||||
|
|
||||||
# Create user with sudo support
|
# Create user with sudo support
|
||||||
RUN groupadd --gid $GID $USERNAME \
|
RUN groupadd --gid $GID dev \
|
||||||
&& useradd --uid $UID --gid $GID -m $USERNAME \
|
&& useradd --uid $UID --gid $GID -m dev \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install -y sudo curl gnupg \
|
&& apt-get install -y sudo curl gnupg \
|
||||||
&& echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME \
|
&& echo "dev ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/dev \
|
||||||
&& chmod 0440 /etc/sudoers.d/$USERNAME \
|
&& chmod 0440 /etc/sudoers.d/dev \
|
||||||
&& usermod -a -G dialout $USERNAME
|
&& usermod -a -G dialout dev
|
||||||
|
|
||||||
# Install system packages
|
# Install system packages
|
||||||
RUN apt-get install -y \
|
RUN apt-get install -y \
|
||||||
@@ -61,26 +60,29 @@ ENV LANG=en_US.UTF-8
|
|||||||
ENV LC_ALL=en_US.UTF-8
|
ENV LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
# Create user directories with proper ownership
|
# Create user directories with proper ownership
|
||||||
RUN mkdir -p /home/${USERNAME}/.vscode-server/extensions \
|
RUN mkdir -p /home/dev/.vscode-server/extensions \
|
||||||
&& mkdir -p /home/${USERNAME}/.local/bin \
|
&& mkdir -p /home/dev/.local/bin \
|
||||||
&& mkdir -p /home/${USERNAME}/.claude \
|
&& mkdir -p /home/dev/.claude \
|
||||||
&& mkdir -p /workspace \
|
&& mkdir -p /workspace \
|
||||||
&& mkdir -p /workspace/.venv \
|
&& chown -R dev:dev /home/dev/.vscode-server \
|
||||||
&& chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.vscode-server \
|
&& chown -R dev:dev /home/dev/.local \
|
||||||
&& chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.local \
|
&& chown -R dev:dev /home/dev/.claude \
|
||||||
&& chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.claude \
|
&& chown -R dev:dev /workspace
|
||||||
&& chown -R ${USERNAME}:${USERNAME} /workspace
|
|
||||||
|
|
||||||
VOLUME /workspace/.venv
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Switch to non-root user (only once, for the rest of the build)
|
# Switch to non-root user (only once, for the rest of the build)
|
||||||
USER ${USERNAME}
|
USER dev
|
||||||
WORKDIR /home/${USERNAME}
|
|
||||||
|
# create ssh keys
|
||||||
|
RUN ssh-keygen -q -t ed25519 -N "" -f /home/dev/.ssh/id_ed25519 && \
|
||||||
|
printf "Host *\n StrictHostKeyChecking accept-new\n" > /home/dev/.ssh/config && \
|
||||||
|
chmod 0700 /home/dev/.ssh && \
|
||||||
|
chmod 0600 /home/dev/.ssh/id_ed25519 /home/dev/.ssh/config && \
|
||||||
|
chmod 0644 /home/dev/.ssh/id_ed25519.pub
|
||||||
|
|
||||||
|
WORKDIR /home/dev
|
||||||
|
|
||||||
# Add local bin to PATH
|
# Add local bin to PATH
|
||||||
ENV PATH="/home/${USERNAME}/.local/bin:${PATH}"
|
ENV PATH="/home/dev/.local/bin:${PATH}"
|
||||||
|
|
||||||
# Install uv
|
# Install uv
|
||||||
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
@@ -96,9 +98,9 @@ RUN curl -fsSL https://gh.io/copilot-install | bash
|
|||||||
RUN curl -fsSL https://claude.ai/install.sh | bash
|
RUN curl -fsSL https://claude.ai/install.sh | bash
|
||||||
|
|
||||||
# User config (most frequently changed)
|
# User config (most frequently changed)
|
||||||
COPY --chown=${USERNAME}:${USERNAME} CLAUDE.md /home/${USERNAME}/.claude/CLAUDE.md
|
COPY --chown=dev:dev CLAUDE.md /home/dev/.claude/CLAUDE.md
|
||||||
COPY --chown=${USERNAME}:${USERNAME} aliases.sh /home/${USERNAME}/.aliases.sh
|
COPY --chown=dev:dev aliases.sh /home/dev/.aliases.sh
|
||||||
COPY --chown=${USERNAME}:${USERNAME} bash_helpers.sh /home/${USERNAME}/.bash_helpers.sh
|
COPY --chown=dev:dev bash_helpers.sh /home/dev/.bash_helpers.sh
|
||||||
|
|
||||||
# Customize bash prompt
|
# Customize bash prompt
|
||||||
RUN echo 'export PS1="${PROJECT_NAME:+\[\e[35m\][$PROJECT_NAME]\[\e[m\] }🐍 \[\e[33m\]\W\[\e[m\] \[\033[1;36m\]# \[\033[0m\]"' >> ~/.bashrc \
|
RUN echo 'export PS1="${PROJECT_NAME:+\[\e[35m\][$PROJECT_NAME]\[\e[m\] }🐍 \[\e[33m\]\W\[\e[m\] \[\033[1;36m\]# \[\033[0m\]"' >> ~/.bashrc \
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Must be sourced: source init.sh
|
||||||
|
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
echo "Error: run as 'source init.sh' or '. init.sh'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
uv sync
|
||||||
|
source .venv/bin/activate
|
||||||
@@ -6,7 +6,6 @@ alias uvs="uv sync --all-extras"
|
|||||||
alias clip='xclip -selection clipboard'
|
alias clip='xclip -selection clipboard'
|
||||||
alias open_ports='sudo ss -tulwn | grep LISTEN'
|
alias open_ports='sudo ss -tulwn | grep LISTEN'
|
||||||
alias bat='batcat'
|
alias bat='batcat'
|
||||||
alias cat='batcat'
|
|
||||||
alias claude-allow="claude --dangerously-skip-permissions"
|
alias claude-allow="claude --dangerously-skip-permissions"
|
||||||
alias reload='source ~/.bashrc'
|
alias reload='source ~/.bashrc'
|
||||||
alias ls='eza'
|
alias ls='eza'
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"""Docker image commands."""
|
"""Docker image commands."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
import typer
|
import typer
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ app = typer.Typer(help="Build and manage Docker images.", no_args_is_help=True)
|
|||||||
|
|
||||||
DOCKER_IMAGE = "python-dev"
|
DOCKER_IMAGE = "python-dev"
|
||||||
DOCKER_DIR = "docker/python-dev"
|
DOCKER_DIR = "docker/python-dev"
|
||||||
|
DOCKERHUB_IMAGE = "roxauto/python-dev"
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
@@ -30,3 +32,20 @@ def build(
|
|||||||
f"{'--no-cache ' if no_cache else ''}"
|
f"{'--no-cache ' if no_cache else ''}"
|
||||||
f"--network=host {DOCKER_DIR}",
|
f"--network=host {DOCKER_DIR}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def push(tag: str = typer.Option("latest", help="Image tag.")):
|
||||||
|
"""Tag and push the python-dev image to DockerHub."""
|
||||||
|
token = os.environ.get("DOCKERHUB_TOKEN")
|
||||||
|
if not token:
|
||||||
|
typer.echo("DOCKERHUB_TOKEN env variable is not set.", err=True)
|
||||||
|
raise typer.Exit(1)
|
||||||
|
subprocess.run(
|
||||||
|
["docker", "login", "-u", "roxauto", "--password-stdin"],
|
||||||
|
input=token,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
run(f"docker tag {DOCKER_IMAGE}:{tag} {DOCKERHUB_IMAGE}:{tag}")
|
||||||
|
run(f"docker push {DOCKERHUB_IMAGE}:{tag}")
|
||||||
|
|||||||
+32
-13
@@ -21,9 +21,35 @@ APT_PACKAGES = [
|
|||||||
"ripgrep",
|
"ripgrep",
|
||||||
"fd-find",
|
"fd-find",
|
||||||
"btop",
|
"btop",
|
||||||
"tldr",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
PYTHON_TOOLS = [
|
||||||
|
"cruft",
|
||||||
|
"invoke",
|
||||||
|
]
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def core():
|
||||||
|
"""Install essential tools."""
|
||||||
|
apt_packages()
|
||||||
|
docker()
|
||||||
|
uv()
|
||||||
|
uv_tools()
|
||||||
|
fzf()
|
||||||
|
zoxide()
|
||||||
|
lazygit()
|
||||||
|
eza()
|
||||||
|
helpers()
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def ai_tools():
|
||||||
|
"""Install AI tools and configure skills."""
|
||||||
|
claude()
|
||||||
|
copilot()
|
||||||
|
ai_skills()
|
||||||
|
ccusage()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def claude():
|
def claude():
|
||||||
@@ -60,6 +86,11 @@ def uv():
|
|||||||
"""Install uv for the current user."""
|
"""Install uv for the current user."""
|
||||||
run("test -f ~/.local/bin/uv || curl -LsSf https://astral.sh/uv/install.sh | sh")
|
run("test -f ~/.local/bin/uv || curl -LsSf https://astral.sh/uv/install.sh | sh")
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def uv_tools():
|
||||||
|
"""Install Python tools using uv."""
|
||||||
|
for tool in PYTHON_TOOLS:
|
||||||
|
run(f"uv tool install --force {tool}")
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def ccusage():
|
def ccusage():
|
||||||
@@ -176,15 +207,3 @@ def ai_skills():
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
|
||||||
def bootstrap():
|
|
||||||
"""Install all base tools."""
|
|
||||||
apt_packages()
|
|
||||||
docker()
|
|
||||||
uv()
|
|
||||||
claude()
|
|
||||||
fzf()
|
|
||||||
zoxide()
|
|
||||||
lazygit()
|
|
||||||
eza()
|
|
||||||
ai_skills()
|
|
||||||
|
|||||||
Reference in New Issue
Block a user