Skip to content

image

image

Image management commands: build, list, cleanup, usage.

register(subparsers)

Register the image subcommand group.

Source code in src/terok/cli/commands/image.py
def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
    """Register the ``image`` subcommand group."""
    p_image = subparsers.add_parser("image", help="Manage terok container images")
    image_sub = p_image.add_subparsers(dest="image_cmd", required=True)

    # image build — L0+L1 build; defaults from config.image.* or a named project
    p_build = image_sub.add_parser(
        "build",
        help="Build the L0+L1 image chain (host-wide default, or a named project)",
        description=(
            "Build the L0+L1 images.  With no project arg, uses the agent set "
            "and base image declared in ~/.config/terok/config.yml "
            "(image.agents, image.base_image), falling back to ``all`` agents "
            "on ubuntu:24.04.  With a project arg, uses that project's "
            "configured base image + agent roster instead.  Use --rebuild to "
            "refresh agent versions; --full-rebuild also re-pulls the base OS "
            "and rebuilds L0 from scratch."
        ),
    )
    set_completer(
        p_build.add_argument(
            "project_id",
            nargs="?",
            default=None,
            help="Project whose base + agents to build for (optional)",
        ),
        _complete_project_ids,
    )
    p_build.add_argument(
        "--base",
        default=None,
        help="Override the configured base image for this build only.",
    )
    p_build.add_argument(
        "--agents",
        default=None,
        help='Comma-separated roster entries to install, or "all".  Overrides config.',
    )
    p_build.add_argument(
        "--family",
        default=None,
        help="Override package family (deb/rpm) for unknown bases.",
    )
    p_build.add_argument(
        "--rebuild",
        action="store_true",
        help="Cache-bust the agent install layers — refreshes agent versions.",
    )
    p_build.add_argument(
        "--full-rebuild",
        action="store_true",
        help="Force --no-cache --pull=always — re-pulls base OS, rebuilds L0+L1.",
    )
    p_build.add_argument(
        "--sidecar",
        action="store_true",
        help="Also build the sidecar L1 image (used by CodeRabbit).",
    )

    # image list
    p_list = image_sub.add_parser("list", help="List terok images with sizes")
    set_completer(
        p_list.add_argument("project_id", nargs="?", default=None, help="Filter by project"),
        _complete_project_ids,
    )

    # image cleanup
    p_cleanup = image_sub.add_parser("cleanup", help="Remove orphaned and dangling terok images")
    p_cleanup.add_argument(
        "--dry-run",
        action="store_true",
        help="Show what would be removed without removing",
    )
    p_cleanup.add_argument(
        "-y",
        "--yes",
        action="store_true",
        dest="assume_yes",
        help="Skip the confirmation prompt and remove immediately.",
    )

    # image usage — disk usage summary (was top-level `storage`)
    p_usage = image_sub.add_parser(
        "usage",
        help="Show storage usage summary (global and per-project)",
    )
    set_completer(
        p_usage.add_argument(
            "--project",
            default=None,
            help="Show detailed per-task breakdown for one project",
        ),
        _complete_project_ids,
    )
    p_usage.add_argument(
        "--json",
        action="store_true",
        dest="json_output",
        help="Machine-readable JSON output",
    )

dispatch(args)

Handle image management commands. Returns True if handled.

Source code in src/terok/cli/commands/image.py
def dispatch(args: argparse.Namespace) -> bool:
    """Handle image management commands.  Returns True if handled."""
    if args.cmd != "image":
        return False

    match args.image_cmd:
        case "build":
            _cmd_build(
                project_id=getattr(args, "project_id", None),
                base=getattr(args, "base", None),
                agents=getattr(args, "agents", None),
                family=getattr(args, "family", None),
                rebuild=getattr(args, "rebuild", False),
                full_rebuild=getattr(args, "full_rebuild", False),
                sidecar=getattr(args, "sidecar", False),
            )
        case "list":
            _cmd_list(getattr(args, "project_id", None))
        case "cleanup":
            _cmd_cleanup(
                dry_run=getattr(args, "dry_run", False),
                assume_yes=getattr(args, "assume_yes", False),
            )
        case "usage":
            _cmd_usage(
                project_id=getattr(args, "project", None),
                json_output=getattr(args, "json_output", False),
            )
        case _:  # pragma: no cover — required=True makes argparse enforce this
            return False
    return True