Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: pre-commit

on:
push:
pull_request:

permissions:
contents: read

jobs:
pre-commit:
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4
Comment thread
coderabbitai[bot] marked this conversation as resolved.
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Run pre-commit
uses: pre-commit/action@v3.0.1
32 changes: 32 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-merge-conflict
- id: end-of-file-fixer
- id: trailing-whitespace
args: ["--markdown-linebreak-ext=md"]
- id: check-yaml

- repo: https://github.com/asottile/pyupgrade
rev: v3.21.2
hooks:
- id: pyupgrade
args: ["--py310-plus"]

- repo: https://github.com/asottile/add-trailing-comma
rev: v4.0.0
hooks:
- id: add-trailing-comma

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.0
hooks:
- id: ruff-check
args: [--fix]
- id: ruff-format

- repo: https://github.com/rhysd/actionlint
rev: v1.7.12
hooks:
- id: actionlint
1 change: 0 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,4 +293,3 @@ VP_PROXY_ENABLED=false vp run claude
network. If you use Podman with the CNI backend, install the `dnsname`
plugin (e.g. `podman-plugins` on Fedora, `golang-github-containernetworking-plugin-dnsname`
on Debian/Ubuntu) and recreate the network. See [Quickstart — Using Podman](quickstart.md#using-podman-instead-of-docker) for full instructions.

5 changes: 1 addition & 4 deletions scripts/check_default_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ def _check_image_exists(image: str) -> tuple[bool, str]:
except subprocess.TimeoutExpired:
return (
False,
(
"timed out after "
f"{MANIFEST_CHECK_TIMEOUT_SECONDS}s while checking docker manifest"
),
(f"timed out after {MANIFEST_CHECK_TIMEOUT_SECONDS}s while checking docker manifest"),
)
if proc.returncode == 0:
return True, ""
Expand Down
18 changes: 12 additions & 6 deletions src/vibepod/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,21 @@ def run_command(
ctx: typer.Context,
agent: Annotated[str | None, typer.Argument(help="Agent to run")] = None,
workspace: Annotated[
Path, typer.Option("-w", "--workspace", help="Workspace directory")
Path,
typer.Option("-w", "--workspace", help="Workspace directory"),
] = Path("."),
pull: Annotated[bool, typer.Option("--pull", help="Pull latest image before run")] = False,
no_overlay: Annotated[
bool, typer.Option("--no-overlay", help="Skip the project overlay image")
bool,
typer.Option("--no-overlay", help="Skip the project overlay image"),
] = False,
rebuild_overlay: Annotated[
bool,
typer.Option("--rebuild-overlay", help="Force rebuilding the project overlay image"),
] = False,
detach: Annotated[
bool, typer.Option("-d", "--detach", help="Run container in background")
bool,
typer.Option("-d", "--detach", help="Run container in background"),
] = False,
env: Annotated[
list[str] | None,
Expand Down Expand Up @@ -116,18 +119,21 @@ def _register_run_alias(command_name: str, agent_name: str) -> None:
def _alias(
ctx: typer.Context,
workspace: Annotated[
Path, typer.Option("-w", "--workspace", help="Workspace directory")
Path,
typer.Option("-w", "--workspace", help="Workspace directory"),
] = Path("."),
pull: Annotated[bool, typer.Option("--pull", help="Pull latest image before run")] = False,
no_overlay: Annotated[
bool, typer.Option("--no-overlay", help="Skip the project overlay image")
bool,
typer.Option("--no-overlay", help="Skip the project overlay image"),
] = False,
rebuild_overlay: Annotated[
bool,
typer.Option("--rebuild-overlay", help="Force rebuilding the project overlay image"),
] = False,
detach: Annotated[
bool, typer.Option("-d", "--detach", help="Run container in background")
bool,
typer.Option("-d", "--detach", help="Run container in background"),
] = False,
env: Annotated[
list[str] | None,
Expand Down
8 changes: 4 additions & 4 deletions src/vibepod/commands/attach.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ def attach(
if not running:
error(
"No running VibePod agent containers to attach to. "
"Start one with `vp run`, or check `vp list --running`."
"Start one with `vp run`, or check `vp list --running`.",
)
raise typer.Exit(1)
if len(running) > 1:
names = ", ".join(sorted(c.name for c in running))
error(
f"Multiple running containers: {names}. "
"Specify one explicitly: `vp attach <container>`."
"Specify one explicitly: `vp attach <container>`.",
)
raise typer.Exit(1)
target = running[0]
Expand All @@ -73,14 +73,14 @@ def attach(
if getattr(target, "status", "") != "running":
error(
f"Container '{container}' is not running "
f"(status: {getattr(target, 'status', 'unknown')})."
f"(status: {getattr(target, 'status', 'unknown')}).",
)
raise typer.Exit(1)

agent = (getattr(target, "labels", {}) or {}).get("vibepod.agent", "agent")
info(f"Attaching to {target.name} ({agent})")
warning(
f"Close the terminal to leave it running, or stop it with `vp stop {target.name}`."
f"Close the terminal to leave it running, or stop it with `vp stop {target.name}`.",
)
try:
manager.attach_interactive(target)
Expand Down
16 changes: 10 additions & 6 deletions src/vibepod/commands/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
@app.command("init")
def init(
agent: Annotated[
str | None, typer.Argument(help="Optional agent config to copy into project")
str | None,
typer.Argument(help="Optional agent config to copy into project"),
] = None,
force: Annotated[
bool, typer.Option("--force", help="Overwrite existing project config if present")
bool,
typer.Option("--force", help="Overwrite existing project config if present"),
] = False,
) -> None:
"""Create a minimal project config or add a specific agent config."""
Expand Down Expand Up @@ -119,10 +121,12 @@ def show(
@app.command("path")
def path(
global_only: Annotated[
bool, typer.Option("--global", help="Show global config path only")
bool,
typer.Option("--global", help="Show global config path only"),
] = False,
project_only: Annotated[
bool, typer.Option("--project", help="Show project config path only")
bool,
typer.Option("--project", help="Show project config path only"),
] = False,
) -> None:
"""Show config and logs paths."""
Expand All @@ -141,7 +145,7 @@ def path(
return

logs_path = Path(
str(get_config().get("logging", {}).get("db_path", "~/.config/vibepod/logs.db"))
str(get_config().get("logging", {}).get("db_path", "~/.config/vibepod/logs.db")),
)
logs_path = logs_path.expanduser().resolve()

Expand Down Expand Up @@ -169,7 +173,7 @@ def allow_dir(
if is_protected_dir(target):
error(
f"'{target}' is a protected directory (home or root) and cannot be added "
"to the allow list."
"to the allow list.",
)
raise typer.Exit(1)
try:
Expand Down
16 changes: 8 additions & 8 deletions src/vibepod/commands/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def claude() -> None:
if not refresh:
warning(
" → no refreshToken present; Claude Code cannot rotate this "
"session and will require re-login after expiry"
"session and will require re-login after expiry",
)

console.print()
Expand Down Expand Up @@ -168,7 +168,7 @@ def claude() -> None:
if not found_any:
console.print(" none set on host")
console.print(
" [dim]note: these are host-side; the container sees its own env.[/dim]"
" [dim]note: these are host-side; the container sees its own env.[/dim]",
)

console.print()
Expand All @@ -182,29 +182,29 @@ def claude() -> None:
elif creds_path.exists():
console.print(
" [yellow]OAuth credentials.json[/yellow] "
"(subject to the known refresh bug — may require /login when expired)"
"(subject to the known refresh bug — may require /login when expired)",
)
else:
console.print(
" [red]no auth[/red] — run `vp run claude` and `/login`, "
"or `vp run claude setup-token`"
"or `vp run claude setup-token`",
)

console.print()
console.print("[bold]Tips[/bold]")
console.print(
" • If `modified` on .credentials.json never updates past the original /login time,"
" • If `modified` on .credentials.json never updates past the original /login time,",
)
console.print(" the token is not being rotated. Re-run with:")
console.print(
" [cyan]vp run claude -e ANTHROPIC_LOG=debug -e DEBUG=1[/cyan]"
" [cyan]vp run claude -e ANTHROPIC_LOG=debug -e DEBUG=1[/cyan]",
)
console.print(
" and look for [dim][API:auth][/dim] entries near/after expiry to confirm."
" and look for [dim][API:auth][/dim] entries near/after expiry to confirm.",
)
console.print(
" • For headless/CI, consider `claude setup-token` + "
"`-e CLAUDE_CODE_OAUTH_TOKEN=...` to bypass refresh entirely."
"`-e CLAUDE_CODE_OAUTH_TOKEN=...` to bypass refresh entirely.",
)

# Exit 2 only if credentials.json is expired AND nothing else would auth:
Expand Down
7 changes: 4 additions & 3 deletions src/vibepod/commands/list_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def _configured_agent_rows() -> list[dict[str, str]]:
"short": get_agent_shortcut(agent) or "-",
"agent": agent,
"image": DEFAULT_IMAGES[agent],
}
},
)
return rows

Expand All @@ -39,14 +39,15 @@ def _running_rows(containers: list[Any]) -> list[dict[str, str]]:
"agent": agent,
"container": getattr(container, "name", "-"),
"context": labels.get("vibepod.workspace", "-"),
}
},
)
return sorted(rows, key=lambda row: (row["agent"], row["container"]))


def list_agents(
running: Annotated[
bool, typer.Option("-r", "--running", help="Show only running agents")
bool,
typer.Option("-r", "--running", help="Show only running agents"),
] = False,
as_json: Annotated[bool, typer.Option("--json", help="Output JSON")] = False,
) -> None:
Expand Down
2 changes: 1 addition & 1 deletion src/vibepod/commands/logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def logs_start(
datasette_port = port if port is not None else int(log_cfg.get("ui_port", 8001))
logs_db_path = Path(str(log_cfg.get("db_path", "~/.config/vibepod/logs.db"))).expanduser()
proxy_db_path = Path(
str(proxy_cfg.get("db_path", "~/.config/vibepod/proxy/proxy.db"))
str(proxy_cfg.get("db_path", "~/.config/vibepod/proxy/proxy.db")),
).expanduser()

try:
Expand Down
Loading
Loading