diff --git a/internal/shell/commands.go b/internal/shell/commands.go
new file mode 100644
index 0000000..80b8651
--- /dev/null
+++ b/internal/shell/commands.go
@@ -0,0 +1,357 @@
+// commands.go - встроенные команды fush shell (стиль busybox)
+// Реализует базовые команды: exit, ls, cd, mkdir, rm, touch, pwd, cat, echo
+// Все команды работают независимо от ОС, используя только стандартную библиотеку Go
+
+package shell
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "fush/pkg/ansi"
+)
+
+// cmdExit обрабатывает команду exit
+func (s *Shell) cmdExit(args []string) error {
+ s.running.Store(false)
+ s.logger.Info("Выполнена команда exit")
+ return nil
+}
+
+// cmdHelp обрабатывает команду help
+func (s *Shell) cmdHelp(args []string) error {
+ fmt.Println()
+ ansi.Println(ansi.Cyan, "╔══════════════════════════════════════════════════════════════╗")
+ ansi.Println(ansi.Cyan, "║ fush shell - Доступные команды ║")
+ ansi.Println(ansi.Cyan, "╚══════════════════════════════════════════════════════════════╝")
+ fmt.Println()
+
+ ansi.Println(ansi.Yellow, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+ ansi.Println(ansi.BrightGreen, "ВСТРОЕННЫЕ КОМАНДЫ (BUSYBOX-STYLE):")
+ ansi.Println(ansi.Yellow, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+
+ commands := []struct {
+ name string
+ desc string
+ }{
+ {"exit", "Выход из оболочки"},
+ {"help", "Показать эту справку"},
+ {"ls [path]", "Вывести список файлов в директории"},
+ {"cd [dir]", "Сменить текущую директорию"},
+ {"pwd", "Показать текущую директорию"},
+ {"mkdir [-p]
", "Создать новую директорию"},
+ {"rm [-rf] ", "Удалить файл или директорию"},
+ {"touch ", "Создать файл или обновить время доступа"},
+ {"cat ", "Вывести содержимое файла"},
+ {"echo [text...]", "Вывести текст на экран"},
+ {"exec [args...]", "Выполнить внешнюю команду"},
+ }
+
+ for _, cmd := range commands {
+ fmt.Printf(" %-20s %s\n", ansi.Colorize(cmd.name, ansi.BrightWhite), cmd.desc)
+ }
+
+ fmt.Println()
+ ansi.Println(ansi.Yellow, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+ ansi.Println(ansi.BrightGreen, "ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:")
+ ansi.Println(ansi.Yellow, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("ls -la", ansi.BrightWhite), "Показать все файлы")
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("cd /tmp", ansi.BrightWhite), "Перейти в /tmp")
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("pwd", ansi.BrightWhite), "Показать текущий путь")
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("mkdir -p a/b/c", ansi.BrightWhite), "Создать вложенные директории")
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("rm -rf olddir", ansi.BrightWhite), "Удалить директорию рекурсивно")
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("cat file.txt", ansi.BrightWhite), "Показать содержимое файла")
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("echo Hello World", ansi.BrightWhite), "Вывести текст")
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("exec go version", ansi.BrightWhite), "Выполнить внешнюю команду")
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("ls | grep .go", ansi.BrightWhite), "Пайплайн")
+ fmt.Printf(" %-30s %s\n", ansi.Colorize("ls > files.txt", ansi.BrightWhite), "Перенаправление вывода")
+
+ fmt.Println()
+ ansi.Println(ansi.Yellow, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+
+ return nil
+}
+
+// cmdLs обрабатывает команду ls (стиль busybox)
+func (s *Shell) cmdLs(args []string) ([]byte, error) {
+ path := "."
+ showAll := false
+ longFormat := false
+
+ // Парсим аргументы
+ for _, arg := range args {
+ if arg == "-a" || arg == "--all" {
+ showAll = true
+ } else if arg == "-l" {
+ longFormat = true
+ } else if !strings.HasPrefix(arg, "-") {
+ path = arg
+ }
+ }
+
+ dir, err := os.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer dir.Close()
+
+ entries, err := dir.Readdir(-1)
+ if err != nil {
+ return nil, err
+ }
+
+ var output strings.Builder
+
+ for _, entry := range entries {
+ name := entry.Name()
+
+ // Пропускаем скрытые файлы если не указан -a
+ if !showAll && strings.HasPrefix(name, ".") {
+ continue
+ }
+
+ if longFormat {
+ // Формат: права ссылки владелец группа размер дата имя
+ perms := entry.Mode().String()
+ nlink := 1 // В Go сложно получить количество жестких ссылок
+ uid := fmt.Sprintf("%d", entry.Sys() != nil) // Упрощённо
+ gid := "users"
+ size := entry.Size()
+ modTime := entry.ModTime().Format("Jan _2 15:04")
+
+ if entry.IsDir() {
+ name = name + "/"
+ } else if entry.Mode()&os.ModeSymlink != 0 {
+ // Для симлинков пытаемся прочитать цель
+ if target, err := os.Readlink(filepath.Join(path, entry.Name())); err == nil {
+ name = name + " -> " + target
+ }
+ }
+
+ fmt.Fprintf(&output, "%s %3d %-8s %-8s %8d %s %s\n",
+ perms, nlink, uid, gid, size, modTime, name)
+ } else {
+ if entry.IsDir() {
+ name = name + "/"
+ }
+ fmt.Fprint(&output, name, "\n")
+ }
+ }
+
+ return []byte(output.String()), nil
+}
+
+// cmdCd обрабатывает команду cd
+func (s *Shell) cmdCd(args []string) error {
+ path := s.GetEnv("HOME")
+ if len(args) > 0 {
+ path = args[0]
+ }
+
+ if path == "~" {
+ path = s.GetEnv("HOME")
+ }
+
+ if err := os.Chdir(path); err != nil {
+ return err
+ }
+
+ pwd, err := os.Getwd()
+ if err == nil {
+ s.SetEnv("PWD", pwd)
+ }
+
+ return nil
+}
+
+// cmdPwd обрабатывает команду pwd
+func (s *Shell) cmdPwd(args []string) ([]byte, error) {
+ dir, err := os.Getwd()
+ if err != nil {
+ return nil, err
+ }
+ return []byte(dir + "\n"), nil
+}
+
+// cmdMkdir обрабатывает команду mkdir (с поддержкой -p)
+func (s *Shell) cmdMkdir(args []string) error {
+ if len(args) == 0 {
+ return fmt.Errorf("требуется имя директории")
+ }
+
+ createParents := false
+ var dirs []string
+
+ for _, arg := range args {
+ if arg == "-p" || arg == "--parents" {
+ createParents = true
+ } else if !strings.HasPrefix(arg, "-") {
+ dirs = append(dirs, arg)
+ }
+ }
+
+ for _, dir := range dirs {
+ var err error
+ if createParents {
+ err = os.MkdirAll(dir, 0755)
+ } else {
+ err = os.Mkdir(dir, 0755)
+ }
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// cmdRm обрабатывает команду rm (с поддержкой -r и -f)
+func (s *Shell) cmdRm(args []string) error {
+ if len(args) == 0 {
+ return fmt.Errorf("требуется имя файла")
+ }
+
+ recursive := false
+ force := false
+ var targets []string
+
+ for _, arg := range args {
+ switch arg {
+ case "-r", "-R", "--recursive":
+ recursive = true
+ case "-f", "--force":
+ force = true
+ default:
+ if !strings.HasPrefix(arg, "-") {
+ targets = append(targets, arg)
+ }
+ }
+ }
+
+ for _, target := range targets {
+ info, err := os.Stat(target)
+ if err != nil {
+ if !force {
+ return err
+ }
+ continue
+ }
+
+ if info.IsDir() && !recursive {
+ return fmt.Errorf("'%s' является директорией, используйте -r для удаления", target)
+ }
+
+ if err := os.RemoveAll(target); err != nil && !force {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// cmdTouch обрабатывает команду touch
+func (s *Shell) cmdTouch(args []string) error {
+ if len(args) == 0 {
+ return fmt.Errorf("требуется имя файла")
+ }
+
+ now := time.Now()
+
+ for _, filename := range args {
+ if strings.HasPrefix(filename, "-") {
+ continue
+ }
+
+ file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
+ if err != nil {
+ return err
+ }
+ file.Close()
+
+ if err := os.Chtimes(filename, now, now); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// cmdCat обрабатывает команду cat (конкатенация файлов)
+func (s *Shell) cmdCat(args []string) ([]byte, error) {
+ if len(args) == 0 {
+ // Читаем из stdin
+ info, err := os.Stdin.Stat()
+ if err != nil {
+ return nil, err
+ }
+
+ if info.Mode()&os.ModeCharDevice != 0 {
+ return nil, fmt.Errorf("ожидается файл или stdin")
+ }
+
+ reader := bufio.NewReader(os.Stdin)
+ var output strings.Builder
+ for {
+ line, err := reader.ReadString('\n')
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+ output.WriteString(line)
+ }
+ return []byte(output.String()), nil
+ }
+
+ var output strings.Builder
+
+ for _, filename := range args {
+ if strings.HasPrefix(filename, "-") {
+ continue
+ }
+
+ data, err := os.ReadFile(filename)
+ if err != nil {
+ return nil, fmt.Errorf("ошибка чтения '%s': %v", filename, err)
+ }
+
+ output.Write(data)
+ if len(data) > 0 && data[len(data)-1] != '\n' {
+ output.WriteByte('\n')
+ }
+ }
+
+ return []byte(output.String()), nil
+}
+
+// cmdEcho обрабатывает команду echo
+func (s *Shell) cmdEcho(args []string) ([]byte, error) {
+ newline := true
+ startIdx := 0
+
+ if len(args) > 0 && args[0] == "-n" {
+ newline = false
+ startIdx = 1
+ }
+
+ var output strings.Builder
+ for i := startIdx; i < len(args); i++ {
+ if i > startIdx {
+ output.WriteByte(' ')
+ }
+ output.WriteString(args[i])
+ }
+
+ if newline {
+ output.WriteByte('\n')
+ }
+
+ return []byte(output.String()), nil
+}