Compare commits

...

8 Commits

Author SHA1 Message Date
Jev 8934a1e71f use standard cat 2026-05-04 11:57:13 +02:00
Jev 86f9c8126d don't mount venv 2026-05-04 11:57:00 +02:00
Jev 243b378712 feat: update Dockerfile to use fixed user and enhance directory ownership; add push command to docker.py for DockerHub integration 2026-04-28 17:25:46 +02:00
Jev Kuznetsov 81f3a2ae5e refactor: update installation commands in README for clarity 2026-04-23 13:01:49 +02:00
Jev Kuznetsov 4b234990af add init 2026-04-23 13:00:30 +02:00
Jev Kuznetsov e6b48bf14b feat: add uv_tools command to install Python tools using uv 2026-04-23 11:08:40 +02:00
Jev Kuznetsov b324ce9e98 chore: add ai-tools/claude/settings.json to .gitignore 2026-04-23 10:58:06 +02:00
Jev Kuznetsov e9fb3398fc reorder 2026-04-23 09:07:30 +02:00
7 changed files with 91 additions and 59 deletions
+1
View File
@@ -42,3 +42,4 @@ ENV/
# OS
.DS_Store
.python-version
ai-tools/claude/settings.json
+3 -15
View File
@@ -8,25 +8,13 @@ Scripts and tools to set up and manage the terminal environment across systems.
## 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
cd /path/to/cli-tools
uv run cli-tools --help
git clone <repo> && cd cli-tools
source init.sh # installs uv if needed, syncs deps, activates venv
```
```bash
cli-tools install bootstrap # install everything (first-time setup)
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 ~
cli-tools install --help # show available commands
```
## Docker
+26 -24
View File
@@ -1,17 +1,16 @@
FROM python:3.13
ARG USERNAME=dev
ARG UID=1000
ARG GID=1000
# Create user with sudo support
RUN groupadd --gid $GID $USERNAME \
&& useradd --uid $UID --gid $GID -m $USERNAME \
RUN groupadd --gid $GID dev \
&& useradd --uid $UID --gid $GID -m dev \
&& apt-get update \
&& apt-get install -y sudo curl gnupg \
&& echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME \
&& usermod -a -G dialout $USERNAME
&& echo "dev ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/dev \
&& chmod 0440 /etc/sudoers.d/dev \
&& usermod -a -G dialout dev
# Install system packages
RUN apt-get install -y \
@@ -61,26 +60,29 @@ ENV LANG=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8
# Create user directories with proper ownership
RUN mkdir -p /home/${USERNAME}/.vscode-server/extensions \
&& mkdir -p /home/${USERNAME}/.local/bin \
&& mkdir -p /home/${USERNAME}/.claude \
RUN mkdir -p /home/dev/.vscode-server/extensions \
&& mkdir -p /home/dev/.local/bin \
&& mkdir -p /home/dev/.claude \
&& mkdir -p /workspace \
&& mkdir -p /workspace/.venv \
&& chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.vscode-server \
&& chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.local \
&& chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.claude \
&& chown -R ${USERNAME}:${USERNAME} /workspace
VOLUME /workspace/.venv
&& chown -R dev:dev /home/dev/.vscode-server \
&& chown -R dev:dev /home/dev/.local \
&& chown -R dev:dev /home/dev/.claude \
&& chown -R dev:dev /workspace
# Switch to non-root user (only once, for the rest of the build)
USER ${USERNAME}
WORKDIR /home/${USERNAME}
USER dev
# 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
ENV PATH="/home/${USERNAME}/.local/bin:${PATH}"
ENV PATH="/home/dev/.local/bin:${PATH}"
# Install uv
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
# User config (most frequently changed)
COPY --chown=${USERNAME}:${USERNAME} CLAUDE.md /home/${USERNAME}/.claude/CLAUDE.md
COPY --chown=${USERNAME}:${USERNAME} aliases.sh /home/${USERNAME}/.aliases.sh
COPY --chown=${USERNAME}:${USERNAME} bash_helpers.sh /home/${USERNAME}/.bash_helpers.sh
COPY --chown=dev:dev CLAUDE.md /home/dev/.claude/CLAUDE.md
COPY --chown=dev:dev aliases.sh /home/dev/.aliases.sh
COPY --chown=dev:dev bash_helpers.sh /home/dev/.bash_helpers.sh
# 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 \
Executable
+10
View File
@@ -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
-1
View File
@@ -6,7 +6,6 @@ alias uvs="uv sync --all-extras"
alias clip='xclip -selection clipboard'
alias open_ports='sudo ss -tulwn | grep LISTEN'
alias bat='batcat'
alias cat='batcat'
alias claude-allow="claude --dangerously-skip-permissions"
alias reload='source ~/.bashrc'
alias ls='eza'
+19
View File
@@ -1,6 +1,7 @@
"""Docker image commands."""
import os
import subprocess
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_DIR = "docker/python-dev"
DOCKERHUB_IMAGE = "roxauto/python-dev"
@app.command()
@@ -30,3 +32,20 @@ def build(
f"{'--no-cache ' if no_cache else ''}"
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 -19
View File
@@ -23,6 +23,33 @@ APT_PACKAGES = [
"btop",
]
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()
def claude():
@@ -59,6 +86,11 @@ def uv():
"""Install uv for the current user."""
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()
def ccusage():
@@ -175,22 +207,3 @@ def ai_skills():
@app.command()
def core():
"""Install essential tools."""
apt_packages()
docker()
uv()
fzf()
zoxide()
lazygit()
eza()
helpers()
@app.command()
def ai_tools():
"""Install AI tools and configure skills."""
claude()
copilot()
ai_skills()
ccusage()