refactor(cli): restructure cmd packages into subdirectories
- Move CLI commands into subdirectories matching command hierarchy:
dev/, go/, php/, build/, ci/, sdk/, pkg/, vm/, docs/, setup/, doctor/, test/, ai/
- Create shared/ package for common styles and utilities
- Add new `core ai` root command with claude subcommand
- Update package declarations and imports across all files
- Create commands.go entry points for each package
- Remove GUI-related files (moved to core-gui repo)
This makes the filesystem structure match the CLI command structure,
improving context capture and code organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:02:43 +00:00
|
|
|
package vm
|
2026-01-28 18:50:32 +00:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
refactor(cli): move commands from cmd/ to pkg/ with self-registration
Implements defence in depth through build variants - only compiled code
exists in the binary. Commands now self-register via cli.RegisterCommands()
in their init() functions, mirroring the i18n.RegisterLocales() pattern.
Structure changes:
- cmd/{ai,build,ci,dev,docs,doctor,go,php,pkg,sdk,setup,test,vm}/ → pkg/*/cmd_*.go
- cmd/core_dev.go, cmd/core_ci.go → cmd/variants/{full,ci,php,minimal}.go
- Added pkg/cli/commands.go with RegisterCommands API
- Updated pkg/cli/runtime.go to attach registered commands
Build variants:
- go build → full (21MB, all 13 command groups)
- go build -tags ci → ci (18MB, build/ci/sdk/doctor)
- go build -tags php → php (14MB, php/doctor)
- go build -tags minimal → minimal (11MB, doctor only)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:55:55 +00:00
|
|
|
"errors"
|
2026-01-28 18:50:32 +00:00
|
|
|
"fmt"
|
2026-02-04 15:33:22 +00:00
|
|
|
goio "io"
|
2026-01-28 18:50:32 +00:00
|
|
|
"os"
|
|
|
|
|
"strings"
|
|
|
|
|
"text/tabwriter"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/host-uk/core/pkg/container"
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
"github.com/host-uk/core/pkg/i18n"
|
2026-02-04 15:33:22 +00:00
|
|
|
"github.com/host-uk/core/pkg/io"
|
2026-01-30 00:47:54 +00:00
|
|
|
"github.com/spf13/cobra"
|
|
|
|
|
)
|
|
|
|
|
|
2026-02-05 03:43:12 +00:00
|
|
|
var (
|
|
|
|
|
// allowedExecCommands is a whitelist of commands allowed to be executed in containers.
|
|
|
|
|
allowedExecCommands = map[string]bool{
|
|
|
|
|
"ls": true,
|
|
|
|
|
"ps": true,
|
|
|
|
|
"cat": true,
|
|
|
|
|
"top": true,
|
|
|
|
|
"df": true,
|
|
|
|
|
"du": true,
|
|
|
|
|
"ifconfig": true,
|
|
|
|
|
"ip": true,
|
|
|
|
|
"ping": true,
|
|
|
|
|
"netstat": true,
|
|
|
|
|
"date": true,
|
|
|
|
|
"uptime": true,
|
|
|
|
|
"whoami": true,
|
|
|
|
|
"id": true,
|
|
|
|
|
"uname": true,
|
|
|
|
|
"echo": true,
|
|
|
|
|
"tail": true,
|
|
|
|
|
"head": true,
|
|
|
|
|
"grep": true,
|
|
|
|
|
"sleep": true,
|
|
|
|
|
"sh": true,
|
|
|
|
|
"bash": true,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
var (
|
|
|
|
|
runName string
|
|
|
|
|
runDetach bool
|
|
|
|
|
runMemory int
|
|
|
|
|
runCPUs int
|
|
|
|
|
runSSHPort int
|
|
|
|
|
runTemplateName string
|
|
|
|
|
runVarFlags []string
|
2026-01-28 18:50:32 +00:00
|
|
|
)
|
|
|
|
|
|
2026-01-29 11:35:22 +00:00
|
|
|
// addVMRunCommand adds the 'run' command under vm.
|
2026-01-30 00:47:54 +00:00
|
|
|
func addVMRunCommand(parent *cobra.Command) {
|
|
|
|
|
runCmd := &cobra.Command{
|
|
|
|
|
Use: "run [image]",
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
Short: i18n.T("cmd.vm.run.short"),
|
|
|
|
|
Long: i18n.T("cmd.vm.run.long"),
|
2026-01-30 00:47:54 +00:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
|
opts := container.RunOptions{
|
|
|
|
|
Name: runName,
|
|
|
|
|
Detach: runDetach,
|
|
|
|
|
Memory: runMemory,
|
|
|
|
|
CPUs: runCPUs,
|
|
|
|
|
SSHPort: runSSHPort,
|
|
|
|
|
}
|
2026-01-28 18:59:45 +00:00
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
// If template is specified, build and run from template
|
|
|
|
|
if runTemplateName != "" {
|
|
|
|
|
vars := ParseVarFlags(runVarFlags)
|
|
|
|
|
return RunFromTemplate(runTemplateName, vars, opts)
|
|
|
|
|
}
|
2026-01-28 18:59:45 +00:00
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
// Otherwise, require an image path
|
|
|
|
|
if len(args) == 0 {
|
refactor(cli): move commands from cmd/ to pkg/ with self-registration
Implements defence in depth through build variants - only compiled code
exists in the binary. Commands now self-register via cli.RegisterCommands()
in their init() functions, mirroring the i18n.RegisterLocales() pattern.
Structure changes:
- cmd/{ai,build,ci,dev,docs,doctor,go,php,pkg,sdk,setup,test,vm}/ → pkg/*/cmd_*.go
- cmd/core_dev.go, cmd/core_ci.go → cmd/variants/{full,ci,php,minimal}.go
- Added pkg/cli/commands.go with RegisterCommands API
- Updated pkg/cli/runtime.go to attach registered commands
Build variants:
- go build → full (21MB, all 13 command groups)
- go build -tags ci → ci (18MB, build/ci/sdk/doctor)
- go build -tags php → php (14MB, php/doctor)
- go build -tags minimal → minimal (11MB, doctor only)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:55:55 +00:00
|
|
|
return errors.New(i18n.T("cmd.vm.run.error.image_required"))
|
2026-01-30 00:47:54 +00:00
|
|
|
}
|
|
|
|
|
image := args[0]
|
|
|
|
|
|
|
|
|
|
return runContainer(image, runName, runDetach, runMemory, runCPUs, runSSHPort)
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
runCmd.Flags().StringVar(&runName, "name", "", i18n.T("cmd.vm.run.flag.name"))
|
|
|
|
|
runCmd.Flags().BoolVarP(&runDetach, "detach", "d", false, i18n.T("cmd.vm.run.flag.detach"))
|
|
|
|
|
runCmd.Flags().IntVar(&runMemory, "memory", 0, i18n.T("cmd.vm.run.flag.memory"))
|
|
|
|
|
runCmd.Flags().IntVar(&runCPUs, "cpus", 0, i18n.T("cmd.vm.run.flag.cpus"))
|
|
|
|
|
runCmd.Flags().IntVar(&runSSHPort, "ssh-port", 0, i18n.T("cmd.vm.run.flag.ssh_port"))
|
|
|
|
|
runCmd.Flags().StringVar(&runTemplateName, "template", "", i18n.T("cmd.vm.run.flag.template"))
|
|
|
|
|
runCmd.Flags().StringArrayVar(&runVarFlags, "var", nil, i18n.T("cmd.vm.run.flag.var"))
|
2026-01-28 18:50:32 +00:00
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
parent.AddCommand(runCmd)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func runContainer(image, name string, detach bool, memory, cpus, sshPort int) error {
|
2026-02-04 15:33:22 +00:00
|
|
|
manager, err := container.NewLinuxKitManager(io.Local)
|
2026-01-28 18:50:32 +00:00
|
|
|
if err != nil {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
return fmt.Errorf(i18n.T("i18n.fail.init", "container manager")+": %w", err)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
opts := container.RunOptions{
|
|
|
|
|
Name: name,
|
|
|
|
|
Detach: detach,
|
|
|
|
|
Memory: memory,
|
|
|
|
|
CPUs: cpus,
|
|
|
|
|
SSHPort: sshPort,
|
|
|
|
|
}
|
|
|
|
|
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
fmt.Printf("%s %s\n", dimStyle.Render(i18n.Label("image")), image)
|
2026-01-28 18:50:32 +00:00
|
|
|
if name != "" {
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
fmt.Printf("%s %s\n", dimStyle.Render(i18n.T("cmd.vm.label.name")), name)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
fmt.Printf("%s %s\n", dimStyle.Render(i18n.T("cmd.vm.label.hypervisor")), manager.Hypervisor().Name())
|
2026-01-28 18:50:32 +00:00
|
|
|
fmt.Println()
|
|
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
c, err := manager.Run(ctx, image, opts)
|
|
|
|
|
if err != nil {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
return fmt.Errorf(i18n.T("i18n.fail.run", "container")+": %w", err)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if detach {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
fmt.Printf("%s %s\n", successStyle.Render(i18n.Label("started")), c.ID)
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
fmt.Printf("%s %d\n", dimStyle.Render(i18n.T("cmd.vm.label.pid")), c.PID)
|
2026-01-28 18:50:32 +00:00
|
|
|
fmt.Println()
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
fmt.Println(i18n.T("cmd.vm.hint.view_logs", map[string]interface{}{"ID": c.ID[:8]}))
|
|
|
|
|
fmt.Println(i18n.T("cmd.vm.hint.stop", map[string]interface{}{"ID": c.ID[:8]}))
|
2026-01-28 18:50:32 +00:00
|
|
|
} else {
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
fmt.Printf("\n%s %s\n", dimStyle.Render(i18n.T("cmd.vm.label.container_stopped")), c.ID)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
var psAll bool
|
2026-01-28 18:50:32 +00:00
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
// addVMPsCommand adds the 'ps' command under vm.
|
|
|
|
|
func addVMPsCommand(parent *cobra.Command) {
|
|
|
|
|
psCmd := &cobra.Command{
|
|
|
|
|
Use: "ps",
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
Short: i18n.T("cmd.vm.ps.short"),
|
|
|
|
|
Long: i18n.T("cmd.vm.ps.long"),
|
2026-01-30 00:47:54 +00:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
|
return listContainers(psAll)
|
|
|
|
|
},
|
|
|
|
|
}
|
2026-01-28 18:50:32 +00:00
|
|
|
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
psCmd.Flags().BoolVarP(&psAll, "all", "a", false, i18n.T("cmd.vm.ps.flag.all"))
|
2026-01-28 18:50:32 +00:00
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
parent.AddCommand(psCmd)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func listContainers(all bool) error {
|
2026-02-04 15:33:22 +00:00
|
|
|
manager, err := container.NewLinuxKitManager(io.Local)
|
2026-01-28 18:50:32 +00:00
|
|
|
if err != nil {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
return fmt.Errorf(i18n.T("i18n.fail.init", "container manager")+": %w", err)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
containers, err := manager.List(ctx)
|
|
|
|
|
if err != nil {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
return fmt.Errorf(i18n.T("i18n.fail.list", "containers")+": %w", err)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Filter if not showing all
|
|
|
|
|
if !all {
|
|
|
|
|
filtered := make([]*container.Container, 0)
|
|
|
|
|
for _, c := range containers {
|
|
|
|
|
if c.Status == container.StatusRunning {
|
|
|
|
|
filtered = append(filtered, c)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
containers = filtered
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(containers) == 0 {
|
|
|
|
|
if all {
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
fmt.Println(i18n.T("cmd.vm.ps.no_containers"))
|
2026-01-28 18:50:32 +00:00
|
|
|
} else {
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
fmt.Println(i18n.T("cmd.vm.ps.no_running"))
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
feat: infrastructure packages and lint cleanup (#281)
* ci: consolidate duplicate workflows and merge CodeQL configs
Remove 17 duplicate workflow files that were split copies of the
combined originals. Each family (CI, CodeQL, Coverage, PR Build,
Alpha Release) had the same job duplicated across separate
push/pull_request/schedule/manual trigger files.
Merge codeql.yml and codescan.yml into a single codeql.yml with
a language matrix covering go, javascript-typescript, python,
and actions — matching the previous default setup coverage.
Remaining workflows (one per family):
- ci.yml (push + PR + manual)
- codeql.yml (push + PR + schedule, all languages)
- coverage.yml (push + PR + manual)
- alpha-release.yml (push + manual)
- pr-build.yml (PR + manual)
- release.yml (tag push)
- agent-verify.yml, auto-label.yml, auto-project.yml
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add collect, config, crypt, plugin packages and fix all lint issues
Add four new infrastructure packages with CLI commands:
- pkg/config: layered configuration (defaults → file → env → flags)
- pkg/crypt: crypto primitives (Argon2id, AES-GCM, ChaCha20, HMAC, checksums)
- pkg/plugin: plugin system with GitHub-based install/update/remove
- pkg/collect: collection subsystem (GitHub, BitcoinTalk, market, papers, excavate)
Fix all golangci-lint issues across the entire codebase (~100 errcheck,
staticcheck SA1012/SA1019/ST1005, unused, ineffassign fixes) so that
`core go qa` passes with 0 issues.
Closes #167, #168, #170, #250, #251, #252, #253, #254, #255, #256
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:34:43 +00:00
|
|
|
_, _ = fmt.Fprintln(w, i18n.T("cmd.vm.ps.header"))
|
|
|
|
|
_, _ = fmt.Fprintln(w, "--\t----\t-----\t------\t-------\t---")
|
2026-01-28 18:50:32 +00:00
|
|
|
|
|
|
|
|
for _, c := range containers {
|
|
|
|
|
// Shorten image path
|
|
|
|
|
imageName := c.Image
|
|
|
|
|
if len(imageName) > 30 {
|
|
|
|
|
imageName = "..." + imageName[len(imageName)-27:]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Format duration
|
|
|
|
|
duration := formatDuration(time.Since(c.StartedAt))
|
|
|
|
|
|
|
|
|
|
// Status with color
|
|
|
|
|
status := string(c.Status)
|
|
|
|
|
switch c.Status {
|
|
|
|
|
case container.StatusRunning:
|
|
|
|
|
status = successStyle.Render(status)
|
|
|
|
|
case container.StatusStopped:
|
|
|
|
|
status = dimStyle.Render(status)
|
|
|
|
|
case container.StatusError:
|
|
|
|
|
status = errorStyle.Render(status)
|
|
|
|
|
}
|
|
|
|
|
|
feat: infrastructure packages and lint cleanup (#281)
* ci: consolidate duplicate workflows and merge CodeQL configs
Remove 17 duplicate workflow files that were split copies of the
combined originals. Each family (CI, CodeQL, Coverage, PR Build,
Alpha Release) had the same job duplicated across separate
push/pull_request/schedule/manual trigger files.
Merge codeql.yml and codescan.yml into a single codeql.yml with
a language matrix covering go, javascript-typescript, python,
and actions — matching the previous default setup coverage.
Remaining workflows (one per family):
- ci.yml (push + PR + manual)
- codeql.yml (push + PR + schedule, all languages)
- coverage.yml (push + PR + manual)
- alpha-release.yml (push + manual)
- pr-build.yml (PR + manual)
- release.yml (tag push)
- agent-verify.yml, auto-label.yml, auto-project.yml
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add collect, config, crypt, plugin packages and fix all lint issues
Add four new infrastructure packages with CLI commands:
- pkg/config: layered configuration (defaults → file → env → flags)
- pkg/crypt: crypto primitives (Argon2id, AES-GCM, ChaCha20, HMAC, checksums)
- pkg/plugin: plugin system with GitHub-based install/update/remove
- pkg/collect: collection subsystem (GitHub, BitcoinTalk, market, papers, excavate)
Fix all golangci-lint issues across the entire codebase (~100 errcheck,
staticcheck SA1012/SA1019/ST1005, unused, ineffassign fixes) so that
`core go qa` passes with 0 issues.
Closes #167, #168, #170, #250, #251, #252, #253, #254, #255, #256
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:34:43 +00:00
|
|
|
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%d\n",
|
2026-01-28 18:50:32 +00:00
|
|
|
c.ID[:8], c.Name, imageName, status, duration, c.PID)
|
|
|
|
|
}
|
|
|
|
|
|
feat: infrastructure packages and lint cleanup (#281)
* ci: consolidate duplicate workflows and merge CodeQL configs
Remove 17 duplicate workflow files that were split copies of the
combined originals. Each family (CI, CodeQL, Coverage, PR Build,
Alpha Release) had the same job duplicated across separate
push/pull_request/schedule/manual trigger files.
Merge codeql.yml and codescan.yml into a single codeql.yml with
a language matrix covering go, javascript-typescript, python,
and actions — matching the previous default setup coverage.
Remaining workflows (one per family):
- ci.yml (push + PR + manual)
- codeql.yml (push + PR + schedule, all languages)
- coverage.yml (push + PR + manual)
- alpha-release.yml (push + manual)
- pr-build.yml (PR + manual)
- release.yml (tag push)
- agent-verify.yml, auto-label.yml, auto-project.yml
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add collect, config, crypt, plugin packages and fix all lint issues
Add four new infrastructure packages with CLI commands:
- pkg/config: layered configuration (defaults → file → env → flags)
- pkg/crypt: crypto primitives (Argon2id, AES-GCM, ChaCha20, HMAC, checksums)
- pkg/plugin: plugin system with GitHub-based install/update/remove
- pkg/collect: collection subsystem (GitHub, BitcoinTalk, market, papers, excavate)
Fix all golangci-lint issues across the entire codebase (~100 errcheck,
staticcheck SA1012/SA1019/ST1005, unused, ineffassign fixes) so that
`core go qa` passes with 0 issues.
Closes #167, #168, #170, #250, #251, #252, #253, #254, #255, #256
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:34:43 +00:00
|
|
|
_ = w.Flush()
|
2026-01-28 18:50:32 +00:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func formatDuration(d time.Duration) string {
|
|
|
|
|
if d < time.Minute {
|
|
|
|
|
return fmt.Sprintf("%ds", int(d.Seconds()))
|
|
|
|
|
}
|
|
|
|
|
if d < time.Hour {
|
|
|
|
|
return fmt.Sprintf("%dm", int(d.Minutes()))
|
|
|
|
|
}
|
|
|
|
|
if d < 24*time.Hour {
|
|
|
|
|
return fmt.Sprintf("%dh", int(d.Hours()))
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("%dd", int(d.Hours()/24))
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-29 11:35:22 +00:00
|
|
|
// addVMStopCommand adds the 'stop' command under vm.
|
2026-01-30 00:47:54 +00:00
|
|
|
func addVMStopCommand(parent *cobra.Command) {
|
|
|
|
|
stopCmd := &cobra.Command{
|
|
|
|
|
Use: "stop <container-id>",
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
Short: i18n.T("cmd.vm.stop.short"),
|
|
|
|
|
Long: i18n.T("cmd.vm.stop.long"),
|
2026-01-30 00:47:54 +00:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
|
if len(args) == 0 {
|
refactor(cli): move commands from cmd/ to pkg/ with self-registration
Implements defence in depth through build variants - only compiled code
exists in the binary. Commands now self-register via cli.RegisterCommands()
in their init() functions, mirroring the i18n.RegisterLocales() pattern.
Structure changes:
- cmd/{ai,build,ci,dev,docs,doctor,go,php,pkg,sdk,setup,test,vm}/ → pkg/*/cmd_*.go
- cmd/core_dev.go, cmd/core_ci.go → cmd/variants/{full,ci,php,minimal}.go
- Added pkg/cli/commands.go with RegisterCommands API
- Updated pkg/cli/runtime.go to attach registered commands
Build variants:
- go build → full (21MB, all 13 command groups)
- go build -tags ci → ci (18MB, build/ci/sdk/doctor)
- go build -tags php → php (14MB, php/doctor)
- go build -tags minimal → minimal (11MB, doctor only)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:55:55 +00:00
|
|
|
return errors.New(i18n.T("cmd.vm.error.id_required"))
|
2026-01-30 00:47:54 +00:00
|
|
|
}
|
|
|
|
|
return stopContainer(args[0])
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parent.AddCommand(stopCmd)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func stopContainer(id string) error {
|
2026-02-04 15:33:22 +00:00
|
|
|
manager, err := container.NewLinuxKitManager(io.Local)
|
2026-01-28 18:50:32 +00:00
|
|
|
if err != nil {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
return fmt.Errorf(i18n.T("i18n.fail.init", "container manager")+": %w", err)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Support partial ID matching
|
|
|
|
|
fullID, err := resolveContainerID(manager, id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
fmt.Printf("%s %s\n", dimStyle.Render(i18n.T("cmd.vm.stop.stopping")), fullID[:8])
|
2026-01-28 18:50:32 +00:00
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
if err := manager.Stop(ctx, fullID); err != nil {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
return fmt.Errorf(i18n.T("i18n.fail.stop", "container")+": %w", err)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
refactor(i18n): consolidate duplicate translation keys into common section
Add common.* keys for reusable translations:
- common.label.* - UI labels (error, done, status, version, etc.)
- common.status.* - status words (running, stopped, dirty, synced)
- common.error.* - error messages (failed, not_found, working_dir)
- common.flag.* - CLI flag descriptions (registry, verbose, etc.)
- common.count.* - count templates (failed, passed, skipped)
- common.result.* - result messages (all_passed, no_issues)
- common.progress.* - progress messages (running, checking)
- common.hint.* - help hints (install_with, fix_deps)
Update all cmd/* files to use common keys instead of duplicated
command-specific keys. Reduces translation maintenance burden
and ensures consistency across the CLI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:32:25 +00:00
|
|
|
fmt.Printf("%s\n", successStyle.Render(i18n.T("common.status.stopped")))
|
2026-01-28 18:50:32 +00:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// resolveContainerID resolves a partial ID to a full ID.
|
|
|
|
|
func resolveContainerID(manager *container.LinuxKitManager, partialID string) (string, error) {
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
containers, err := manager.List(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var matches []*container.Container
|
|
|
|
|
for _, c := range containers {
|
|
|
|
|
if strings.HasPrefix(c.ID, partialID) || strings.HasPrefix(c.Name, partialID) {
|
|
|
|
|
matches = append(matches, c)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch len(matches) {
|
|
|
|
|
case 0:
|
refactor(cli): move commands from cmd/ to pkg/ with self-registration
Implements defence in depth through build variants - only compiled code
exists in the binary. Commands now self-register via cli.RegisterCommands()
in their init() functions, mirroring the i18n.RegisterLocales() pattern.
Structure changes:
- cmd/{ai,build,ci,dev,docs,doctor,go,php,pkg,sdk,setup,test,vm}/ → pkg/*/cmd_*.go
- cmd/core_dev.go, cmd/core_ci.go → cmd/variants/{full,ci,php,minimal}.go
- Added pkg/cli/commands.go with RegisterCommands API
- Updated pkg/cli/runtime.go to attach registered commands
Build variants:
- go build → full (21MB, all 13 command groups)
- go build -tags ci → ci (18MB, build/ci/sdk/doctor)
- go build -tags php → php (14MB, php/doctor)
- go build -tags minimal → minimal (11MB, doctor only)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:55:55 +00:00
|
|
|
return "", errors.New(i18n.T("cmd.vm.error.no_match", map[string]interface{}{"ID": partialID}))
|
2026-01-28 18:50:32 +00:00
|
|
|
case 1:
|
|
|
|
|
return matches[0].ID, nil
|
|
|
|
|
default:
|
refactor(cli): move commands from cmd/ to pkg/ with self-registration
Implements defence in depth through build variants - only compiled code
exists in the binary. Commands now self-register via cli.RegisterCommands()
in their init() functions, mirroring the i18n.RegisterLocales() pattern.
Structure changes:
- cmd/{ai,build,ci,dev,docs,doctor,go,php,pkg,sdk,setup,test,vm}/ → pkg/*/cmd_*.go
- cmd/core_dev.go, cmd/core_ci.go → cmd/variants/{full,ci,php,minimal}.go
- Added pkg/cli/commands.go with RegisterCommands API
- Updated pkg/cli/runtime.go to attach registered commands
Build variants:
- go build → full (21MB, all 13 command groups)
- go build -tags ci → ci (18MB, build/ci/sdk/doctor)
- go build -tags php → php (14MB, php/doctor)
- go build -tags minimal → minimal (11MB, doctor only)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:55:55 +00:00
|
|
|
return "", errors.New(i18n.T("cmd.vm.error.multiple_match", map[string]interface{}{"ID": partialID}))
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
var logsFollow bool
|
2026-01-28 18:50:32 +00:00
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
// addVMLogsCommand adds the 'logs' command under vm.
|
|
|
|
|
func addVMLogsCommand(parent *cobra.Command) {
|
|
|
|
|
logsCmd := &cobra.Command{
|
|
|
|
|
Use: "logs <container-id>",
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
Short: i18n.T("cmd.vm.logs.short"),
|
|
|
|
|
Long: i18n.T("cmd.vm.logs.long"),
|
2026-01-30 00:47:54 +00:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
|
if len(args) == 0 {
|
refactor(cli): move commands from cmd/ to pkg/ with self-registration
Implements defence in depth through build variants - only compiled code
exists in the binary. Commands now self-register via cli.RegisterCommands()
in their init() functions, mirroring the i18n.RegisterLocales() pattern.
Structure changes:
- cmd/{ai,build,ci,dev,docs,doctor,go,php,pkg,sdk,setup,test,vm}/ → pkg/*/cmd_*.go
- cmd/core_dev.go, cmd/core_ci.go → cmd/variants/{full,ci,php,minimal}.go
- Added pkg/cli/commands.go with RegisterCommands API
- Updated pkg/cli/runtime.go to attach registered commands
Build variants:
- go build → full (21MB, all 13 command groups)
- go build -tags ci → ci (18MB, build/ci/sdk/doctor)
- go build -tags php → php (14MB, php/doctor)
- go build -tags minimal → minimal (11MB, doctor only)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:55:55 +00:00
|
|
|
return errors.New(i18n.T("cmd.vm.error.id_required"))
|
2026-01-30 00:47:54 +00:00
|
|
|
}
|
|
|
|
|
return viewLogs(args[0], logsFollow)
|
|
|
|
|
},
|
|
|
|
|
}
|
2026-01-28 18:50:32 +00:00
|
|
|
|
refactor(i18n): consolidate duplicate translation keys into common section
Add common.* keys for reusable translations:
- common.label.* - UI labels (error, done, status, version, etc.)
- common.status.* - status words (running, stopped, dirty, synced)
- common.error.* - error messages (failed, not_found, working_dir)
- common.flag.* - CLI flag descriptions (registry, verbose, etc.)
- common.count.* - count templates (failed, passed, skipped)
- common.result.* - result messages (all_passed, no_issues)
- common.progress.* - progress messages (running, checking)
- common.hint.* - help hints (install_with, fix_deps)
Update all cmd/* files to use common keys instead of duplicated
command-specific keys. Reduces translation maintenance burden
and ensures consistency across the CLI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:32:25 +00:00
|
|
|
logsCmd.Flags().BoolVarP(&logsFollow, "follow", "f", false, i18n.T("common.flag.follow"))
|
2026-01-28 18:50:32 +00:00
|
|
|
|
2026-01-30 00:47:54 +00:00
|
|
|
parent.AddCommand(logsCmd)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func viewLogs(id string, follow bool) error {
|
2026-02-04 15:33:22 +00:00
|
|
|
manager, err := container.NewLinuxKitManager(io.Local)
|
2026-01-28 18:50:32 +00:00
|
|
|
if err != nil {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
return fmt.Errorf(i18n.T("i18n.fail.init", "container manager")+": %w", err)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fullID, err := resolveContainerID(manager, id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
reader, err := manager.Logs(ctx, fullID, follow)
|
|
|
|
|
if err != nil {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
return fmt.Errorf(i18n.T("i18n.fail.get", "logs")+": %w", err)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
feat: infrastructure packages and lint cleanup (#281)
* ci: consolidate duplicate workflows and merge CodeQL configs
Remove 17 duplicate workflow files that were split copies of the
combined originals. Each family (CI, CodeQL, Coverage, PR Build,
Alpha Release) had the same job duplicated across separate
push/pull_request/schedule/manual trigger files.
Merge codeql.yml and codescan.yml into a single codeql.yml with
a language matrix covering go, javascript-typescript, python,
and actions — matching the previous default setup coverage.
Remaining workflows (one per family):
- ci.yml (push + PR + manual)
- codeql.yml (push + PR + schedule, all languages)
- coverage.yml (push + PR + manual)
- alpha-release.yml (push + manual)
- pr-build.yml (PR + manual)
- release.yml (tag push)
- agent-verify.yml, auto-label.yml, auto-project.yml
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add collect, config, crypt, plugin packages and fix all lint issues
Add four new infrastructure packages with CLI commands:
- pkg/config: layered configuration (defaults → file → env → flags)
- pkg/crypt: crypto primitives (Argon2id, AES-GCM, ChaCha20, HMAC, checksums)
- pkg/plugin: plugin system with GitHub-based install/update/remove
- pkg/collect: collection subsystem (GitHub, BitcoinTalk, market, papers, excavate)
Fix all golangci-lint issues across the entire codebase (~100 errcheck,
staticcheck SA1012/SA1019/ST1005, unused, ineffassign fixes) so that
`core go qa` passes with 0 issues.
Closes #167, #168, #170, #250, #251, #252, #253, #254, #255, #256
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:34:43 +00:00
|
|
|
defer func() { _ = reader.Close() }()
|
2026-01-28 18:50:32 +00:00
|
|
|
|
2026-02-04 15:33:22 +00:00
|
|
|
_, err = goio.Copy(os.Stdout, reader)
|
2026-01-28 18:50:32 +00:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-29 11:35:22 +00:00
|
|
|
// addVMExecCommand adds the 'exec' command under vm.
|
2026-01-30 00:47:54 +00:00
|
|
|
func addVMExecCommand(parent *cobra.Command) {
|
|
|
|
|
execCmd := &cobra.Command{
|
|
|
|
|
Use: "exec <container-id> <command> [args...]",
|
feat(i18n): add translation keys to all CLI commands
Replace hardcoded strings with i18n.T() calls across all cmd/* packages:
- ai, build, ci, dev, docs, doctor, go, php, pkg, sdk, setup, test, vm
Adds 500+ translation keys to en.json for command descriptions,
flag descriptions, labels, messages, and error strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:37:57 +00:00
|
|
|
Short: i18n.T("cmd.vm.exec.short"),
|
|
|
|
|
Long: i18n.T("cmd.vm.exec.long"),
|
2026-01-30 00:47:54 +00:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
|
if len(args) < 2 {
|
refactor(cli): move commands from cmd/ to pkg/ with self-registration
Implements defence in depth through build variants - only compiled code
exists in the binary. Commands now self-register via cli.RegisterCommands()
in their init() functions, mirroring the i18n.RegisterLocales() pattern.
Structure changes:
- cmd/{ai,build,ci,dev,docs,doctor,go,php,pkg,sdk,setup,test,vm}/ → pkg/*/cmd_*.go
- cmd/core_dev.go, cmd/core_ci.go → cmd/variants/{full,ci,php,minimal}.go
- Added pkg/cli/commands.go with RegisterCommands API
- Updated pkg/cli/runtime.go to attach registered commands
Build variants:
- go build → full (21MB, all 13 command groups)
- go build -tags ci → ci (18MB, build/ci/sdk/doctor)
- go build -tags php → php (14MB, php/doctor)
- go build -tags minimal → minimal (11MB, doctor only)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:55:55 +00:00
|
|
|
return errors.New(i18n.T("cmd.vm.error.id_and_cmd_required"))
|
2026-01-30 00:47:54 +00:00
|
|
|
}
|
|
|
|
|
return execInContainer(args[0], args[1:])
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parent.AddCommand(execCmd)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func execInContainer(id string, cmd []string) error {
|
2026-02-05 03:43:12 +00:00
|
|
|
if len(cmd) == 0 {
|
|
|
|
|
return errors.New(i18n.T("cmd.vm.error.id_and_cmd_required"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validate against whitelist
|
|
|
|
|
baseCmd := cmd[0]
|
|
|
|
|
if !allowedExecCommands[baseCmd] {
|
|
|
|
|
return errors.New(i18n.T("cmd.vm.error.command_not_allowed", map[string]interface{}{"Command": baseCmd}))
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-04 15:33:22 +00:00
|
|
|
manager, err := container.NewLinuxKitManager(io.Local)
|
2026-01-28 18:50:32 +00:00
|
|
|
if err != nil {
|
refactor(i18n): migrate all pkg/* to grammar engine
Replace verbose map-based translation calls with concise grammar
engine helpers across all command packages:
- i18n.T("common.label.xxx") → i18n.Label("xxx")
- i18n.T("common.error.failed", map) → i18n.T("i18n.fail.verb", subj)
- i18n.T("common.progress.running", map) → i18n.ProgressSubject()
- i18n.T("common.count.xxx", map) → i18n.T("i18n.count.xxx", n)
Packages updated: ai, ci, dev, docs, php, pkgcmd, sdk, setup, test, vm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:45 +00:00
|
|
|
return fmt.Errorf(i18n.T("i18n.fail.init", "container manager")+": %w", err)
|
2026-01-28 18:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fullID, err := resolveContainerID(manager, id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
return manager.Exec(ctx, fullID, cmd)
|
|
|
|
|
}
|